[plt-scheme] to define, or to let

From: Bradd W. Szonye (bradd+plt at szonye.com)
Date: Tue Mar 23 16:57:42 EST 2004

I just thought of another way to explain why I prefer explicit language
constructs for sequential (LET*) and non-sequential (LET) evaluation.
Earlier, I quoted a key point from Steve McConnell's /Code Complete/:

    When statements have dependencies that require you to put them in a
    certain order, take steps to make the dependencies clear.

In a language with strict left-to-right evaluation, it's easy to write
code with implicit or "accidental" order dependencies. Because the
language guarantees a specific evaluation order, the program may still
produce the correct output for all possible inputs. You could use
exhaustive black-box testing or formal proofs to demonstrate that the
program is "correct."

However, while the program may be "correct," the source code and the
process used to construct it are both flawed, because they violate an
important engineering principle. McConnell's key point above is just a
specific example of a more general principle: Engineers must identify
and document all significant requirements and risk factors. A program
with implicit sequencing requirements fails that test.

In the comp.lang.scheme discussion, one poster consistently rejected
this argument, unfavorably comparing it to Orwellian "thought crimes."
That poster strongly felt that the program's correctness was sufficient
to justify the means used to create it. That criticism might be
reasonable in some contexts, like an informal, one-man job. However, in
a complex software product developed and maintained by a large team of
programmers, it's not enough to make sure that the final product is
correct. Good engineering pratices and processes are absolutely
necessary to make sure that the product is also affordable, efficient,
robust, and maintainable.

In this specific case, that means following McConnell's advice and
making sure that all ordering requirements are clear. You could do that
in docs or comments in any language, but Scheme makes it trivial to do
it in code, which means that both humans and programs can easily make
use of the information.

Furthermore, note that McConnell's principle implies that ordering
requirements are not the "default" case. If they were, there would be no
point in making them clear. That also justifies Scheme's "default" use
of non-ordered evaluation for function arguments.

Finally, note that unspecified evaluation order does not cause any
"ambiguity" for correct code. If the programmer has correctly identified
all ordering requirements, then there is no "ambiguous" code at all. If
he has identified them incorrectly (or he didn't bother identifying them
at all), then the code is incorrect, regardless of whether the program
happens to produce the correct output.
Bradd W. Szonye

Posted on the users mailing list.