[英]Is there a way to use destructuring bind with &rest?
I have a function that uses &rest
which returns a list of the varying amount of args to the function.我有一个使用
&rest
的 function,它将不同数量的参数列表返回给 function。
I open break lists up with destructuring bind
(db).我用
destructuring bind
(db) 打开中断列表。 However, db is useful for when the number of variables are known.但是,当变量数量已知时,db 很有用。
What is the best way to break up an &rest
list where the number of values vary most of the time?什么是最好的方法来分解一个
&rest
列表,其中值的数量大部分时间都在变化?
Here's a simple example of Trivia for pattern matching:下面是用于模式匹配的Trivia的一个简单示例:
(defun foo (&rest rest)
(trivia:match rest
((list* a b c _)
(values :got-a-b-c a b c))))
CL-USER> (foo :a :b :c :and :foo)
:GOT-A-B-C
:A
:B
:C
list*
allows to pattern-match on a list of varying length. list*
允许在不同长度的列表上进行模式匹配。 More precisely:更确切地说:
Both
list
andlist*
patterns check if the object is of type list, has the same length and then matches the contents to the subpatterns.list
和list*
模式都检查 object 是否属于列表类型,是否具有相同的长度,然后将内容与子模式匹配。 list* also checks the elements against the subpatterns, however the last pattern is matched againstnthcdr
of the list.list* 还根据子模式检查元素,但是最后一个模式与列表的
nthcdr
匹配。
https://lispcookbook.github.io/cl-cookbook/pattern_matching.html https://lispcookbook.github.io/cl-cookbook/pattern_matching.html
If you don't know the number of things you wish to bind you can't possibly solve this problem because the number of variables is unknown until runtime.如果你不知道你希望绑定的东西的数量,你就不可能解决这个问题,因为变量的数量在运行时是未知的。
So the only possible case you can solve is where the number of elements in the list is constrained in some way: in particular it needs to have a maximum number of 'interesting' elements that you want to bind variables to at one time.因此,您可以解决的唯一可能情况是列表中的元素数量以某种方式受到限制:特别是它需要具有最大数量的“有趣”元素,您希望一次将变量绑定到这些元素。 In that case you can either use a matching macro of some kind, or if your requirements are simpler just use
destructuring-bind
:在这种情况下,您可以使用某种匹配的宏,或者如果您的要求更简单,只需使用
destructuring-bind
:
(defun foo (&rest args)
(destructuring-bind (&optional (a nil ap) (b nil bp) (c nil cp) &rest extras) args
(unless (null extras)
(error "too many args"))
... use AP, BP, CP to know if one, two or three arguments were
... provided, and A, B, C to know what they were.
...))
More generally you might want a matching macro.更一般地说,您可能需要一个匹配的宏。 Another answer has already mentioned Trivia, but
destructuring-match
provides a case
-like variant of destructuring-bind
:另一个答案已经提到了 Trivia,但
destructuring-match
提供了一个类似case
的destructuring-bind
变体:
(defun foo (&rest args)
(destructuring-match args
((a &optional (b 0))
(+ a b))
((a b c)
(+ a (- b c)))
(otherwise
(error "need between 1 and 3 arguments"))))
However the above version of foo
can actually be happily be dealt with by just destructuring-bind
:然而,上述版本的
foo
实际上可以通过destructuring-bind
轻松处理:
(defun foo (&rest args)
(destructuring-bind (a &optional (b 0) (c 0)) args
(+ a (- b c))))
The only difference here is that you don't get to control the error case.这里唯一的区别是您无法控制错误情况。
destructuring-match
is really intended for pulling apart much more complex structures in macros. destructuring-match
实际上是为了分解宏中更复杂的结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.