考虑创建日期库的示例。我们可能有一个列表,将月份索引映射到该月的天数:
(defparameter *daymap* '(0 31 28 31 30 31 30 31 31 30 31 30 31))
假设我们还有一个跟踪一年的全局变量:
(defvar *year* 1900)
有没有办法定义
*daymap*
列表,以便 `(nth 2 daymap) 在闰年计算为 29?
我已经尝试了以下(和类似的),但没有成功:
(defparameter *daymap* '(0 31 #'(if (= 0 (mod *year* 4)) 28 29) 31 30 31 30 31 31 30 31 30 31))
在 REPL 中输入
(nth 2 *daymap*)
计算结果为:“#'(if (= 0 (mod *year* 4))
”而不是 28
或 29
。
可以将函数嵌入为列表元素:函数是一流的。然而
nth
只获取某个列表的第 n 个元素。如果该元素是一个函数,那么该值就是一个函数:它不会神奇地为您调用它。
但是你的例子很混乱。
#'x
读作 (function x)
,因此 '(1 2 #'(if ...) ...)
读作 '(1 2 (function (if ...))'
。这段数据没有任何功能,而是一个以 function
开头的列表。
如果要将函数嵌入到列表中,您需要确保匿名函数的语法正确,并且列表不能是文字数据。比如说
(defparameter *daymap*
`(0
31
,(lambda () (if (= 0 (mod *year* 4)) 28 29))
31 30 31 30 31 31 30 31 30 31))
现在您可以轻松地在
nth
周围写一些垫片来执行您想要的操作:
(defun nth/call (n list)
(let ((it (nth n list)))
(if (functionp it)
(funcall it)
it)))
甚至
(defun nth/force (n list)
;; MUNGE
(do ((it (nth n list)
(if (functionp it) (funcall it) it)))
((not (functionp it)) it)))