如何解决Common Lisp:如果已经传递给我,如何传递关键字参数
我一次又一次地发现自己的情况是,函数A需要调用带有或不带有关键字参数的函数B,这取决于是否已将关键字参数提供给功能A。
也许愚蠢的MWE更容易理解:让我们问一个叫汤米的男孩,他在学校的日子过得怎么样:
(defun answer (&key (math "boring" math-tested?)
(physics "heavy" physics-tested?))
(if math-tested?
(if physics-tested?
(format t "I got an ~A from math and a ~A from physics!" math physics)
(format t "I got an ~A from math." math))
(if physics-tested?
(format t "I got an ~A from physics." physics)
(format t "Math was ~A and physics was ~A." math physics))))
(defun father-son-talk (&key (math nil math-tested?)
(physics nil physics-tested?))
(format t "Hello Tommy,how was school today?~%")
(cond ((and math-tested? physics-tested?)
(answer :math math :physics physics))
(math-tested?
(answer :math math))
(physics-tested?
(answer :physics physics))
(t (answer))))
这可以按预期工作,但由于以下几个原因而令人讨厌:
-
对
answer
的调用基本上是重复的。如果answer
除了关键字之外还有几个普通的参数,在这四种情况下,我都必须格外小心。更糟糕的是维护这种东西。 -
如果父亲和儿子有不同的默认参数(可能会想写一个
(answer :math math :physics physics)
,则很容易引起进一步的困惑。
问题:假设answer
是我必须遵循的接口的一部分,如何简化father-son-talk
?理想情况下,我想要类似的东西
(defun father-son-talk (&key (math nil math-tested?)
(physics nil physics-tested?))
(format t "Hello Tommy,how was school today?~%")
(answer :math (math math-tested?) :physics (physics physics-tested?)))
解决方法
对此的常见解决方案是apply
:
(defun father-son-talk (&rest all-options &key math physics)
(declare (ignore math physics))
(format t "Hello Tommy,how was school today?~%")
(apply #'answer all-options))
如果father-son-talk
本身根本不需要关键字参数,则可以进一步简化
(defun father-son-talk (&rest all-options)
(format t "Hello Tommy,how was school today?~%")
(apply #'answer all-options))
使用这样的函数可以做的一个不错的技巧是说您确实想要关键字参数,并且您接受 any 关键字参数,然后将它们传递给实现功能:
(defun father-son-talk (&rest all-options &key &allow-other-keys)
(format t "Hello Tommy,how was school today?~%")
(apply #'answer all-options))
这与以前的版本类似,不同之处在于,例如(father-son-talk 1)
现在是错误的:它的参数必须全部是关键字参数。您想要哪个取决于answer
是否可能需要非关键字参数,因此两者都可能很有趣。
还有一个很好的例子,一个函数本身想要关键字参数,但希望集合是可扩展的:该函数获取的单个&rest
参数实际上是一个属性列表,因此您可以执行以下操作这个:
(defun foo (&rest plist &key &allow-other-keys)
...
(getf ':x plist 1) ...)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。