R5RS gives proposed macro definitions for library forms of syntax:
http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.3
Which also defines letrec, in a very complicated way, certainly not how I would define it, I would simply use:
(define-syntax letrec2
(syntax-rules ()
((letrec2 ((name val) ...) body bodies ...)
((lambda ()
(define name val) ...
body bodies ...)))))
As far as I understand the semantics of letrec, which I use very often as a named let. It works in this way, however as I've had my fair share of debates with philosophers who think they can just disprove special relativity or established phonological theories, I know that when you think you have a simple solution to a complex problem, it's probably WRONG. There has got to be some point where this macro does not satify the semantics of letrec else they'd probably have used it.
In this definition, the definitions are local to the body of the letrec, they can refer to each other for mutual recursion, I'm not quite sure what (if any) is wrong.
It seems to me that you have pushed the responsibility of the implementation from the macro to the compiler something the R5RS designers seem to be trying to avoid.
In fact local defines are implemented with letrec in R5RS. See 6.2.2 Internal definitions.
I think the designers intentions are summed up well in the introduction to the R5RS:
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today.
edit1: Example of internal defines transformed to r5rs version of letrec. PLT scheme 4.2.5 collects/r5rs/main.ss
(define-syntax (r5rs:body stx)
(syntax-case stx (let)
[(_ (let () . body))
#'(let () . body)]
[_
;; Convert internal definitions to `r5rs:letrec', as opposed
;; to `letrec'.
...
In PLT Scheme in R5RS mode does convert internal defines to the R5RS version of letrec. You can also test this for yourself by using DrScheme's macro expander on any code with internal defines.
R5RS states that the semantics of letrec
are exactly the same as those of internal definitions. See the section devoted to the latter for details; I quote the key fragment below:
A <body> containing internal definitions can always be converted into a completely equivalent
letrec
expression.
Thus defining letrec
in terms of internal defines just shifts the problem around.
Also, I find it simpler to define a letrec
macro and have lambda
desugar internal defines into letrec
than to stuff all that complex code into the lambda
handler and build letrec
on top of that. That's without touching on the question of which is the prettier form of introducing mutually recursive bindings in a non-top-level scope... ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With