在宏中创建名称空间限定的函数名称

Chr*_*son 5 clojure

我有一堆函数可以映射到外部系统定义的某些代码:

(defn translate-from-ib-size-tick-field-code [val]
  (condp = val
    0 :bid-size
    3 :ask-size
    5 :last-size
    8 :volume))

(defn translate-to-ib-size-tick-field-code [val]
  (condp = val
    :bid-size 0
    :ask-size 3
    :last-size 5
    :volume 8))
Run Code Online (Sandbox Code Playgroud)

我想制作一个宏来删除重复:

#_ (translation-table size-tick-field-code
                      {:bid-size 0
                       :ask-size 3
                       :last-size 5
                       :volume 8})    
Run Code Online (Sandbox Code Playgroud)

我开始像这样的宏:

(defmacro translation-table [name & vals]
  `(defn ~(symbol (str "translate-to-ib-" name)) [val#]
     (get ~@vals val#)))
Run Code Online (Sandbox Code Playgroud)

结果函数体似乎正确,但函数名称错误:

re-actor.conversions> (macroexpand `(translation-table monkey {:a 1 :b 2}))
(def translate-to-ib-re-actor.conversions/monkey 
     (.withMeta (clojure.core/fn translate-to-ib-re-actor.conversions/monkey      
     ([val__10589__auto__] 
        (clojure.core/get {:a 1, :b 2} val__10589__auto__))) (.meta ...
Run Code Online (Sandbox Code Playgroud)

事实证明,我希望"translate-to-ib-"作为函数名称的一部分出现,而不是名称空间的前缀.

我怎么能用clojure宏做这个?如果我只是做错了并且由于某种原因不应该使用宏,请告诉我,但我也想知道如何创建这样的函数名称来提高我对clojure和宏的理解.谢谢!

Jus*_*mer 7

宏观问题有两个方面:

1)在引用传递给的表单时,您正在使用反引号macroexpand,该命名空间限定符号:

`(translation-table monkey {:a 1 :b 2})
=> (foo.bar/translation-table foo.bar/monkey {:a 1, :b 2})
Run Code Online (Sandbox Code Playgroud)

foo.bar你在哪里的名字空间.

2)您正在defn使用符号构造项目的名称name,当它符合名称空间时,将字符串化为"foo.bar/monkey".这是一个可行的版本:

(defmacro translation-table [tname & vals]
  `(defn ~(symbol (str "translate-to-ib-" (name tname))) [val#]
     (get ~@vals val#)))
Run Code Online (Sandbox Code Playgroud)

请注意,我们tname使用该name函数获取了没有命名空间部分的名称.

至于宏是否是正确的解决方案,可能不是:-)对于这样的简单案例,我可能只使用地图:

(def translate-from-ib-size-tick-field-code 
  {0 :bid-size
   3 :ask-size
   5 :last-size
   8 :volume})

;; swap keys & vals
(def translate-to-ib-size-tick-field-code
  (zipmap (vals translate-from-ib-size-tick-field-code)
          (keys translate-from-ib-size-tick-field-code)))

(translate-from-ib-size-tick-field-code 0)
=> :bid-size

(translate-to-ib-size-tick-field-code :bid-size)
=> 0
Run Code Online (Sandbox Code Playgroud)

如果速度至关重要,请查看case.