Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
blog.metaobject.com
Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
1–10 of 114 posts
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#2What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme:
https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#3That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
Passing Smalltalk blocks and Scheme/Lisp lambdas into functions have different behaviours.
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#4That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
Smalltalk blocks are anonymous functions sure, but the evaluation is delayed - you have to pass the message #value (and its variants) to it. This not the case in Scheme and maybe Lisps, where evaluation is eager. Passing Smalltalk blocks and Scheme/Lisp lambdas into functions have different behaviours.
CL-USER 9 > (defun my-if (test then else)
(if test (funcall then) (funcall else)))
MY-IF
CL-USER 10 > (let ((a 10))
(my-if (> a 5)
(lambda ()
(print 'hello))
(lambda ()
(print 'world)))
'done)
HELLO
DONE
The lambdas you see above serve the same purpose as blocks in Smalltalk.Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#5That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
I've always understood the semantics to be:
fn: (a b c) => (call a (eval b) (eval c))
mac: (a b c) => (eval (call a b c))
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#6That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
What are lisp macros for if not to delay evaluation? I assume you're making a distinction between purpose and mechanism here? I've always understood the semantics to be: fn: (a b c) => (call a (eval b) (eval c)) mac: (a b c) => (eval (call a b c))
https://en.wikipedia.org/wiki/Fexpr
When an FEXPR is called, it gets unevaluated args and can then at runtime decide what to do.
Macros OTOH are a different mechanism, where expressions get rewritten at macro expansion time, which can be for example at compile time. The macro then gets called with arbitrary expressions it encloses (those don't need to be valid code by themselves) and computes new source.
Thus macros are code generators from expressions. In a compiled implementation, macro expansion is done with compilation interleaved: each form gets expanded, even repeatedly until it no longer expands into a macro, and then the resulting non-macro form gets compiled.
Thus in a way a macro does not delay execution, it does the opposite: it actually shifts computation to compile time -> the computation of code from expressions and the computation of arbitrary side effects in the compile-time environment.
In an interpreter version of Lisp, the macro gets also expanded at runtime - but in its own macroexpansion during evaluation. There eval will call the macroexpander repeatedly until it gets a non-macro form.
Now, what can you do with arbitrary complex code generators at compile time? https://stackoverflow.com/a/2563308/69545
Actually Paul Graham wrote a classical Lisp book explaining a bunch of things around macros. Available here for download:
http://www.paulgraham.com/onlisp.html
The classic Lisp article which motivated the move from FEXPRs to macros:
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#7That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
What are lisp macros for if not to delay evaluation? I assume you're making a distinction between purpose and mechanism here? I've always understood the semantics to be: fn: (a b c) => (call a (eval b) (eval c)) mac: (a b c) => (eval (call a b c))
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#8That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
What are lisp macros for if not to delay evaluation? I assume you're making a distinction between purpose and mechanism here? I've always understood the semantics to be: fn: (a b c) => (call a (eval b) (eval c)) mac: (a b c) => (eval (call a b c))
(first b c) -> (eval b)
i can't think of a way (but it might be possible) to not evaluate c with a regular function. first is trivial and dumb, but it's obvious how to turn that into short circuiting `and` or `or`.Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#9Earlier quoted context omitted.
Smalltalk blocks are anonymous functions sure, but the evaluation is delayed - you have to pass the message #value (and its variants) to it. This not the case in Scheme and maybe Lisps, where evaluation is eager. Passing Smalltalk blocks and Scheme/Lisp lambdas into functions have different behaviours.
That doesn't matter. One can write IF as a function taking functions as THEN and ELSE forms: CL-USER 9 > (defun my-if (test then else) (if test (funcall then) (funcall else))) MY-IF CL-USER 10 > (let ((a 10)) (my-if (> a 5) (lambda () (print 'hello)) (lambda () (print 'world))) 'done) HELLO DONE The lambdas you see above serve the same purpose as blocks in Smalltalk.
The innovation here is using better syntax for anonymous functions to make such things practical in languages without macros.
Re: Lisp Macros, Delayed Evaluation and the Evolution of Smalltalk
#10That's a common misconception that Lisp macros are mostly used to 'delay' evaluation. What Smalltalk calls 'blocks' are just (anonymous) functions in Lisp. Books like SICP explain in detail how to use that for delayed evaluation in Lisp/Scheme: https://mitpress.mit.edu/sites/default/files/sicp/full-text/...
What are lisp macros for if not to delay evaluation? I assume you're making a distinction between purpose and mechanism here? I've always understood the semantics to be: fn: (a b c) => (call a (eval b) (eval c)) mac: (a b c) => (eval (call a b c))