Clojure: Name of variables in a list - clojure

I have a something like this:
(def a "text")
(def b "text")
(def c nil)
(def d 8)
(def e "")
(def testlist (list a b c d e ))
Now, is there any way to get the string of the variable names? I assume a 'no' is the most likely answer.
name does not seem to work, as it only returns the value. Does the list only contain the values after def?
EDIT: What i forgot and that may be essential to this question: i can neither use eval nor can i use defmacro, both are not allowed (for safety etc. reasons). So, yeah...

you could use macro to do this (just for fun. i don't think it is a viable usecase at all)
user> (defmacro list+ [& syms]
`(with-meta (list ~#syms) {:vars (quote ~syms)}))
#'user/list+
user> (def testlist (list+ a b c d e))
#'user/testlist
user> (-> testlist meta :vars)
(a b c d e)
user> (defn nil-vals-names [data]
(for [[v name] (map vector data (-> data meta :vars))
:when (nil? v)]
name))
#'user/nil-vals-names
user> (nil-vals-names testlist)
(c)

You will not be able to get a string from the variable names since Clojure will evaluate them as soon as possible to produce the testlist
=> (def testlist (a b c d e ))
("text" "text" nil 8 "")
However, you can quote the list to retrieve the symbol associated to each variable name
=> (def testlist (quote (a b c d e ))) ;; equivalent to '(a b c d e ))
(a b c d e)
And then transform these symbols into strings with the str function
=> (map str testlist)
("a" "b" "c" "d" "e")
Later, you can eval this list to retrieve the value in the context of your namespace
=> (map eval testlist)
("text" "text" nil 8 "")
Note that using eval with an external input (e.g. read-line) can create a security risk in Clojure and other languages.
Moreover, the list has to be evaluated in the same namespace as its definition. Otherwise, Clojure will not be able to resolve the symbols.
=> (ns otherns)
=> (map eval user/testlist)
java.lang.RuntimeException: Unable to resolve symbol: a in this context
The best practice in most case would be to use macros

It's quite unclear what are you trying to achieve, bit still there is a possible way.
meta function take a reference and returns a map with :name field that holds a sting with the variable name:
user=> (def foo 42)
#'user/foo
user=> (meta #'foo)
{:line 1, :column 1,
:file "/some/tmp/file.clj",
:name foo,
:ns #namespace[user]}

Related

defmethod dispatch when varargs involved

I am trying to find a way to define a multi-method that (a) dispatches on multiple args and (b) allows methods to be specified that care only about some of the args (the compiler does not like the _ in the last method):
(defmulti whocares (fn [a1 a2] [(class a1)(class a2)]))
(defmethod whocares [String String] [s1 s2]
(println :s2 s1 s2))
(defmethod whocares [_ String] [any1 s2]
(println :_s any1 s2))
Compiler definitely does not like that _.
I know about the :default catch-all, but I need something more granular (on individual args).
In CL we would use t as the type that matches everything, but I do not see indication clojure has something for X such that (isa? whatever X) would always return true.
btw, I imagine there is a top to the Java class hierarchy, but I am trying to stay away from my library supporting only Java classes.
The simplest way would be to use java.lang.Object as your catch all type:
(defmulti whocares (fn [a b] [(class a) (class b)]))
(defmethod whocares [String String] [a b] (println "Two strings" a b))
(defmethod whocares [Object String] [a b] (println "Anything and string" a b))
(whocares "a" "b")
;; => "Two strings a b"
(whocares 1 "c")
;; => "Anything and string 1 c"
(whocares :a "c")
;; => "Anything and string :a c"
I am not sure why you don't want to use the top class of Java hierarchy. It's possible using derive to define your catch all dispatch value but you still need to make the Java's Object class a child of your custom catch all value:
(derive Object :whocares/any)
(defmulti whocares2 (fn [a b] [(class a) (class b)]))
(defmethod whocares2 [String String] [a b] (println "Two strings" a b))
(defmethod whocares2 [:whocares/any String] [a b] (println "Anything and string" a b))
(whocares2 "a" "b")
;; => "Two strings a b"
(whocares2 1 "c")
;; => "Anything and string 1 c"
(whocares2 :a "c")
;; => "Anything and string :a c"

Make vars constant for use in case statements in Clojure

In Clojure, is there a way to make a var constant such that it can be used in case statements?
e.g.
(def a 1)
(def b 2)
(let [x 1]
(case x
a :1
b :2
:none))
=> :none
I understand I can use something like cond or condp to get around this, but it would be nice if I could define something that does not require further evaluation so I could use case.
Related and answer stolen from it:
As the docstring tells you: No you cannot do this. You can use Chas Emericks macro and do this however:
(defmacro case+
"Same as case, but evaluates dispatch values, needed for referring to
class and def'ed constants as well as java.util.Enum instances."
[value & clauses]
(let [clauses (partition 2 2 nil clauses)
default (when (-> clauses last count (== 1))
(last clauses))
clauses (if default (drop-last clauses) clauses)
eval-dispatch (fn [d]
(if (list? d)
(map eval d)
(eval d)))]
`(case ~value
~#(concat (->> clauses
(map #(-> % first eval-dispatch (list (second %))))
(mapcat identity))
default))))
Thus:
(def ^:const a 1)
(def ^:const b 2)
(let [x 1]
(case+ x
a :1
b :2
:none))
=> :1
An alternative (which is nice since it's more powerful) is to use core.match's functionality. Though you can only match against local bindings:
(let [x 2
a a
b b]
(match x
a :1
b :2
:none))
=> :2
You can also use clojure.core/condp for the job:
(def a 1)
(def b 2)
(let [x 1]
(condp = x
a :1
b :2
:none))
#=> :1

What is meant by destructuring in Clojure?

I'm a Java and learning clojure.
What is exactly destructuring in clojure?
I can see this blog saying:
The simplest example of destructuring is assigning the values of a
vector.
user=> (def point [5 7])
#'user/point
user=> (let [[x y] point]
(println "x:" x "y:" y))
x: 5 y: 7
what he meant by assigning the values of a vector? Whats the real use of it?
Thanks in advance
point is a variable that contains a vector of values. [x y] is a vector of variable names.
When you assign point to [x y], destructuring means that the variables each get assigned the corresponding element in the value.
This is just a simpler way of writing:
(let [x (nth point 0) y (nth point 1)]
(println "x:" x "y:" y))
See Clojure let binding forms for another way to use destructuring.
It means making a picture of the structure of some data with symbols
((fn [[d [s [_ _]]]]
(apply str (concat (take 2 (name d)) (butlast (name s)) (drop 7 (name d))) ))
'(describing (structure (of data))))
=> "destructuring"
((fn [[d e _ _ _ _ _ i n g _ _ _ _ _ s t r u c t u r e & etc]]
[d e s t r u c t u r i n g]) "describing the structure of data")
=> [\d \e \s \t \r \u \c \t \u \r \i \n \g]
Paste those ^ examples into a REPL & play around with them to see how it works.
The term "Destructuring" sounds heavier than it is.
It's like visually matching shapes to shapes. For example:
(def nums [1 2 3 4 5 6])
(let [[a b c & others] nums]
;; do something
)
Imagine the effect of the let binding as:
1 2 3 4 5 6
| | | ( )
v v v v
[a b c & others]
;; Now we can use a, b, c, others, and of course nums,
;; inside the let binding:
user=> (let [[a b c & others] nums]
(println a)
(println b)
(println c)
(println others)
(println nums))
1
2
3
(4 5 6)
[1 2 3 4 5 6]
The goal is to concisely name items of a collection, for use inside the scope of a let binding or function (i.e. within a "lexical scope").
Why "concise"? Well, without destructuring, the let binding would look like this:
(let [a (nth nums 0) ;; or (first nums)
b (nth nums 1) ;; or (second nums)
c (nth nums 2)
others (drop 3 nums)]
;; do something
)
This illustrates the basic idea. There are many details (ifs and buts, and dos and don'ts), and it's worth reading further, in depth. Here are a few resources that explain more, with examples:
My personal favourite: Jay Fields's post on Clojure Destructuring:
http://blog.jayfields.com/2010/07/clojure-destructuring.html
A gentle introduction to destructuring, from Braveclojure:
http://www.braveclojure.com/do-things/#3_3_3__Destructuring
its used to name components of a data structure, and get their values.
Say you want to have a "person" structure. In java, you would go all the way to create a class with constructors, getters and setters for the various fields, such as name, age, height etc.
In Clojure you could skip the "ceremony" and simply have a vector with 3 slots, first for name, than for age and last for height. Now you could simply name these "components" and get their values, like so:
(def person ["Fred" 30 180])
(let [[name age height] person]
(println name age height)) ;; will print: Fred 30 180
p.s - there are better ways to make a "person" in clojure (such as records etc), this is just an example to understand what destructuring does.
Destructuring is a convenience feature which allows local bindings (not variables!) to be created easily by taking apart complex data structures (seq-ables like vectors, or associatives like hash-maps), as it is described here.
Take the following example:
(let [v [1 2 3 4 5 6]
v_0 (first v)
v_1 (nth v 1)
v_rest (drop 2 v)
m {:a 1 :b 2}
m_a (get m :a)
m_b (get m :b)
m_default (get m :c "DEFAULT")]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Then the above code can be simplified using destructuring bindings like the following:
(let [[v_0 v_1 & v_rest :as v]
[1 2 3 4 5 6]
{m_a :a m_b :b m_default :c :or {m_default "DEFAULT"} :as m}
{:a 1 :b 2}]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Destructuring patterns can be used in let bindings and function parameters (fn, defn, letfn, etc.), and also in macros to return let bindings containing such destructuring patterns.
One important usage to note is with the if-letand when-let macros. The if statement is always evaluated on the whole form, even if the destructured bindings themselves evaluate to nil:
(if-let [{:keys [a b]}
{:c 1 :d 2}]
(println a b)
(println "Not this one"))
Destructuring binds a pattern of names to a complex object by binding each name to the corresponding part of the object.
To bind to a sequence, you present a vector of names. For example ...
(let [[x y] (list 5 7)] ... )
... is equivalent to
(let [x 5, y 7] ... )
To bind to a map or to a vector by index lookup, you present a map of name-to-key pairs. For example ...
(let [{x 0, y 1} [5 7]] ... )
... is equivalent to both of the above.
As others have mentioned, you can find a full description of this powerful mechanism here.

Macro quoting and unquoting

I'm trying to write a macro to require some namespaces programmatically, so that the result for a passed-in argument would be (require 'value-of-argument). If I say (defmacro r [x] `(require ~x)) then I get (require value-of-x) as expected, but I can't work out how to get the quote in there.
Edit: here's a simpler example of my problem:
(defmacro q [x] `(str ~x))
=> (map (fn [e] (q e)) (map symbol ["x" "y" "z"]))
=> ("x" "y" "z")
however,
(defmacro q [x] `(str '~x))
=> (map (fn [e] (q e)) (map symbol ["x" "y" "z"]))
=> ("e" "e" "e")
All you need is to quote the argument again, like this:
(defmacro r [x] `(require '~x))
It should do the trick.
EDIT: The above won't work since x isn't known at compile time, when the macro is expanded.
However, now that I think about it, why not just call require directly, without a macro?
This seems to work:
(require (symbol "clojure.walk"))
Does that help?
(defmacro r [x] `(require (quote ~x)))

Map restructuring

In clojure, I can destructure a map like this:
(let [{:keys [key1 key2]} {:key1 1 :key2 2}]
...)
which is similar to CoffeeScript's method:
{key1, key2} = {key1: 1, key2: 2}
CoffeeScript can also do this:
a = 1
b = 2
obj = {a, b} // just like writing {a: a, b: b}
Is there a shortcut like this in Clojure?
It's not provided, but can be implemented with a fairly simple macro:
(defmacro rmap [& ks]
`(let [keys# (quote ~ks)
keys# (map keyword keys#)
vals# (list ~#ks)]
(zipmap keys# vals#)))
user=> (def x 1)
#'user/x
user=> (def y 2)
#'user/y
user=> (def z 3)
#'user/z
user=> (rmap x y z)
{:z 3, :y 2, :x 1}
I wrote a simple macro for this in useful, which lets you write that as (keyed [a b]). Or you can parallel the :strs and :syms behavior of map destructuring with (keyed :strs [a b]), which expands to {"a" a, "b" b}.
The short answer is: no.
The main reason is that in Clojure, not only keywords but any value can be used as a key in a map. Also, commas are whitespace in Clojure. So {a, b} is the same as {a b} and will result in a map with one key-value pair, where the key is whatever a evaluates to.
You could however write a macro that takes a list of symbols and builds a map with the names of the symbols (converted to keywords) as keys and the evaluations of the symbols as values.
I don't think that is provided out of the box in clojure .. but hey this is lisp and we can use macros to have something like this:
(defmacro my-map [& s]
(let [e (flatten (map (fn [i] [(keyword (str i)) i]) s))]
`(apply hash-map [~#e]))
)
Usage:
(def a 10)
(def b 11)
(def result (my-map a b))
result would be your map