1

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?

3
  • 1
    It has actually little to do with read-string. Try ('foo 2 3) and you'll get the same result. Commented Dec 4, 2018 at 8:18
  • 1
    or, what is more demonstrative: ('+ {'+ 10} 11) , ('+ {'- 10} 11} Commented Dec 4, 2018 at 8:21
  • 1
    Here is a directly related question: stackoverflow.com/questions/8219305/…. Basically passing arguments to symbols cause them to look up themselves in the first arg, the second arg would be the default value, hence getting 3 as result. Commented Dec 4, 2018 at 8:42

2 Answers 2

4

(read-string "+") returns a symbol + that could be resolved or evaluated to get an actual value, i.e. + function.

load-string returns the result of the expression.

In other words load-string equals to (eval (read-string "+"))

You don't get nil or an exception because the language does evaluation for you.

  1. Compiler resolves symbol + in order to evaluate the expression.
  2. + symbol is resolved to #'clojure.core/+ according to current namespace aliases, because core aliases are always available.

    (class (read-string "+"))
    ; => clojure.lang.Symbol
    (class (resolve (read-string "+")))
    ; => clojure.lang.Var
    (class (deref (resolve (read-string "+"))))
    ; => clojure.core$_PLUS_`
    
Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.