繁体   English   中英

clojurescript 中的宏 - 无法正确展开

[英]macros in clojurescript - does not expand properly

我在 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 ) 开头的宏。但是,我希望在构建时扩展 map。

到底是怎么回事? 我该怎么做才能获得以下内容:

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

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

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

创建一个列表,其中第一个 position 是 var get引用的 function object。 您真正想要返回的是一个列表,其中包含get的完全限定符号作为第一个 position。 将您的宏定义更改为

(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

你可以把'get !!

(ns macro-question.map)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM