On Dec 4, 2023, at 8:21 AM, Marc Nieper-Wißkirchen <marc.nie...@gmail.com> wrote:
Am Mo., 4. Dez. 2023 um 12:11 Uhr schrieb Sergei Egorov < e...@acm.org>: I would like to repeat the argument that seems to be lost in the discussion. After giving it some thought, now I can see that the two SRFIs are not entirely incompatible.
What if we explicitly mark situations where there is an identifier that would refer to an outside scope in SRFI-251 semantics while referring to "over-the-run-of-commands" definition according to SRFI-245 semantics, and only those situations, as "it is an error"? Would it still leave enough useful programs "in the clear"? If this is so, both SRFIs become different implementation strategies for the same common idea; all current implementations of both STFIs would stil be compliant, stepping into "is an error" territory in different ways, but giving the compliant bodies the same meaning.
The problem with this approach is that - unless it becomes mandatory to raise an exception when in the "it is an error situation" - Schemes and programs will start to diverge.
True if you are firmly in the "all errors must raise exceptions" camp; I am not, both as user and an implementor. Schemes were diverging from the very start, and the freedom of handling "it is an error" situations allowed them to scale easily in both directions. I think that nothing seriosly bad came out of this freedom. But that's a philosophical issue, too complicated to discuss here.
There's still a need to insert an occasional command in the middle of a run of mutually recursive definitions, and it can be addressed by introducing a define! form (any other name would do), such that (define! <command>) is a definition, so it does not interrupt the "run" of definitions. It can be just a macro expanding into R7RS (define-values () (begin <command> (values)) or something implementation-dependent with the same semantics. In fact, just this form alone can solve all the problems mentioned in rationale, albeit a little more clumsily.
This approach has the advantage that no change to any expander is necessary and that it already works in R5RS, R6RS and R7RS-small.
The name "define!" should be bike-shedded, of course. :) I would also make it a form taking zero, one or more commands.
A similar approach is to extend define-values:
(define-values <formals> <definition> ...
<command> ... <_expression_>)
will expand into
(define-values <formals> (let () <definition> ... <command> ... <_expression_>))
This will already cover a lot of use cases, namely to allow long calculations for local variables appearing before the point of definition.
For the other use cases,
(define-values #f ...)
will expand into
(define-values <tmp> ... #f)
One restriction of RnRS would still apply, namely that every form is either an _expression_ or a definition. One cannot write a general `check-argument' macro that expands into the correct form in each context; but this is possibly a good thing.
I agree on all counts ) Perhaps we can stick with it and see what happens?
|