| Lisps are expression based languages, but not pure. It's easy to mistake it as "like most other languages", but it's not quite the same - everything is an expression and returns a result. There are no "statements". They appear procedural because of syntax sugar - ie, the body of a function is basically implicitly wrapped in (progn ...), (begin ...), ($sequence ...), etc - which are all equivalent expression forms which evaluate their sub-expressions in order and return the result of the last one. (progn a b c) ;; CommonLisp
(begin a b c) ;; Scheme
($sequence a b c) ;; Kernel
;; evaluate a, then b, then c,
;; ignore the results of evaluating a and b
;; return the result of evaluating c.
So when you see: (define (foo)
(expr1)
(expr2)
(expr3))
If we desugar, it would be (define foo (lambda () (begin (expr1) (expr3) (expr3))))
We get behavior that looks just like other procedural languages (without a "return" keyword) - but everything is still an expression.A similarity is the comma operator in C. Imagine you didn't write statements but the body of your C functions was entirely chains of comma operators. CommonLisp has a couple of other useful related forms - prog1 and prog2. They still evaluate their sub-expressions in order, but prog1 returns the result of evaluating the first expression, and prog2 returns the result of the second expression. (define (foo) (prog1 (expr1) (expr2) (expr3))
(foo)
;; evaluates expr1, then expr2, then expr3
;; returns the result of evaluating expr1
;; ignores the results of evaluating expr2 and expr3
|
To simplify it, you can consider cons, car, cdr the beating heart of Lisp. These special forms directly encode the execution semantics as the traversal of a head over cells of a tape. Lisp belongs to the same family as the Turing machine, and that's a very big family. SML also belongs to this family. The overwhelming majority of programming languages belong to this family.