Erlang language issues
Tue Apr 16 11:14:50 CEST 2002
Lots of issues here, hope I got them all :-)
[new and old type tests]
>The old type tests must of course remain for backwards
>compatibility, but they are now being renamed to the "is_" forms
>very early in the compilation.
I think my basic question is whether one can rename guard tests
into the new operations directly. This way, one could get rid
of having both type(X) and is_type(X). It would seem to be possible
for most cases, perhaps excepting the dual mode of float(X) that
you mention, or any similar cases.
(Though looking at the context, it should be possible to deduce
what version is intended: off the top of my head, on the toplevel
one uses is_float(X), inside arithmetic one uses to_float(X) or
whatever the operation may be called. Any questionable cases are
flagged with a warning.)
> /.../ the reason for the extension is to make guards more like
> other expressions. A complication is that failure in the first
> argument of a top-level guard 'or' (semicolon) goes on to try the
> other alternative as if there were two clauses, while at the
> expression-level the whole 'or'-operation fails immediately.
I think making guards behave like expressions is a Good Thing,
generally speaking, because it is more convenient to have full
boolean expressions. As you say, the problem is nailing down the details.
I suppose the behaviours above should be unified. If nothing else, for
the sanity of programmers :-)
>For some reason, the original and/or were defined to evaluate both
>arguments. Personally, I would love to give and/or the semantics
>of andalso/orelse, but previous experience suggests that any
>semantic changes in Erlang, however obscure, are politically
>impossible. Could this be an exception to the rule?
One might hope so, if only for the reason that most people might
think 'and' really works like 'andalso'. And that is why I
asked the question: do you people out there really want 'and' to evaluate
(Personally, I tend to curse the fact that it does :-)
>The main problem with allowing any function in guards is not
>really the time (after all, length/1 is allowed), but the side
>effects (such as sending messages or updating ETS tables). The
>assumption when a guard fails is that the state of the world did
>not change. Also, guards are used in 'receive': sending a message
>from a guard expression in a receive-clause, or evaluating a
>receive within a receive, could cause major inconsistencies (it
>would be very hard to specify what the semantics actually should
>be, if this was allowed).
To handle this, I once proposed that execution would be in 'normal mode' or
'guard mode'. The latter would trigger an un-catchable exception
(i.e., fail) when a side-effect was attempted. That way, remote
calls still work. (The originating guard would catch the failure.)
(Roughly speaking, you would only switch out of guard mode when you
exit the guard that set the computation into guard mode.)
I'm a bit ambivalent about permitting "deep guards", however.
What do we define as a side-effect, for instance? _Reading_ the database?
Permitting long-running guards means we must be able to context-switch
inside the guard, which means the database can change while we run the
guard, which might be construed as an impurity. (And what about read locks?)
And so on.
I believe the original restriction on guards comes from concurrent logic
programming, where "deep guards" had severe problems and ultimately
led to disallowing them.
Well, the Real World intrudes so I have to leave off here. Basically,
I'd like to reduce the number of constructs when their meanings are
very close. And yes, legacy code is a problem.
More information about the erlang-questions