> By contrast in a lisp the syntax for setting a variable looks the same as the syntax for looping and for everything else. It's all just function calls.
Not really.
Setting a variable in Lisp is not a function call. IF is also not a function call. Defining a function is also not a function call. Loop operations like DO, DOLIST, DOTIMES, ... are also not function calls. Lots of things are not function calls. Macro forms are also not function calls.
(let ((a 10) (b 20) c)
(declare (type (integer 0 *) a b c))
(setf c (* a b))
c)
Above is a LET expression, a variant of a lambda application.
It does not look like a function call. It looks like an operator list form, with LET as the operator. The next element is not a function call or similar, but a binding list with three variable definitions, two of them having an init value. Next to the binding list is a declaration form, with a type declaration for the local variables. Then a sequence of forms, a body, which is evaluated top down and the last value ist returned. There is a setf form, for setting a variable. The variable in the setf form is not evaluated, it will be set to the value of the second argument.
Neither LET, DECLARE, TYPE, INTEGER, or SETF are functions. They have different syntax and/or semantics from function calls.
Thus we have:
* special control flow
* a LET syntax which is not looking like a function call
* a lexical scope created by LET
* a type declaration with special syntax
* special evaluation rules, unlike evaluation of a function form
A Lisp user will need to learn that IF, WHEN, AND, ... and a lot of other operators are not functions....
Not really.
Setting a variable in Lisp is not a function call. IF is also not a function call. Defining a function is also not a function call. Loop operations like DO, DOLIST, DOTIMES, ... are also not function calls. Lots of things are not function calls. Macro forms are also not function calls.