What I mean is, there will only be 20~30 builtins; the rest can be implemented 'in userspace', as it were.
Though specifically in the case of cl, clos might complicate that somewhat, but probably not a ton.
It's one of the features of Common Lisp that things that might be buried in the compiler in other languages are surfaced and made available to the user. This means a great deal of the language's standard functionality can be implemented as if it were in "user space". Macros, readtables, method combinations, setf expanders and generalized places, for example.
IMO, if Common Lisp were to be extended (it probably won't be, at least officially, as there's no money for another whack at a standard) I think it would be best even if more "internal" features were surfaced this way, and made available for user extension.
Re: lambda: it's important to realize that this series is building up incrementally bigger features from nothing. This Lisp compiler won't have a full implementation of closures or even labeled procedures for some time. So right now we're getting used to name binding and using what we have.
While it's possible to generate the same code I did even when rewriting to lambda, you'll probably have to have some kind of strength reduction afterward.
(let* ((a 1) (b a)) (+ a b))
is equivalent to: ((((lambda (a) (lambda (b) (+ a b))) a) 1)
And anyway, implementing 'letrec' in C/Asm is really not that hard: allocate cells, assign names to them, compute the values. Compare that with the machinery of making closures (flat or linked?) and function invocation.I personally prefer to have 'letrec' as a primitive and implement non-recursive 'let' on top of it by checking whether any newly bound names are referenced from the bound values.
(let* ((a 1) (b a)) (+ a b))
I think this should just be plain let.If I do:
(define-syntax let-
(syntax-rules ()
[(_ ((x e) ...) b1 b2 ...)
((lambda (x ...) b1 b2 ...) e ...)]))
And then try: (let- ((a 2) (b a)) (+ a b))
I get: ; a: undefined;
; cannot reference an identifier before its definition
; in module: top-level
Question: I saw a chapter about unary functions. In some interpreters let bindings are explained as "sugar", or syntactic extensions on top of function calls. For instance `let` is not present in the core of scheme [1]. So in this way one could transform a let binding from:
to: through: ... then you wouldn't need to compile let bindings, just function application, which some people call "desugaring".I was wondering if this kind of desugaring is used in practical lisp compilers or not... without knowing too much about lisp compilers, I imagine one reason to not go this way is that it could potentially generate way more code than compiling higher level concepts like `let` directly.
1: https://scheme.com/tspl4/further.html