I have the following form:
((read-string "+") 2 3)
It returns 3
I have two questions about this:
1) Why does the form above return 3
instead of nil
or throwing an exception or anything else? How exactly is this form resolving?
2) What is returned from read-string
in this case? And how is it different from if I had used load-string
?
What you are actually doing is using a symbol as a function and passing arguments to it. You can read a related Q&A that covers this in more detail. From the answer:
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
As stated in @akond's answer, read-string
returns a symbol and load-string
evaluates that too. You could trigger the same behavior by passing any other symbol:
((symbol 'hi) 2 3)
;; 3
('foo 2 3)
;; 3
('foo '{foo 2} 3)
;; 2
('foo 2)
;; nil since there is no default value provided
If you are curious you can have a look at Symbol implementation in Clojure source code.