Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What, if any, is wrong with this definition of letrec in Scheme?

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.

like image 512
Zorf Avatar asked May 14 '10 15:05

Zorf


2 Answers

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.

like image 66
Davorak Avatar answered Sep 26 '22 01:09

Davorak


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... ;-)

like image 30
Michał Marczyk Avatar answered Sep 27 '22 01:09

Michał Marczyk