【问题标题】:macros in clojurescript - does not expand properlyclojurescript 中的宏 - 无法正确展开
【发布时间】:2020-03-17 19:22:19
【问题描述】:

我在 clojure 中创建了一个宏

(ns macro-question.map)

(defmacro lookup [key] (list get (apply hash-map (range 1 5)) key))

在 clojure repl 中它按预期工作

$ clj
Clojure 1.9.0
user=> (require 'macro-question.map)
nil
user=> (macro-question.map/lookup 1)
2

所以我创建了一个这样的 clojurescript 模块来尝试使用它:

(ns macro-question.core (:require-macros [macro-question.map]))

(defn lookup1 [] (macro-question.map/lookup 1))

当我在 repl 中尝试时,我得到了这个

$ clj -m cljs.main  --repl-env node
ClojureScript 1.10.520
cljs.user=> (require 'macro-question.core)
Execution error (ExceptionInfo) at cljs.compiler/fn (compiler.cljc:304).
failed compiling constant: clojure.core$get@3df1a1ac; clojure.core$get is not a valid ClojureScript constant.

同时回到 clojure,有一个线索为什么会这样

user=> (macroexpand '(macro-question.map/lookup 1))
(#object[clojure.core$get 0x101639ae "clojure.core$get@101639ae"] {1 2, 3 4} 1)

我可以创建以'( 而不是(list 开头的宏。但是,我希望在构建时扩展地图。

发生了什么事?我该怎么做才能获得以下内容:

user=> (macroexpand '(macro-question.map/lookup 1))
(get {1 2, 3 4} 1)

或者我应该怎么做才能在 clojurescript 中使用这个宏?

【问题讨论】:

    标签: clojure clojurescript lisp-macros


    【解决方案1】:

    你可以把'get!!

    (ns macro-question.map)
    
    (defmacro lookup [key] (list 'get (apply hash-map (range 1 5)) key))
    

    https://stackoverflow.com/posts/58985564 是关于它为什么会发生的更好答案,也是一种更好的方法。这只是显示了一个简单的解决方案,它只解决了当前的问题,我在提出问题后立即意识到)

    【讨论】:

    • 如果您只输入get,那么如果您的宏的使用者在其命名空间或词法范围中重新定义了get 以表示其他含义,那么您将获得该定义。如果您像我一样使用语法引用,那么您肯定会引用clojure.core/get,即定义宏的命名空间中可用的get。尝试用你的定义做(let [get nil] (lookup 1))
    • 是的 - 更新了我的答案以更清楚地反映这一点
    【解决方案2】:

    (list get (apply hash-map (range 1 5)) key)

    创建一个列表,其中第一个位置是 var get 引用的函数对象。您真正想要返回的是一个列表,其中get 的完全限定符号 作为第一个位置。将您的宏定义更改为

    (defmacro lookup [key] 
      `(get ~(apply hash-map (range 1 5)) ~key))
    
    (macroexpand '(lookup 1))
    => (clojure.core/get {1 2, 3 4} 1)
    

    读者参考指南在这里很有帮助https://clojure.org/reference/reader

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      相关资源
      最近更新 更多