Alex028502
Alex028502

Reputation: 3814

macros in clojurescript - does not expand properly

I have created a macro in clojure

(ns macro-question.map)

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

in the clojure repl it works as expected

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

So I create a clojurescript module like this to try to use it:

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

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

and when I try that in the repl, I get this

$ 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.

meanwhile back in clojure, there is a clue why this might be

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

I can create macros that start with '( instead of (list. However, I want the map to be expanded at build time.

What is going on? And what do I have to do to get something like the following:

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

or what should I be doing to use this macro in clojurescript?

Upvotes: 2

Views: 295

Answers (2)

Alex028502
Alex028502

Reputation: 3814

You can just put 'get!!

(ns macro-question.map)

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

(https://stackoverflow.com/posts/58985564 is a better answer about why it happens, and a much better way to do it. This just shows a simple solution that only solves the immediate issue, that I realised right after I had asked the question)

Upvotes: 1

bfabry
bfabry

Reputation: 1904

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

Creates a list where the first position is the function object that the var get refers to. What you actually want to return is a list with the fully qualified symbol for get as the first position. Change your macro definition to

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

The reference guide for the reader is helpful here https://clojure.org/reference/reader

Upvotes: 1

Related Questions