Clojure中的常量定义

时间:2012-02-07 14:08:58

标签: macros clojure

我正在尝试定义一个宏来定义在Clojure 1.3中添加的编译时常量语法:

  

== 2.14 ^:const defs ==

     

^:const允许您使用更快的参考命名原始值。

     

(def constants {:pi 3.14:e 2.71})

     

(def ^:const pi(:pi constants))(def ^:const e(:e constants))

     

查找的开销:e和:地图中的pi发生在编译时   时间,因为(:pi常数)和(:e常数)在它们的时候进行评估   父母def表格被评估。

基本上我想要(def ^:const ... ...)左右的语法糖,所以我试着这样做:

(defmacro defconst [const-name const-val]
  `(def ^:const ~const-name ~const-val))

但这不起作用:

user=> (macroexpand '(defconst pi 3.14))
(def pi 3.14)

从我收集的内容来看,#^<...>元快捷方式是一个读取器宏,并且要定义一个向某些内容添加元数据的宏,应该使用(with-meta ...)

我没有找到关于^:const的任何文件。这个语法结构是否甚至可以创建某种元数据?以下示例未显示任何内容:

user=> (def ^:const pi 3.14)
#'user/pi
user=> (meta pi)
nil

1 个答案:

答案 0 :(得分:10)

第一个问题是您正在检查3.14的元数据。使用(meta (var pi))查看pi的元数据。如果您这样做,您会看到它包含:const true

(defmacro defconst [const-name const-val]
  `(def
    ~(with-meta const-name
       (assoc (meta const-name) :const true))
    ~const-val))

准确地再现了^:const的元数据和性能(代码是根据defn-的来源改编的。)