追求4 4Clojure 问题178 -最佳手,我有一个用于将卡片值从字符转换为数字的方法:
(fn [ch]
(or
({\A 1} ch)
((zipmap "TJQK" (iterate inc 10)) ch)
(- (int ch) (int \0))))zipmap表达式是在每个调用上计算的,总是生成{\K 13, \Q 12, \J 11, \T 10}__。
如何使编译器只对其进行一次评估?
经过多次脑力的折腾,我想到了
(defmacro constant [exp] (eval exp))..。因此,包装zipmap调用:
(constant (zipmap "TJQK" (iterate inc 10)))我认为这相当于
(eval '(zipmap "TJQK" (iterate inc 10)))..。但不需要引用eval的话:
(eval (zipmap "TJQK" (iterate inc 10)))欢迎修改、评论和改进。
发布于 2014-04-02 14:23:17
您的constant宏将在这种特殊情况下工作,因为正在计算的表单只有解析为clojure.core和编译时文本中函数的符号。在其他情况下,您可能会遇到符号解析的问题,例如从函数参数中计算要在匿名函数中使用的本地常量。
更常见的方法是将对zipmap的调用移到fn表单之外。一个选项是使用zipmap将zipmap调用的结果存储在变量中,就像在(def my-const (zipmap "TJQK" (iterate inc 10)))中一样。
但是,在这种情况下,您要创建一个匿名函数,创建一个可全局访问的var可能会导致过度。因此,我建议将fn放入捕获常量值的let绑定中:
(let [face-cards (zipmap "TJQK" (iterate inc 10))]
(fn [ch]
(or
({\A 1} ch)
(face-cards ch)
(- (int ch) (int \0)))))编辑:如注释中所指出的,此解决方案将在加载时而不是在编译时计算常量值。我很难想出一个重要的场景,但值得指出的是,它的语义与您的方法略有不同。
https://stackoverflow.com/questions/22813713
复制相似问题