The API Cheatsheet section on Lists seems to indicate that '() is a list constructor, just like (list), but I've found that in practice they're not exactly the same. For example, given:
(def foo "a")
(def bar "b")
(def zip "c")
The following statement:
(apply str '(foo bar zip))
produces the output "foobarzip", which I wouldn't expect.
But the supposedly equivalent:
(apply str (list foo bar zip))
produces "abc", as I'd expect.
What's going on here? If there's a "shorthand" for a list in Clojure (like {} for maps and [] for vectors), what is it?
In lisps, ' (like quote) quotes its arguments, i.e. preserves them pretty much exactly as written in their s-exp form, including not evaluating anything within.
To put it another way '(foo bar zip) creates a list containing the symbols foo, bar, zip; while (list foo bar zip) creates a list containing the values of foo, bar, zip. In the first case, str will be converting the symbols themselves to strings and then concatenating them.
As a demonstration of this:
=> (def foo "a")
=> (type (first '(foo)))
clojure.lang.Symbol
=> (type (first (list foo)))
java.lang.String
The difference is that, as you can see, the literal syntax '() is quoted. This means symbols inside are not evaluated. To use list literals while evaluating the elements you can exploit the syntax-quote reader macro:
user=> (apply str `(~foo ~bar ~zip))
"abc"
When you write:
(def foo "a")
(def bar "b")
(def zip "c")
You've defined three symbols: foo, bar and zip associated with values: "a", "b" and "c".
The association is stored inside the namsepace table, so if using the REPL, the namespace would be user by default, so the user namespace table would now contain:
{foo
#'user/foo
bar
#'user/bar,
zip
#'user/zip}
You can see the namespace table by doing: (ns-interns *ns*)
Now if you write: (foo bar zip) inside Clojure, there is going to be four different ways this can be read by the reader. You'll need to specify to the reader which way it should be read. That's where `, ' and list come into play.
Case of no indicator:
(foo bar zip)
When simply written without any indicator, the reader will interpret this as an S-expression and will interpret foo as a symbol mapping to a function, with bar and zip as symbols mapping to values to be passed into the foo function.
In our case, it will throw an exception:
java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
This is because no function foo was defined, foo was associated with "a", which is a String, not an IFn (a Clojure function).
If the function foo was defined, it would have called foo passing in as argument "b" and "c".
Case of list:
(list foo bar zip)
When using the list symbol, the reader is actually interpreting this the same way as the no indicator case. That is, it's looking for a symbol list that maps to a function which will take the associated values mapped to foo, bar and zip as arguments. The list function is pre-defined by Clojure inside the clojure.core namespace; it returns a list of it's arguments.
So when the reader looks for list, it find the clojure.core function, then it looks for the foo symbol, and finds that it maps to "a", and so on. Once it has found all the mapping for the symbols, it calls list and passes it the associated values of foo bar zip, which would be "a" "b" "c". So (list foo bar zip) is the same as (list "a" "b" "c").
Case of ':
'(foo bar zip)
The ' quote tells the reader that the form that follows is to be read as is. In our case, foo, bar and zip are symbols, and (foo bar zip) is a list of symbols. So the reader will interpret this as a list of symbols.
That's why when you run (apply str '(foo bar zip)) it's going to call str 'foo 'bar 'zip which will give you foobarzip. That is, it's going to convert each symbol in the list of symbols to a String representation, and then concatenate these into one String.
By taking the form as is, it's passing as argument a list of symbols, without evaluating the symbols, i.e., without looking for what they're associated with. If you ran (eval '(foo bar zip)) you would pass a list of symbols to eval, and eval would evaluate the symbols to values and return a list of the values the symbols are mapped to. So you can think of the quote ' as passing the code around as code.
Case of `:
`(foo bar zip)
This one is a little more complicated. The reader will see the backquote ` and will resolve the symbols inside the list of symbols recursively as to get a list of fully qualified symbols.
Basically, when the reader looks up symbols inside the table of symbols, it does so from the table of symbols of the current namespace. A fully qualified symbol, is a symbol that includes the namespace information. So when running `(foo bar zip) the reader will replace those symbols with fully qualified ones, turning it into (user.foo user.bar user.zip).
It's possible to tell the reader to evaluate some on the elements in the list, while changing others to fully qualified symbols. To do so, you prefix the symbols you want evaluated with ~ as in:
`(foo ~bar zip)
will give you
(clojure.foo "b" clojure.zip)
Effectively, the backquote ` is a lot similar to the quote ' in that it does not evaluate, but simply returns code, except that it manipulates the code to be returned a bit by fully qualifying symbols within it. This has implications for macros, where sometimes you might want a fully qualified reference, to fetch from another namespace, and sometimes you want flexibility in saying, look for this symbol in the current namespace.
Related
I am very new to clojure so this may have a simple fix. I have two examples of code that I can't seem to find the difference in why one works and the other doesn't. The first is:
(defn example []
(def demokeys (hash-map "z" 1 "b" 2 "a" 3))
(println demokeys)
(println (get demokeys "b")))
(example)
which is from https://www.tutorialspoint.com/clojure/clojure_maps_get.htm. This works the way I expect it to, with it printing the hash map and then a 2 on the next line.
The second example is:
(defn bill-total [bill]
(println bill)
(println (get bill "b"))
(println "sometext")
)
(bill-total[(hash-map "z" 1 "b" 2 "a" 3)])
which prints the hashmap, then nil, then sometext. Why does it not correctly print the 2 as it does in the previous example?
First of all, don't use def within defn unless you need dynamic runtime declarations (and even then, you should probably reconsider). Instead, use let for local bindings.
As to your main question, you have wrapped the map in a vector, with those [] here: (bill-total [...]). When calling a function, you don't need to repeat its arguments vector's brackets - call it just like you call println or hash-map, because they're also just regular functions.
So in the end, it should be (bill-total (hash-map "z" 1 "b" 2 "a" 3)).
As a final note, there's rarely a need to explicitly use hash-map, especially when you already know the keys and values. So, instead of (hash-map ...) you can use the map literal and write {...}, just like in {"z" 1, "b" 2, "a" 3} (I used commas here just for readability since Clojure ignores them).
The API Cheatsheet section on Lists seems to indicate that '() is a list constructor, just like (list), but I've found that in practice they're not exactly the same. For example, given:
(def foo "a")
(def bar "b")
(def zip "c")
The following statement:
(apply str '(foo bar zip))
produces the output "foobarzip", which I wouldn't expect.
But the supposedly equivalent:
(apply str (list foo bar zip))
produces "abc", as I'd expect.
What's going on here? If there's a "shorthand" for a list in Clojure (like {} for maps and [] for vectors), what is it?
In lisps, ' (like quote) quotes its arguments, i.e. preserves them pretty much exactly as written in their s-exp form, including not evaluating anything within.
To put it another way '(foo bar zip) creates a list containing the symbols foo, bar, zip; while (list foo bar zip) creates a list containing the values of foo, bar, zip. In the first case, str will be converting the symbols themselves to strings and then concatenating them.
As a demonstration of this:
=> (def foo "a")
=> (type (first '(foo)))
clojure.lang.Symbol
=> (type (first (list foo)))
java.lang.String
The difference is that, as you can see, the literal syntax '() is quoted. This means symbols inside are not evaluated. To use list literals while evaluating the elements you can exploit the syntax-quote reader macro:
user=> (apply str `(~foo ~bar ~zip))
"abc"
When you write:
(def foo "a")
(def bar "b")
(def zip "c")
You've defined three symbols: foo, bar and zip associated with values: "a", "b" and "c".
The association is stored inside the namsepace table, so if using the REPL, the namespace would be user by default, so the user namespace table would now contain:
{foo
#'user/foo
bar
#'user/bar,
zip
#'user/zip}
You can see the namespace table by doing: (ns-interns *ns*)
Now if you write: (foo bar zip) inside Clojure, there is going to be four different ways this can be read by the reader. You'll need to specify to the reader which way it should be read. That's where `, ' and list come into play.
Case of no indicator:
(foo bar zip)
When simply written without any indicator, the reader will interpret this as an S-expression and will interpret foo as a symbol mapping to a function, with bar and zip as symbols mapping to values to be passed into the foo function.
In our case, it will throw an exception:
java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
This is because no function foo was defined, foo was associated with "a", which is a String, not an IFn (a Clojure function).
If the function foo was defined, it would have called foo passing in as argument "b" and "c".
Case of list:
(list foo bar zip)
When using the list symbol, the reader is actually interpreting this the same way as the no indicator case. That is, it's looking for a symbol list that maps to a function which will take the associated values mapped to foo, bar and zip as arguments. The list function is pre-defined by Clojure inside the clojure.core namespace; it returns a list of it's arguments.
So when the reader looks for list, it find the clojure.core function, then it looks for the foo symbol, and finds that it maps to "a", and so on. Once it has found all the mapping for the symbols, it calls list and passes it the associated values of foo bar zip, which would be "a" "b" "c". So (list foo bar zip) is the same as (list "a" "b" "c").
Case of ':
'(foo bar zip)
The ' quote tells the reader that the form that follows is to be read as is. In our case, foo, bar and zip are symbols, and (foo bar zip) is a list of symbols. So the reader will interpret this as a list of symbols.
That's why when you run (apply str '(foo bar zip)) it's going to call str 'foo 'bar 'zip which will give you foobarzip. That is, it's going to convert each symbol in the list of symbols to a String representation, and then concatenate these into one String.
By taking the form as is, it's passing as argument a list of symbols, without evaluating the symbols, i.e., without looking for what they're associated with. If you ran (eval '(foo bar zip)) you would pass a list of symbols to eval, and eval would evaluate the symbols to values and return a list of the values the symbols are mapped to. So you can think of the quote ' as passing the code around as code.
Case of `:
`(foo bar zip)
This one is a little more complicated. The reader will see the backquote ` and will resolve the symbols inside the list of symbols recursively as to get a list of fully qualified symbols.
Basically, when the reader looks up symbols inside the table of symbols, it does so from the table of symbols of the current namespace. A fully qualified symbol, is a symbol that includes the namespace information. So when running `(foo bar zip) the reader will replace those symbols with fully qualified ones, turning it into (user.foo user.bar user.zip).
It's possible to tell the reader to evaluate some on the elements in the list, while changing others to fully qualified symbols. To do so, you prefix the symbols you want evaluated with ~ as in:
`(foo ~bar zip)
will give you
(clojure.foo "b" clojure.zip)
Effectively, the backquote ` is a lot similar to the quote ' in that it does not evaluate, but simply returns code, except that it manipulates the code to be returned a bit by fully qualifying symbols within it. This has implications for macros, where sometimes you might want a fully qualified reference, to fetch from another namespace, and sometimes you want flexibility in saying, look for this symbol in the current namespace.
Perhaps you can help me find this in the docs. I'm using pound-quote to be able to pass around unevaluated function names prior to execution. For example:
(#'cons 1 ())
;(1)
(defn funcrunner [func a b]
(func a b))
(funcrunner cons 'a ())
;(a)
(funcrunner 'cons 'a ())
'()
(funcrunner #'cons 'a ())
;(a)
#'cons
;#'clojure.core/cons
(resolve (symbol 'cons))
;#'clojure.core/cons
My guess is that this is a reader macro.
My question is (a) What is the pound quote (#') shorthand for? (b) Can you explain what it is doing? (c) Can you locate it in the docs? (d) Is it actually shorthand for for resolve and symbol functions?
PS - For those not in the US - # is also known as a 'hash' or a 'cross-hash'.
PPS - I'm aware my example makes the need for this somewhat redundant. I'm interested to know if this is completely redundant or there are specific use cases.
#' is a reader macro that expands to (var foo). What you're doing here is not passing around unevaluated functions, you're passing around vars which contain functions. The reason this works the way it does is because vars are functions that look up their contained value and call it:
user=> (defn foo [x] (+ x 10))
#'user/foo
user=> (#'foo 10)
20
user=> ((var foo) 10)
20
Notice that when I defined the function, a var was returned. It looks like what you've been doing! :)
#' is the reader macro for var. See http://clojure.org/special_forms#var and http://clojure.org/vars
(var foo) returns the var named by the symbol foo, which can hold any kind of value, including functions.
I'm expecting below that I should be able to call my function squared indirectly via the symbol function, but its not working. What am I doing wrong here:
user=> (defn squared [x] (* x x))
#'user/squared
user=> (squared 2)
4
user=> ((symbol "squared") 2)
nil
user=> ((symbol "user" "squared") 2)
nil
user=>
The symbol itself does not hold your function, the Var it names does.
This says "take the contents (# = deref) of the Var (resolve) named by the symbol (symbol) whose name is "squared" and apply it (as a function) to the argument 2:
(#(resolve (symbol "squared")) 2)
This says "take the Var named by the symbol etc.":
((resolve (symbol "squared")) 2)
Both will work, since Vars, when asked to act as a function, defer to the functions stored in them. (If you try to use a Var as a function when it is not bound to a function, an error will result.)
This says "take the symbol named "squared" and apply it as a function to the argument 2" -- note that the symbol itself is used as the function:
((symbol "squared") 2)
Now symbols can be used as functions (they implement the clojure.lang.IFn interface), but the way they act when used in this way is that they look themselves up in their argument, i.e. treat their argument as a map and perform a lookup inside it:
('foo {'foo 2})
; is equivalent to
(get {'foo 2} 'foo)
If the argument passed to a symbol is not something it makes sense to do lookups in, nil is returned.
I have a symbol "a" bound to a function:
(defn a []
(println "Hello, World"))
user=> a
#<user$a__292 user$a__292#97eded>
user=> (a)
Hello, World
nil
Then I use syntax-quote, it "resolves the symbol in the current context, yielding a fully-qualified symbol", according to Clojure documentation. But why can't I use it the same way as unqualified symbol?
user=> `a
user/a
user=> (`a)
java.lang.IllegalArgumentException: Wrong number of args passed to: Symbol (NO_SOURCE_FILE:0)
Second question: if I have a symbol in a list, why can't I evaluate it the same way as if I would evaluate the symbol directly?
user=> (def l '(a 1 2))
#'user/l
user=> 'l
l
user=> (first l)
a
user=> ((first l))
java.lang.IllegalArgumentException: Wrong number of args passed to: Symbol (NO_SOURCE_FILE:0)
I have a suspicion I have a fatal flaw somewhere in the fundamental understanding of how symbols work here. What is wrong with above code?
REPL = read eval print loop. Step through the read-eval process.
READ: Clojure sees the string "(`a)", parses it and ends up with a data structure. At read time, reader macros are expanded and not much else happens. In this case, the reader expands the backquote and ends up with this:
user> (read-string "(`a)")
((quote user/a))
EVAL: Clojure tries to evaluate this object. Evaluation rules vary depending on what kind of object you're looking at.
Some objects evaluate as themselves (numbers, strings, keywords etc.).
A Symbol is evaluated by resolving it in some namespace to obtain some value (usually).
A List is evaluated by macro-expanding the list until there are no macros left, then recursively evaluating the first item in the list to obtain some resulting value, then using the value of the first item in the list to decide what to do. If the first value is a special form, special stuff happens. Otherwise the first value is treated as a function and called with the values of the rest of the list (obtained by recursively evaluating all of the list's items) as parameters.
etc.
Refer to clojure.lang.Compiler/analyzeSeq in the Clojure source to see the evaluation rules for lists, or clojure.lang.Compiler/analyzeSymbol for symbols. There are lots of other evaluation rules there.
Example
Suppose you do this:
user> (user/a)
The REPL ends up doing this internally:
user> (eval '(user/a))
Clojure sees that you're evaluating a list, so it evaluates all items in the list. The first (and only) item:
user> (eval 'user/a)
#<user$a__1811 user$a__1811#82c23d>
a is not a special form and this list doesn't need to be macroexpanded, so the symbol a is looked up in the namespace user and the resulting value here is an fn. So this fn is called.
Your code
But instead you have this:
user> (eval '((quote user/a)))
Clojure evaluates the first item in the list, which is itself a list.
user> (eval '(quote user/a))
user/a
It evaluated the first item in this sub-list, quote, which is a special form, so special rules apply and it returns its argument (the Symbol a) un-evaluated.
The symbol a is the value in this case as the fn was the value up above. So Clojure treats the Symbol itself as a function and calls it. In Clojure, anything that implements the Ifn interface is callable like an fn. It so happens that clojure.lang.Symbol implements Ifn. A Symbol called as a function expects one parameter, a collection, and it looks itself up in that collection. It's meant to be used like this:
user> ('a {'a :foo})
:foo
This is what it tries to do here. But you aren't passing any parameters, so you get the error "Wrong number of args passed to: Symbol" (it expects a collection).
For your code to work you'd need two levels of eval. This works, hopefully you can see why:
user> (eval '((eval (quote user/a))))
Hello, world
user> ((eval (first l)))
Hello, world
Note that in real code, using eval directly is usually a really bad idea. Macros are a better idea by far. I'm only using it here for demonstration.
Look in Compiler.java in the Clojure source to see how this all plays out. It's not too hard to follow.
Using a Symbol as a function is not the same thing as evaluating it. Symbols-as-functions work the same way as keywords-as-functions. Like this:
user=> (declare a)
#'user/a
user=> (def a-map {'a "value"})
#'user/a-map
user=> ('a a-map)
"value"
user=>
This is not how you would normally use a symbol. They are more commonly used for looking up vars in a namespace, and when generating code in a macro.
To break down the layers of indirection, let's define "x" as 1 and see what happens:
user=> (def x 1)
#'user/x
Using def, we have created a "var." The name of the var is the symbol user/x. The def special form returns the var itself to the repl, and this is what we can see printed. Let's try and get a hold of that var:
user=> #'x
#'user/x
The #' syntax is a reader macro that says "give me the var referred to by the following symbol." And in our case, that symbol is "x". We got the same var back as before. Vars are pointers to values, and can be dereferenced:
user=> (deref #'x)
1
But the var needs to be found before it can be dereferenced. This is where the callability of symbols come into play. A namespace is like a map, where the symbols are keys and vars are the values, and when we plainly name a symbol, we implicitly look up its var in our namespace. Like this:
user=> ('x (.getMappings *ns*))
#'user/x
Although, in reality, it is probably more like this:
user=> (.findInternedVar *ns* 'x)
#'user/x
And now we have come full circle on the journey of the unquoted symbol:
user=> (deref (.findInternedVar *ns* 'x))
1
user=> x
1
The two are not entirely equal, though. Because the evaluator does this for all symbols, including deref and *ns*.
The thing about quoting is that you essentially bypass this whole mechanism, and just get the plain symbol back. Like the #' reader macro get plain vars back, the ` and ' reader macros will get plain symbols back, with or without a namespace qualification respectively:
user=> 'x
x
user=> `x
user/x
user=> (def l '(a 1 2))
user=> ((first l))
Turn this into:
user=> (def l `(~a 1 2))
The ~ here resolves the symbol a to its corresponding var, and the backtick makes unquoting work.
In general, you must understand the difference between vars (which are bound to something) and symbols (which are never bound to anything).
I'll try to explain it (in the hope that my exaplanation does not confuse you further):
user=> (def v "content")
#'user/content
-> defines a var in the current namespace under the symbol 'v (fully qualified 'user/v, assuming this is the current namespace), and binds it (the var, not the symbol) to the object "content".
user=> v
"content"
-> resolves v to the var, and gets the bound value
user=> #'v
#'user/v
-> resolves to the var itself
user=> 'v
v
-> does not resolve anything, just a plain symbol (unfortunately, the REPL does not indicate this, printing 'v as v)
user=> `v
user/v
-> as you already quoted, resolves to the symbol in the current context (namespace), but the result is still a symbol (fully qualified), not the var user/v
user=> '(v)
(v)
-> plain quoting, does not resolve anything
user=> `(v)
(user/v)
-> syntax-quote, same as quoting, but resolves symbols to namespace-qualified symbols
user=> `(~v)
("content")
-> resolve the symbol to its var (which is implicitely dereferenced), yielding its bound object