【发布时间】:2021-02-15 23:25:30
【问题描述】:
我一次又一次地发现,函数 A 需要使用或不使用关键字参数来调用函数 B,这取决于是否已将此类关键字参数提供给函数 A。
也许一个愚蠢的 MWE 更容易理解:让我们问问一个叫 Tommy 的男孩,他在学校的一天过得怎么样:
(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?)))
【问题讨论】:
标签: common-lisp keyword-argument optional-arguments