clojure - clojurescript 中的宏 - 无法正确扩展

标签 clojure clojurescript lisp-macros

我在 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(应用 HashMap (范围 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

关于clojure - clojurescript 中的宏 - 无法正确扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58982065/

相关文章:

java - Clojail 不会在 Clojure 中抛出安全异常

clojure - 使用交换!在嵌套 map 上

algorithm - 反序列化广度优先树

clojure - Clojurescript/Clojure 中服务器和客户端之间的代码共享

jquery - 如何在 Clojurescript 中使用 jayq 从事件中获取数据?

macros - scheme中如何用双引号写LISP宏

common-lisp - setf 如何在幕后工作?

javascript - 使用 Clojure 向 JavaScript 添加语法

clojure - 绑定(bind)函数如何与 core.async 一起使用?

time - 使用宏定义计算 10 个复活节相关日期的函数