July 2019

The operators fn, if, var and while work differently than other operators when passed as a parameter to a function or evaluated when they're not the first atom in a list.

They're not like + where a program can run:

(= theop (fn (op a b c) (op a b c)))
(theop + 1 2 3) ; -> 6

The reason is that their primary goal isn't to evaluate code or to generate source code. It's to generate IR, something close to binary code. These four operators are something like macros for IR. Calling them operators isn't very accurate.

This may look pointless, because interpreters don't generate IR for code and instead evaluate code directly. In an interpreter, these operators would get source code as input. But this difference matters if a language isn't written as an interpreter because then the language must generate this IR at run-time. IR is usually generated at read-time to speed up execution, but in the rare cases where these operators are evaluated at run-time they must generate IR at run-time.

What should a program do if if is passed as a parameter? This may sound like an absurd question in a static programming language, where as far as I know if isn't a parameter, but I've seen enough Lisp to know I'd better not exclude possibilities. The real barrier may be just imagination.