Quantcast
Channel: How to bind var's name and value in the clojure macro? - Stack Overflow
Viewing all articles
Browse latest Browse all 4

Answer by Taylor Wood for How to bind var's name and value in the clojure macro?

$
0
0

It looks like you want to write a file of delimited values using binding names and their values from inside a let. Macros transform code during compilation and so they cannot know the run-time values that the symbols you pass are bound to. You can use a macro to emit code that will be evaluated at run-time:

(defmacro to-rows [& args]  (let [names (mapv name args)]    `(cons ~names (map vector ~@args))))    (defn get-stuff []  (let [nums [1 2 3]        chars [\a \b \c]        bools [true false nil]]    (to-rows nums chars bools)))(get-stuff)=> (["nums""chars""bools"]    [1 \a true]    [2 \b false]    [3 \c nil])

Alternatively you could produce a hash map per row:

(defmacro to-rows [& args]  (let [names (mapv name args)]    `(map (fn [& vs#] (zipmap ~names vs#)) ~@args)))=> ({"nums" 1, "chars" \a, "bools" true}    {"nums" 2, "chars" \b, "bools" false}    {"nums" 3, "chars" \c, "bools" nil})

You would then need to write that out to a file, either using data.csv or similar code.

To see what to-rows expands to, you can use macroexpand. This is the code being generated at compile-time that will be evaluated at run-time. It does the work of getting the symbol names at compile-time, but emits code that will work on their bound values at run-time.

(macroexpand '(to-rows x y z))=> (clojure.core/cons ["x""y""z"] (clojure.core/map clojure.core/vector x y z))

As an aside, I'm assuming you aren't typing thousands of literal values into let bindings. I think this answers the question as asked but there could likely be a more direct approach than this.


Viewing all articles
Browse latest Browse all 4

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>