[plt-scheme] to define, or to let
Paul Schlie wrote:
> Relying on the code's author to give an implementation the liberty to
> evaluate code in any order ...
...
> as it truly only enables the specification of ambiguous
> code, with no redeeming benefits which couldn't be safely
> achieved though appropriate analysis as is now done in most
> modern compilers.
It's not just about implementations and compilers, though. Code involves
communication to other humans, also, and this is often the more difficult
part of its job, or at least the one it does less well (since by some
accounts, too much effort has been put into doing compilation well).
In dealing with large bodies of code written mostly by other people, one of
the biggest issues you run into is divining the intent of the authors
(especially since it's a natural law that there are never any comments
addressing the issue you're interested in).
On the specific issue of eval order, if the order is fixed everywhere, then
part of the original authors' intent is obscured. Deliberate, legal, but
implicit evaluation order dependencies potentially exist anywhere in the
code, and there are no immediately obvious clues as to where these
dependencies exist, where they don't, where they're intentional, and where
they're not.
The unspecified eval order constructs allow programmers to document their
intent, and that can be important. If they make an error and their
documented intent doesn't match the program's actual semantics, that's an
error.
The concern is that this sort of error is a difficult one to catch, and from
a formal semantics perspective it's a doozy, which raises bogeyman terms
like unsafe, unsound, unpredictable, unverifiable and non-deterministic (in
the bad sense).
There's a simple solution to this, and it's one that most implementations,
including PLT, can be seen as already using (although they don't say so
explicitly). That is, within any single implementation, a fixed evaluation
order can be used, which gives even erroneous programs a predictable
semantics.
However, even if an implementation guarantees a fixed evaluation order, I am
suggesting that this should not be taken to mean that it is acceptable to
rely on order dependency in constructs like LET, or ordinary argument
evaluation.
If I were writing docs for an implementation on this issue, I would tell the
user that code which relies on order dependency should use constructs
specifically designed for that purpose, such as LET*. Care should be taken
to avoid order dependencies in constructs like LET, or in ordinary function
argument evaluation. I would further point out that to avoid unpredictable
behavior, the implementation uses a fixed argument order in all cases, but
that this is a safety net, not to be abused. I would explain the issue of
code communicating to humans as well as compilers.
Finally, I would claim that on certain days, such as Halloween, the
language's icon would be replaced by a scary face. On these days, you would
not be able to depend on argument evaluation order in constructs that don't
guarantee it. If you have been a good girl or boy and written your code
correctly throughout the year, your programs will not break. If you have
not been good, then your soul will be unsafe, its likely fate unverifiable.
Anton