Skip to content

Commit

Permalink
Introduce -defun
Browse files Browse the repository at this point in the history
- I used `-lambda` as a base, tried several versions with extracting the common
code but neither of them made the code more readable(IMO).

- Removed the restrictions against doing `(-lambda () ...)` which does not seem
to needed.
  • Loading branch information
yyoncho committed May 18, 2020
1 parent fe9bbc2 commit 243d313
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
37 changes: 33 additions & 4 deletions dash.el
Expand Up @@ -2146,7 +2146,7 @@ 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 normal `lambda', so there is no performance
penalty.
See `-let' for the description of destructuring mechanism."
Expand All @@ -2156,8 +2156,6 @@ See `-let' for the description of destructuring mechanism."
[&optional ("interactive" interactive)]
def-body)))
(cond
((not (consp match-form))
(signal 'wrong-type-argument "match-form must be a list"))
;; no destructuring, so just return regular lambda to make things faster
((-all? 'symbolp match-form)
`(lambda ,match-form ,@body))
Expand All @@ -2166,7 +2164,38 @@ See `-let' for the description of destructuring mechanism."
;; 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 (defun-name match-form &rest body)
"Return a `defun' DEFUN-NAME 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 normal `defun', so there is no performance
penalty.
See `-let' for the description of destructuring mechanism."
(declare (doc-string 3) (indent defun)
(debug (&define sexp
[&optional stringp]
[&optional ("interactive" interactive)]
def-body)))
(cond
;; no destructuring, so just return regular defun to make things faster
((-all? 'symbolp match-form)
`(defun ,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.
`(defun ,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))

(-map #'dash-plus '((1 2) (3 4) (5 6)))) => '(3 7 11)

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

(-map 'a+b '((:a 1 :b 2) (:a 3 :b 4) (:a 5 :b 6)))) => '(3 7 11))

(defexamples -setq
(progn (-setq a 1) a) => 1
(progn (-setq (a b) (list 1 2)) (list a b)) => '(1 2)
Expand Down

0 comments on commit 243d313

Please sign in to comment.