[plt-scheme] Re: to define, or to let

From: Anton van Straaten (anton at appsolutions.com)
Date: Fri Apr 9 12:21:16 EDT 2004

Bill Richter wrote:
> I get it: letrec* is like let*, which I use all the time, I rarely use
> let, because as you say, let* is a "binding+sequencing construct."  So
> I guess I'm with vast majority, and prefer letrec* to the R5RS letrec.
> But R5RS letrec doesn't sound busted to me, and I think you agree.

Right, it's not busted, even by Matthias' standards, as long as you fix an
evaluation order for its initializers, which is allowed by R5RS.

In code which defines mutually recursive functions, it's quite common that
the functionality of letrec* is not needed, and letrec is all you need.  If
you write letrec* when all you need is letrec, you withhold information from
your program source code that can communicate potentially useful
information, to a reader of the program, about the relationship between the
letrec initializers.  For example, if you want to rearrange the code for
some reason, it's easier to rearrange a letrec than a letrec*, without even
looking at what the code is actually doing.

Boiled down, it's about being able to express what you mean in a language,
rather than being forced to say something you don't mean in order to get
what you want.  (The latter, of course, is much like real life! ;)

>    An implementation of R5RS letrec is semantically safe, by Matthias'
>    criterion, if it provides a fixed order of evaluation for the
>    initializers.
>
> That's what I'm missing, Anton.  Did I miss a long discussion?

Yes.  :)

> I like
> left-to-right eval, but why is a fixed order of evaluation safer?

It's safer than an unspecified order, in the presence of side effects.  If
you have side effects in an expression with an unspecified order of
evaluation, then the expression tends to have multiple possible meanings,
i.e. its meaning is ambiguous.  That's the semantic ambiguity I mentioned.
It means you can't rely on the program's behavior, hence it is unsafe.

> Maybe it's safer to be forced to code so that order of evaluation
> doesn't matter.

Definitely, but if you're concerned with the semantics of full Scheme, you
can't just close your eyes and ignore the bits you don't like.  R5RS Scheme
supports side effects, but most of it has unspecified evaluation order.
That makes many of its constructs semantically ambiguous in the sense
described above.  The only easy way to achieve semantic certainty (safety)
in this case is to choose a fixed evaluation order.

> Taking this to the extreme, we get functional
> programming, which everyone likes!

I agree (for some value of "everyone" which includes me), but realistically,
having some side effects is useful, at least with current language
technology.  Any functionally-oriented language with side effects has to
deal with this issue, and there are languages on both sides of the
fixed-evaluation-order fence.

Scheme is somewhat unique in that R5RS provides a rather flexible template
for implementations.  In that template, order of evaluation is left as a
blank to be filled in by implementations, and it's even valid for an
implementation to leave it blank.  This gives R5RS Scheme a less
satisfactory semantics, from a certain perspective.

However, if you're going to have a functionally-oriented language, and you
want to use it functionally, then the ability to communicate which bits of
your program are intended to be functional (in the side-effect-free sense)
and which aren't, is useful.  That doesn't mean you can't have a fixed
evaluation order, but it does mean you need constructs that are explicitly
intended for code that doesn't rely on evaluation order.  Without that,
you're forced to write code that says more than you mean to say.

Anton



Posted on the users mailing list.