Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce -defun #336

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 41 additions & 7 deletions dash.el
Expand Up @@ -2146,27 +2146,61 @@ such that:
(-lambda (x y ...) body)

has the usual semantics of `lambda'. Furthermore, these get
translated into normal lambda, so there is no performance
translated into a normal `lambda', so there is no performance
penalty.

See `-let' for the description of destructuring mechanism."
See `-let' for a description of the destructuring mechanism."
(declare (doc-string 2) (indent defun)
(debug (&define sexp
[&optional stringp]
[&optional ("interactive" interactive)]
def-body)))
(cond
((not (consp match-form))
(signal 'wrong-type-argument "match-form must be a list"))
yyoncho marked this conversation as resolved.
Show resolved Hide resolved
((nlistp match-form)
(signal 'wrong-type-argument (list #'listp match-form)))
;; no destructuring, so just return regular lambda to make things faster
((-all? 'symbolp match-form)
((-all? #'symbolp match-form)
`(lambda ,match-form ,@body))
(t
(let* ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index))) match-form)))
(let ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index))) match-form)))
;; TODO: because inputs to the lambda are evaluated only once,
;; -let* need not to create the extra bindings to ensure that.
;; We should find a way to optimize that. Not critical however.
`(lambda ,(--map (cadr it) inputs)
`(lambda ,(-map #'cadr inputs)
(-let* ,inputs ,@body))))))

(defmacro -defun (name match-form &rest body)
"Define NAME as a function which destructures its input as MATCH-FORM and executes BODY.

Note that you have to enclose the MATCH-FORM in a pair of parens,
such that:

(-defun (x) body)
(-defun (x y ...) body)

has the usual semantics of `defun'. Furthermore, these get
translated into a normal `defun', so there is no performance
penalty.

See `-let' for a description of the destructuring mechanism."
(declare (doc-string 3) (indent defun)
(debug (&define name sexp
[&optional stringp]
[&optional ("declare" &rest sexp)]
[&optional ("interactive" interactive)]
def-body)))
yyoncho marked this conversation as resolved.
Show resolved Hide resolved
(cond
((nlistp match-form)
(signal 'wrong-type-argument (list #'listp match-form)))
;; no destructuring, so just return regular defun to make things faster
((-all? #'symbolp match-form)
`(defun ,name ,match-form ,@body))
(t
(let ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index))) match-form)))
;; TODO: because inputs to the defun are evaluated only once,
;; -let* need not to create the extra bindings to ensure that.
;; We should find a way to optimize that. Not critical however.
yyoncho marked this conversation as resolved.
Show resolved Hide resolved
yyoncho marked this conversation as resolved.
Show resolved Hide resolved
`(defun ,name ,(-map #'cadr inputs)
(-let* ,inputs ,@body))))))

(defmacro -setq (&rest forms)
Expand Down
13 changes: 13 additions & 0 deletions dev/examples.el
Expand Up @@ -1259,6 +1259,19 @@ new list."
(funcall (-lambda (a b) (+ a b)) 1 2) => 3
(funcall (-lambda (a (b c)) (+ a b c)) 1 (list 2 3)) => 6)

(defexamples -defun
(progn
(-defun dash-plus ((x y))
(+ x y))

(dash-plus '(1 2))) => 3

(progn
(-defun a+b ((&plist :a a :b b))
(+ a b))

(a+b '(:a 1 :b 2))) => 3)

yyoncho marked this conversation as resolved.
Show resolved Hide resolved
(defexamples -setq
(progn (-setq a 1) a) => 1
(progn (-setq (a b) (list 1 2)) (list a b)) => '(1 2)
Expand Down