lisp - 在 Common Lisp 中构建动态 COND 子句
问题描述
我想知道是否可以从像(伪代码)这样的循环中动态构建 COND 子句:
(defvar current-state 1)
(defmacro mymacro ()
(cond
`(loop (state . callback) in possible-states
do ((eq current-state ,state)
(funcall ,callback)))))
LOOP 将从列表中构建子句并生成如下内容:
(cond
((eq current-state 1)
(funcall func-1))
((eq current-state 2)
(funcall func-2))
((eq current-state 3)
(funcall func-3)))
解决方案
宏在编译时扩展,因此您的possible-states
变量必须是编译时常量。如果不是这种情况(或者如果你对我上面的意思不是很清楚),你不应该在这里使用宏。
改用函数:
(funcall (cdr (find current-state possible-states :key #'car :test #'eq)))
或者
(funcall (cdr (assoc current-state possible-states :test #'eq)))
或者,更好的是,使您possible-states
的哈希表而不是关联列表:
(funcall (gethash current-state possible-states))
然而,如果你possible-states
是一个编译时间常数,你确实可以使用一个宏,除了你可能想要使用
case
而不是
cond
:
(defmacro state-dispatch (state)
`(case ,state
,@(mapcar (lambda (cell)
`((,(car cell)) (,(cdr cell))))
possible-states)))
(defparameter possible-states '((1 . foo) (2 . bar)))
(macroexpand-1 '(state-dispatch mystate))
==> (CASE MYSTATE ((1) (FOO)) ((2) (BAR))) ; T
请注意,从速度的角度来看,该gethash
版本可能与宏版本相同(至少不慢)。
推荐阅读
- reactjs - 错误格式的钩子获取错误“效果函数不得返回除函数之外的任何内容......”
- javascript - 使用 Angular 7 同步水平滚动
- java - 表单中的 ModelAttribute 无法与对象绑定(Spring MVC)
- ios - 如何实现顶部带有标题的水平滚动集合视图?
- apache-spark - Pyspark - 计算新项目的长度
- javascript - 如何防止 VueJs 在 DOM 完全挂载之前更新数据
- spring-boot - Kubernetes 部署成功,但没有显示更新的内容
- apache-spark - 当底层文件发生变化时,PySpark 应该刷新视图还是源表?
- python - 在 Python Docker API 中实现“docker rmi”
- java - 如何为许多作者和许多读者(线程)添加和删除 HashMap?