Dom*_*riš 5 lisp common-lisp multiple-value let
最近,我经常嵌套几个返回多个值的函数。然而,与let
允许将这些调用优雅地写成一个大语句的 不同,我总是以大量缩进结束。
我的问题是:有几个多值函数,例如
(defun return-1-and-2 ()
(values 1 2))
(defun return-3-and-4 ()
(values 3 4))
Run Code Online (Sandbox Code Playgroud)
是否有可能达到与
(multiple-value-bind (one two)
(return-1-and-2)
(multiple-value-bind (three four)
(return-3-and-4)
(list one two three four)))
Run Code Online (Sandbox Code Playgroud)
但写得更简洁 - 方式let
,即,类似
(multiple-value-bind (one two)
(return-1-and-2)
(multiple-value-bind (three four)
(return-3-and-4)
(list one two three four)))
Run Code Online (Sandbox Code Playgroud)
?
图书馆中可能有类似的结构。
请注意,它更类似于let*
,而不是let
,因为范围是嵌套的。
一个人可以写一个宏。例如:
(defmacro multiple-value-let* ((&rest bindings) &body body)
"Sets the scope for several ((var-0 ... var-n) form)
binding clauses, using the multiple return values of the form."
(if (null bindings)
`(progn ,@body)
(destructuring-bind (((&rest vars) form) &rest rest-bindings)
bindings
`(multiple-value-bind ,vars
,form
(multiple-value-let* ,rest-bindings
,@body)))))
Run Code Online (Sandbox Code Playgroud)
例子:
CL-USER 33 > (walker:walk-form
'(multiple-value-let* (((one two) (return-1-and-2))
((three four) (return-3-and-4)))
(list one two three four)))
(MULTIPLE-VALUE-BIND (ONE TWO)
(RETURN-1-AND-2)
(MULTIPLE-VALUE-BIND (THREE FOUR)
(RETURN-3-AND-4)
(PROGN (LIST ONE TWO THREE FOUR))))
Run Code Online (Sandbox Code Playgroud)
我越来越喜欢这个库let-plus
,它提供了一个let+
具有此选项(以及其他选项)的宏:
(let+ (((&values one two) (return-1-and-2))\n ((&values three four) (return-3-and-4))\n (foo (bar)) ; other examples\n (#(a b c) (some-vector))) ;\n #| body\xe2\x80\xa6 |#)\n
Run Code Online (Sandbox Code Playgroud)\n
在塞拉皮姆,mvlet*
:
展开一系列嵌套的多值绑定表单。
(mvlet* ((minutes seconds (truncate seconds 60))
(hours minutes (truncate minutes 60))
(days hours (truncate hours 24)))
(declare ((integer 0 *) days hours minutes seconds))
(fmt "~d day~:p, ~d hour~:p, ~d minute~:p, ~d second~:p"
days hours minutes seconds))
Run Code Online (Sandbox Code Playgroud)
https://github.com/ruricolist/serapeum/blob/master/REFERENCE.md#mvlet-rest-bindings-body-body