3 ms·
Different problems. If you look at McCarthy's first paper [1] it becomes clear (after a long while) that eval does not have to support macros. The ideas in Co
by dapperdrake 1y ago
Different problems.
If you look at McCarthy's first paper [1] it becomes clear (after a long while) that eval does not have to support macros.
The ideas in Common Lisp on macros and evaluation (eval) are (conceptually "far away" from McCarthy's paper, perhaps more developed):
1. Read-time with "#." and #'set-dispatch-macro-character
2. Macroexpansion-time with #'macroexpand and #'defmacro and (macrolet …)-forms and (symbol-macrolet …)-forms
3. Compile-time (optional for evaluators) with #'compile and #'define-compiler-macro
4. Load-time with (load-time-value …)-forms
5. Run-time with #'funcall and #'eval (conceptually) and #'defun and (lambda …)-forms (conceptually)
The trick is that eval is called recursively and depth-first along the abstract syntax tree (AST). Function evaluation is depth-first left-to-right. Macros and special-forms are for not depth-forst and left-to-right. Loops need to evaluate (incf i) or "i++" possibly more than once, exactly once, or not at all. "If" only evaluates either its second or its third argument, but never both.
Note, how #'set-dispatch-macro-character, #'macroexpand, #'compile, #'load-time-value, and #'eval are all functions. They are "executed at (their own) run-time."
The difference bewteen compile-time and load-time becomes obvious in parenscript. In parenscript compile time has symbolic-expressions (s-expressions) and parenscript-forms a.k.a. "valid parenscript in parentheses" while load-time already has JavaScript code. In Lisp all of this stiff just happens to be Lisp objects. Strings at read-time (symbolic-expression), lists for macroexpansion (macros are like user-defined special forms) [macroexpansion turns them into valid common lisp a.k.a. Common Lisp forms], and internal Lisp objects like compiled functions for the compiler, "loader", and run-time.
Note, that the issue of having two namespaces, that of values and that of functions, is a separate issue. Here is where macros and functions look the same, because their names are at the beginning of a "form", e.g. (with-open-file …). With-open-file never directly evaluates its first argument: the list of arguments for function open.
A "form" is a list that is meant to be evaluated. If it is valid Common Lisp code, then it is a lisp form. If it user-defined, then it better be a function call or a macro call. And the macro call has to translate it into either the call of a user-defined function or valid Common Lisp code.
Macros define "new syntax" kind of like special forms deviate from function evaluation. (if a b c) is a special form, that is a non-function-call defined by Lisp, just like Haskell leverages lazy evaluation to define "if" without eager function evaluation.
[1] http://www-formal.stanford.edu/jmc/recursive.pdf http://www-formal.stanford.edu/jmc/recursive.pdf