The macro was broken until now for anything other than list forms,
due to a mistake in quoting.  Use this as an opportunity to rethink
the macro's behavior in this case.  Instead of using funcall, which
is unusual for a macro, thread the value using ->.  Suggested by
Zach Shaftel <zshaftel@gmail.com>.

* dash.el (-doto): Rewrite in terms of ->.  Fix docstring.  Add
Edebug spec.
(--doto): Rename argument for consistency with -doto.  Expand
docstring.  Add Edebug spec.
* dev/examples.el (-doto): Test fixed behavior of -doto.

* README.md:
* dash.texi: Regenerate docs.

Fixes #333.
master
Basil L. Contovounesios 5 years ago
parent 8879c41d30
commit d983d4fea0
No known key found for this signature in database
GPG Key ID: 205AB54A5D5D8CFF
  1. 9
      README.md
  2. 25
      dash.el
  3. 9
      dash.texi
  4. 2
      dev/examples.el

@ -2650,12 +2650,13 @@ if `num` is less than 1.
#### -doto `(init &rest forms)`
Evaluate `init` and thread the result as the 2nd argument to other `forms`.
`init` is evaluated once. Its result is passed to `forms`, which are
then evaluated sequentially. Returns the target form.
Evaluate `init` and pass it as argument to `forms` with [`->`](#--x-optional-form-rest-more).
The `result` of evaluating `init` is threaded through each of `forms`
individually using [`->`](#--x-optional-form-rest-more), which see. The return value is `result`,
which `forms` may have modified by side effect.
```el
(-doto (list 1 2 3) (pop) (pop)) ;; => '(3)
(-doto (list 1 2 3) pop pop) ;; => '(3)
(-doto (cons 1 2) (setcar 3) (setcdr 4)) ;; => '(3 . 4)
(gethash 'k (--doto (make-hash-table) (puthash 'k 'v it))) ;; => 'v
```

@ -63,24 +63,23 @@
(!cdr ,l)))))
(defmacro -doto (init &rest forms)
"Evaluate INIT and thread the result as the 2nd argument to other FORMS.
INIT is evaluated once. Its result is passed to FORMS, which are
then evaluated sequentially. Returns the target form."
(declare (indent 1))
(let ((retval (make-symbol "value")))
"Evaluate INIT and pass it as argument to FORMS with `->'.
The RESULT of evaluating INIT is threaded through each of FORMS
individually using `->', which see. The return value is RESULT,
which FORMS may have modified by side effect."
(declare (debug (form body)) (indent 1))
(let ((retval (make-symbol "result")))
`(let ((,retval ,init))
,@(mapcar (lambda (form)
(if (listp form)
`(,(car form) ,retval ,@(cdr form))
`(funcall form ,retval)))
forms)
,@(mapcar (lambda (form) `(-> ,retval ,form)) forms)
,retval)))
(defmacro --doto (eval-initial-value &rest forms)
(defmacro --doto (init &rest forms)
"Anaphoric form of `-doto'.
This just evaluates INIT, binds the result to `it', evaluates
FORMS, and returns the final value of `it'.
Note: `it' need not be used in each form."
(declare (indent 1))
`(let ((it ,eval-initial-value))
(declare (debug (form body)) (indent 1))
`(let ((it ,init))
,@forms
it))

@ -4026,13 +4026,14 @@ if @var{num} is less than 1.
@anchor{-doto}
@defmac -doto (init &rest forms)
Evaluate @var{init} and thread the result as the 2nd argument to other @var{forms}.
@var{init} is evaluated once. Its result is passed to @var{forms}, which are
then evaluated sequentially. Returns the target form.
Evaluate @var{init} and pass it as argument to @var{forms} with @code{->} (@pxref{->}).
The @var{result} of evaluating @var{init} is threaded through each of @var{forms}
individually using @code{->} (@pxref{->}), which see. The return value is @var{result},
which @var{forms} may have modified by side effect.
@example
@group
(-doto (list 1 2 3) (pop) (pop))
(-doto (list 1 2 3) pop pop)
@result{} '(3)
@end group
@group

@ -1365,7 +1365,7 @@ consuming a list to produce a single value."
(let (s) (--dotimes 3 (push it s) (setq it -1)) s) => '(2 1 0))
(defexamples -doto
(-doto (list 1 2 3) (pop) (pop)) => '(3)
(-doto (list 1 2 3) pop pop) => '(3)
(-doto (cons 1 2) (setcar 3) (setcdr 4)) => '(3 . 4)
(gethash 'k (--doto (make-hash-table) (puthash 'k 'v it))) => 'v
(-doto (cons 1 2)) => '(1 . 2)))

Loading…
Cancel
Save