能否将函数作为LISP列表元素?如何实现闰年动态计算二月天数?
LISP 问题解答
1. 能否将函数作为LISP列表的元素?
当然可以。LISP中函数是第一类对象,你可以直接将函数对象(通过#'或function操作符引用)作为列表的元素存储。需要使用时,通过funcall或apply调用该函数对象即可。
2. 动态调整二月天数的日期映射列表实现
问题分析
你尝试的写法存在两个核心问题:
#'(if ...)是错误语法:#'用于引用函数或lambda表达式,但if是特殊运算符而非函数,这种写法会被解析为不完整的函数引用,导致返回未完成的表达式片段。- 即便写法正确,列表中存储的是函数对象,直接用
(nth 2 *daymap*)只能拿到函数本身,不会自动执行计算。
另外,你原有的闰年判断逻辑不完整——标准闰年规则是:能被4整除但不能被100整除,或能被400整除的年份才是闰年。
解决方法
下面提供几种可行的实现方案:
方案1:列表存储lambda函数,调用时执行
将二月的天数计算逻辑封装为lambda函数存入列表,获取时通过funcall执行函数得到结果:
(defparameter *year* 1900) (defparameter *daymap* '(0 31 #'(lambda () (if (and (= 0 (mod *year* 4)) (or (/= 0 (mod *year* 100)) (= 0 (mod *year* 400)))) 29 28)) 31 30 31 30 31 31 30 31 30 31)) ;; 使用方式 (funcall (nth 2 *daymap*))
方案2:用函数替代列表(推荐)
如果不需要严格使用列表结构,直接定义一个函数来返回对应月份的天数会更直观,避免手动调用函数对象的麻烦:
(defparameter *year* 1900) (defun get-month-days (month) (case month (2 (if (and (= 0 (mod *year* 4)) (or (/= 0 (mod *year* 100)) (= 0 (mod *year* 400)))) 29 28)) (1 31) (3 31) (4 30) (5 31) (6 30) (7 31) (8 31) (9 30) (10 31) (11 30) (12 31) (0 0))) ;; 使用方式 (get-month-days 2)
方案3:列表加自定义访问函数
如果必须保留列表结构,可以在列表中用标记指代需要计算的月份,再封装一个访问函数处理逻辑:
(defparameter *year* 1900) (defparameter *daymap* '(0 31 :leap-month 31 30 31 30 31 31 30 31 30 31)) (defun get-month-days (month) (let ((value (nth month *daymap*))) (if (eq value :leap-month) (if (and (= 0 (mod *year* 4)) (or (/= 0 (mod *year* 100)) (= 0 (mod *year* 400)))) 29 28) value))) ;; 使用方式 (get-month-days 2)
内容的提问来源于stack exchange,提问作者owisco
相关产品推荐
相关产品推荐

