Erratum for letrec* definition

59 views
Skip to first unread message

John Cowan

unread,
Nov 30, 2013, 12:47:44 AM11/30/13
to scheme-re...@googlegroups.com, scheme-...@scheme-reports.org
I've added the following erratum to the list at
<http://trac.sacrideo.us/wg/wiki/R7RSSmallErrata>:

The semantics of letrec* should say that evaluation of the <init>s
is interleaved with assignment to the <variable>s. As written,
it could be understood as allowing the <init>s to be evaluated
first in left-to-right order and then assigned to the <variable>s
in left-to-right order.

Not interleaving the assignments would make letrec* fairly useless.

Any objections?

--
John Cowan co...@ccil.org http://ccil.org/~cowan
Assent may be registered by a signature, a handshake, or a click of a computer
mouse transmitted across the invisible ether of the Internet. Formality
is not a requisite; any sign, symbol or action, or even willful inaction,
as long as it is unequivocally referable to the promise, may create a contract.
--Specht v. Netscape

Alex Shinn

unread,
Nov 30, 2013, 7:57:10 PM11/30/13
to scheme-re...@googlegroups.com, scheme-reports
On Sat, Nov 30, 2013 at 2:47 PM, John Cowan <co...@mercury.ccil.org> wrote:
I've added the following erratum to the list at
<http://trac.sacrideo.us/wg/wiki/R7RSSmallErrata>:

    The semantics of letrec* should say that evaluation of the <init>s
    is interleaved with assignment to the <variable>s. As written,
    it could be understood as allowing the <init>s to be evaluated
    first in left-to-right order and then assigned to the <variable>s
    in left-to-right order.

Not interleaving the assignments would make letrec* fairly useless.

Any objections?

I'm not sure we need bother clarifying this.  Interleaving
assignment is both the most natural and only realistic
interpretation of the existing text.  You have to stretch
it quite a lot to think that it allows the <init>s to be
evaluated outside the order of the assignments.

-- 
Alex

John Cowan

unread,
Nov 30, 2013, 10:00:09 PM11/30/13
to scheme-re...@googlegroups.com, scheme-reports
Alex Shinn scripsit:

> I'm not sure we need bother clarifying this. Interleaving
> assignment is both the most natural and only realistic
> interpretation of the existing text. You have to stretch
> it quite a lot to think that it allows the <init>s to be
> evaluated outside the order of the assignments.

Well, someone on #scheme was complaining about it being unclear,
and when I looked at it, I realized that I had never really
understood letrec* before. He was under the impression that
letrec* is to letrec as let* is to let; that is, that letrec*
expands to nested letrecs. Anyway, Riastradh set both of us
straight, and clarified that although some Schemes implement
letrec as letrec*, this is definitely a bug. See the page
LetrecStar for which Schemes do what now.

So since it had confused at least one user, and I didn't correctly
understand it when I looked at it, I thought it would be good
to add a clarification.

--
John Cowan http://ccil.org/~cowan co...@ccil.org
Lope de Vega: "It wonders me I can speak at all. Some caitiff rogue
did rudely yerk me on the knob, wherefrom my wits yet wander."
An Englishman: "Ay, belike a filchman to the nab'll leave you
crank for a spell." --Harry Turtledove, Ruled Britannia

Alex Shinn

unread,
Nov 30, 2013, 11:52:31 PM11/30/13
to scheme-re...@googlegroups.com, scheme-reports
On Sun, Dec 1, 2013 at 12:00 PM, John Cowan <co...@mercury.ccil.org> wrote:
Alex Shinn scripsit:

> I'm not sure we need bother clarifying this.  Interleaving
> assignment is both the most natural and only realistic
> interpretation of the existing text.  You have to stretch
> it quite a lot to think that it allows the <init>s to be
> evaluated outside the order of the assignments.

Well, someone on #scheme was complaining about it being unclear,
and when I looked at it, I realized that I had never really
understood letrec* before.  He was under the impression that
letrec* is to letrec as let* is to let; that is, that letrec*
expands to nested letrecs.

If that is the misconception, then your clarification
doesn't help - in nested letrecs the order of <init>
evaluation and variable assignment would be the
same as it is now.

Perhaps instead we could just add some more
examples?  This should help understanding better
than lengthening the prose.

Anyway, Riastradh set both of us
straight, and clarified that although some Schemes implement
letrec as letrec*, this is definitely a bug.

Using letrec as though it were letrec* is indeed
a bug.  Specifically, it "is an error", which means
implementations are free to handle this situation
however they want, including raising an exception
or simply treating it as letrec*.

-- 
Alex

John Cowan

unread,
Dec 1, 2013, 1:23:41 PM12/1/13
to Jussi Piitulainen, Alex Shinn, scheme-re...@googlegroups.com, scheme-reports
Jussi Piitulainen scripsit:

> Not sure what there is already but I donate the following.

Thanks. I rewrote this using letrec* as:

(define (means ton)
(letrec*
((mean
(lambda (f g)
(f (/ (sum g ton) n))))
(sum
(lambda (g ton)
(if (null? ton)
(+)
(if (number? ton)
(g ton)
(+ (sum g (car ton))
(sum g (cdr ton)))))))
(n (sum (lambda (x) 1) ton)))
(values (mean values values)
(mean exp log)
(mean / /))))

and added your example to both the errata page and the errata branch.

See LetrecStar on the wiki for which Schemes implement letrec*,
which implement letrec as letrec*, and how they handle internal defines.
'My young friend, if you do not now, immediately and instantly, pull
as hard as ever you can, it is my opinion that your acquaintance in the
large-pattern leather ulster' (and by this he meant the Crocodile) 'will
jerk you into yonder limpid stream before you can say Jack Robinson.'
--the Bi-Coloured-Python-Rock-Snake

John Cowan

unread,
Dec 1, 2013, 1:29:46 PM12/1/13
to scheme-re...@googlegroups.com, scheme-reports
Alex Shinn scripsit:

> Using letrec as though it were letrec* is indeed a bug. Specifically,
> it "is an error", which means implementations are free to handle this
> situation however they want, including raising an exception or simply
> treating it as letrec*.

Yes, that's true (though not true in R6RS, where sequential dependency in
letrec must signal an error). Besides the R6RS implementations, only MIT,
Scheme48/scsh, SigScheme, and TinyScheme do not handle letrec as letrec*,
though SISC prints a warning. Only Scheme48/scsh and SigScheme get upset
by sequential dependencies in internal defines (following R5RS strictly).

--
I don't know half of you half as well John Cowan
as I should like, and I like less than half co...@ccil.org
of you half as well as you deserve. http://www.ccil.org/~cowan
--Bilbo
Reply all
Reply to author
Forward
0 new messages