最近,我经常嵌套几个返回多个值的函数。但是,与let
我允许将这些调用优雅地写入一个大语句不同,我总是以很多缩进结尾。
我的问题是:具有多个多值函数,例如
(defun return-1-and-2 ()
(values 1 2))
(defun return-3-and-4 ()
(values 3 4))
是否有可能达到与
(multiple-value-bind (one two)
(return-1-and-2)
(multiple-value-bind (three four)
(return-3-and-4)
(list one two three four)))
但写得更简洁let
一点,例如
(multiple-let (((one two) (return-1-and-2))
((three four) (return-3-and-4)))
(list one two three four))
?
库中可能有类似的构造。
请注意,由于作用域是嵌套的,因此它更类似于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)))))
例:
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))))
感谢您提供的宏以及
let*
类推。您是否有可能在第二个列表中输入错字,multiple-let*
而不是multiple-value-let*
?@DominikMokriš:很好,改变了。