Re:Reading a Programmer's Guide to Common Lisp
by ogogmad on Thursday February 22, 2024 @02:57PM
(#39472226)
One possible alternative is to combine PROGN with LET, which you might then call BLOCK, with the macro definition of BLOCK looking for `VAR`s. The VAR syntax wouldn't make sense anywhere else. More exactly:
(block
(var first-thing 'EXAMPLE)
(do-something)
(var foo 'EXAMPLE)
(do-something-else))
Expand this into: (let ((first-thing 'EXAMPLE))
(do-something)
(let ((foo 'EXAMPLE'))
(do-something-else)))
This would reduce indentation. But it would also involve big changes to Common Lisp.
Re:Reading a Programmer's Guide to Common Lisp
by reikonomusha on Thursday February 22, 2024 @03:11PM
(#39472458)
If BLOCK weren't already the name of something in Common Lisp, this sort of syntax is very easy to add, easy enough to write in an HN comment. Let's call it OGOGMAD instead.
(defmacro ogogmad (&body b)
(cond
((endp b) '(progn))
((endp (rest b)) b)
(t
(let ((f (first b))
(r (rest b)))
(if (eq 'var (first f))
`(let (,(rest f))
(ogogmad ,@r))
`(progn
,f
(ogogmad ,@r))))))
Exactly as you specify, this only lets you put VAR syntax immediately inside of OGOGMAD forms. (Untested, typed on mobile.)
Re:Reading a Programmer's Guide to Common Lisp
by Jtsummers on Thursday February 22, 2024 @03:10PM
(#39472431)
It wouldn't require any changes to the language. It would probably require a tree-walking macro, which are not too uncommon. You'd want a different name though since `block` is already a thing in CL.
http://clhs.lisp.se/Body/s_block.htm
I'd recommend On Lisp by Paul Graham and Let Over Lambda by Doug Hoyt if you're interested in trying it.
Re:Reading a Programmer's Guide to Common Lisp
by lispm on Thursday February 22, 2024 @05:45PM
(#39474387)
Reducing indentation is mostly a non-goal in Lisp. Can't work with nested lists? Don't use Lisp. Lisp processes nested lists. Lisp means List Processor.
You may want to do it in a text oriented language, but not so much in an expression oriented language, where programmers edit an expression tree, by tree manipulation commands.
In Lisp the "tree" is "nested lists".
Btw., what does
(block
(when (foo)
(var first-thing 'EXAMPLE))
(do-something)
(var foo 'EXAMPLE)
(do-something-else))
mean? Is it legal? Your macro would need to traverse the expression tree, knowing the whole Lisp syntax, including expanding macros, possibly in a source interpreter. WHEN is a macro. BLOCK would need to find the VAR expression inside the WHEN macro, which is not easy for the general case. This would be very very strange. Macros are usually expanded outside to inside. Your BLOCK macro would need to expand macros in enclosed code, to find VAR expressions.In JavaScript something like above is legal in a function.
Re:Reading a Programmer's Guide to Common Lisp
by kazinator on Friday February 23, 2024 @12:18AM
(#39477251)
We would specifically not want this macro to be looking inside forms like when, and just analyze the forms that are its direct arguments. (Which is pretty easy.)
Re:Reading a Programmer's Guide to Common Lisp
by kazinator on Friday February 23, 2024 @12:47AM
(#39477390)
TXR Lisp:
(defmacro ogogmad (:match)
(() ())
(((var @var @init))
^(progn ,init nil))
((@single)
single)
(((var @var @init) . @rest)
^(let ((,var ,init)) (ogogmad ,*rest)))
((@first . @rest)
^(progn ,first (ogogmad ,*rest))))
1> (expand '(ogogmad (var a 4) (var b 5) (+ a b)))
(let ((a 4))
(let ((b 5))
(+ a b)))
2> (expand '(ogogmad))
nil
3> (expand '(ogogmad 42))
42
4> (expand '(ogogmad (var a 42)))
nil
5> (expand '(ogogmad (var a (print 42))))
(progn (print 42)
())
6> (ogogmad (var a 4) (var b 5) (+ a b))
9
:match is a new kind of macro, called a parameter list macro, that I invented. defmacro doesn't know anything about pattern matching. Parameter list macros are expanded in any function/lambda or macro parameter list situation. The :match macro assumes that the function's body consists of pattern matching clauses. It infers the parameters from it, which get substituted.
Re:Reading a Programmer's Guide to Common Lisp
by samatman on Thursday February 22, 2024 @04:28PM
(#39473514)
Lua throws an error when you try and do analogous things. I think it's compile time, actually, might be runtime though. It would be reasonable for a language like Common Lisp to reject potentially-undefined variables.
Lisp's design, I find, is best understood through the lens of how we might most straightforwardly interpret the semantics of the syntax, i.e., how we might write an evaluator for the language. It's a large part of the appeal of using Lisp; it's possible to understand the language—from parsing to execution—so well that you could in principle write a conforming interpreter for even something like Common Lisp without Herculean effort. Having such an understanding of the language has a variety of practical benefits even if you're just using the language.
A construct that you suggest like
would be quite laborious to nail down semantically, especially if we want VAR to work in as many contexts as possible. This goes against the above ethos.Even then, if we do make a variety of decisions about syntax and scoping rules to allow VAR, we have additional questions to answer in the context of Lisp specifically. For example, are macros allowed to expand into VAR statements? Is this allowed?
This sort of shenanigan can't happen with LET quite as opaquely, since the closest equivalent would require the sum to be wrapped: Now I'm clued in to something goofy potentially happening when looking at the definition of F.So we might ban macros expanding into VAR statements. So then how do we write binding macros? Introduce a dedicated SCOPE special operator?
But now we just have an obscure LET. :)Languages with very complicated grammars also typically come with comparatively complicated scoping rules (e.g., Python). Lisp's LET maybe seems gratuitous in a world of "var x = 2" syntax, but it's also abundantly clear what it means and how it works at all times, regardless of nesting or context.
To leave the reader with one last thing to ponder: What should this do in a compiled implementation of Common Lisp with VAR?