我正在尝试使用clojure宏,并想知道我可能做错了什么?
我有一个简单的例子,试图根据地图动态创建函数.
例如:
(def units {:cm 100
:mm 1000
:m 1
:km 1/1000})
(defn m-to-unit-helper [[k v]]
(let [f (symbol (str "to-" (name k)))]
`(defn ~f [m#] (* ~v m#))))
(defmacro m-to-units [units-map]
(let [funcs (map m-to-unit-helper units-map)]
`(do ~@funcs)))
; complains with: Don't know how to create ISeq from: clojure.lang.Symbol
(m-to-units units)
; To try and debug
(defn debug [units-map]
(let [funcs (map m-to-unit-helper units-map)]
(clojure.pprint/pprint `(do ~@funcs))))
; see below
(debug units)
Run Code Online (Sandbox Code Playgroud)
宏不起作用,但调试输出看起来应该创建正确的结构:
(do
(clojure.core/defn
to-mm
[m__32709__auto__]
(clojure.core/* 1000 m__32709__auto__))
(clojure.core/defn
to-m
[m__32709__auto__]
(clojure.core/* 1 m__32709__auto__))
(clojure.core/defn
to-cm
[m__32709__auto__]
(clojure.core/* 100 m__32709__auto__))
(clojure.core/defn
to-km
[m__32709__auto__]
(clojure.core/* 1/1000 m__32709__auto__)))
Run Code Online (Sandbox Code Playgroud)
任何建议将不胜感激.谢谢.
m-to-units是一个宏,这意味着每个参数都将被传递而不被评估,这意味着宏内部的值units-map实际上是符号units.
现在,如果您直接传递地图,它将按预期工作:
(m-to-units {:mm 1000, :m 1, :cm 100, :km 1/1000})
;; => #'user/to-km
(to-cm 10)
;; => 1000
Run Code Online (Sandbox Code Playgroud)
您可以做什么 - 虽然我认为这是不好的做法 - eval用于获取单位地图的实际价值,无论它是作为地图还是通过符号传递:
(defmacro m-to-units
[units-map]
(let [funcs (map m-to-unit-helper (eval units-map))]
`(do ~@funcs)))
(m-to-units units)
;; => #'user/to-km
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
804 次 |
| 最近记录: |