You are trying to do too much at once when you say
'(' is a kind of call that calls the succeeding operator on the operands while the closing paren ')' is a terminate that wraps up the previous evaluation and returns the final value generated
The Clojure evaluation model does not assign semantics to characters directly. Instead, evaluation of a Clojure program goes through two broad phases:
- First, read the characters in the source file according to the language's lexical rules, yielding a Clojure data structure
- Second, evaluate that data structure, according to the language's evaluation rules, yielding a value
So when we write an expression like (+ (* 4 5) 2)
, what happens? The reader matches up parentheses to create lists, and yields as its result a list of three elements: the symbol +
, another list (containing the symbol *
and the numbers 4 and 5), and the number 2.
Next we move to evaluate that expression. Notice, crucially, that at this point there is no trace of parentheses. The textual source of the program is no longer material. We're evaluating a list. Of course, if we printed that list, conventionally we would surround it with parentheses, but that does not concern the evaluator. How do we evaluate this list? Well, the evaluation rule for lists is to, first, evaluate each of the components, and then invoke the first component as a function, passing the remaining components as arguments1. So our list of pending tasks is:
- Evaluate
+
- Evaluate
(* 4 5)
- Evaluate
2
- Invoke the result of (1), passing the results of (2) and (3) as arguments
(1), of course, evaluates to the addition function, (2) evaluates (in a similar manner) to the number 20, and (3) evaluates to the number 2 (since numbers evaluate to themselves). Thus, (4) becomes "Invoke the addition function, passing the numbers 20 and 2 as arguments". Of course, the final result is 22.
1 The rule is actually more complicated than this, because of macros, but for functions this suffices.