You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在plist循环中创建定时器?Lisp代码类型错误排查

问题分析与解决

核心原因

sb-ext:make-timer的第一个参数要求是函数对象或者符号,你传入的(print "first")是一个表达式(列表),不属于要求的类型,因此触发类型错误。而硬编码的(lambda () ...)是一个匿名函数对象,符合参数要求,所以能正常执行。

解决方案

有两种常见的修正方式:

方式1:用eval执行传入的表达式

将每个待执行的表达式包装进无参lambda,通过eval执行:

(defun run-timeline (timeline)
  "Timeline is a plist with alternating timecodes and code to execute"
  (alexandria:doplist (time form timeline)
    (sb-ext:schedule-timer
     (sb-ext:make-timer (lambda ()
                          (eval form))
                        :thread t)
     time)))

(run-timeline '(0 (print "first")
                2 (print "second")))

这种方式保持了调用时的简洁性,但要注意eval会在全局环境中执行代码,若表达式依赖词法作用域内的变量,可能无法正确引用。

方式2:传入函数对象而非表达式

调整调用方式,直接传入lambda函数对象,函数内部无需eval:

(defun run-timeline (timeline)
  "Timeline is a plist with alternating timecodes and code to execute"
  (alexandria:doplist (time form timeline)
    (sb-ext:schedule-timer
     (sb-ext:make-timer form
                        :thread t)
     time)))

(run-timeline '(0 (lambda () (print "first"))
                2 (lambda () (print "second"))))

这种方式更符合Lisp函数式编程的风格,避免了eval的潜在问题,适合处理包含闭包变量的复杂逻辑。


内容的提问来源于stack exchange,提问作者kflak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:17:34