Constructive criticism of Erlang

Chris Pressey cpressey@REDACTED
Thu Feb 8 00:59:30 CET 2001


Thanks to everyone who responded.

Thomas Lindgren wrote:
> I got on a roll here :-)
> cpressey@REDACTED wrote:
> > I understand this makes the compiler more complex though, but even under
> > the current system, more BIFs should be allowed in guards.  I don't see
> > why I can't say "when element(N, T) == 0", for example; that's fairly
> > lightweight, no?
> Guards should basically be side-effect free and guaranteed to
> terminate. Note that element/2 is permitted in guards (see p.29 of the
> Erlang book).

Whoops, you're right.  I jumped the gun here.  My test code that
"showed" that element/2 didn't work in a guard, was actually broken in a
different way.  My bad :-)

> > 3. Speaking of making the compiler complex, it would be great if it
> > could deduce the legal set of types used by each argument in each
> > function (perhaps using supplied predicate guards such as record/2) [...]
> Unfortunately, type checking of function calls can be difficult in
> general. For example, hot code loading means remote calls (between
> modules) do not have a statically known type. Take the following
> definition:
> f(X) -> m:g(X).
> Since m can be loaded at runtime, you can't say anything about what
> type X is expected to be. (In fact, it can change as new versions of m
> are loaded.) So you can't statically derive a type for f/1.

That's OK, I don't believe in type inference, really; I think it's too
fancy to be warranted in many languages, and I think Erlang is one of
those languages.  If I define a (static, low-order) function (in this
module) like this:

  foo(X) when atom(X)  -> m:g(X);
  foo(X) when tuple(X) -> n:q(X).

Then later I go and do something unwise like

  foo([a,2,3]);

The compiler could (in this very limited instance) check that 'list' is
not a member of the set 'atom, tuple' and reject that call (or at least
produce a warning).  If the guards were left out, then the compiler
would have no way to check, and no warnings would appear (which would be
like Erlang as it is now.)

Now, this isn't some fancy inferred type scheme that tries to predict
everything; it's more like explicit typing from Pascal (which does allow
overlapping types; e.g. range types.)  The important property, that you
can build a "strong" sense of identity (checked at compile-time),
underlies both systems.

(You see, I appreciate and understand functional programming, but I'll
never be an FP zealot, so I'm not sold on the FP school's ideas about
type systems.  In my experience the really useful languages are the ones
that combine features from more than one heritage and/or paradigm.  Like
Erlang!)

I'd never propose trying to take the dynamic type system out of Erlang -
but supplementing it with a compile-time type checker of any sort would
surely increase productivity, as potential errors could be caught
without having to test the part of the program which contains the error.

> Anyway, your message inspired me to look for more dark corners to be
> swept. Here are two:
> 1. I think records should be cleaned up.

I realize records in Erlang leave a bit to be desired.  I find it mildly
annoying that I have to re-state the name of the record pretty much
everywhere.  I would probably find that less annoying if I were a
'Hungarian names' fan, but I'm not.  Otherwise, include files for
sharing structure declarations, transparency through to the underlying
tuple, etc, are suboptimal, but also for the most part adequate, on par
with other production languages.

> I think we should take better advantage of exceptions than we do
> today.

I was considering trapping a "badarith" exception to try to accomplish
overloading of +-*/, but that sounds like it's probably the wrong way to
approach that one.

Robert Virding wrote:
> Chris Pressey <cpressey@REDACTED> writes:
> >1. Having semicolons as statement seperators instead of statement
> >terminators is basically *annoying* during program maintainance (while
> >adding or removing a statement.)  Having an extraneous semicolon
> >(especially before an 'end' token) generate a warning rather than an
> >error would be more pleasant.
> To be consistent you would have to allow it before the final '.' of a
> function definition as well.  Personally I still don't see the problem.
> :-)

Sure, what the heck;.  :-)

The other option would be to make semicolons entirely optional - but I
thought that might be a bit risque for Erlang (even though I'm sure the
compiler and most humans could handle a semicolon-free source file with
few problems.)

> >2. I don't think I agree with the idea that only some "specially
> >selected" functions should be allowed in guards.  This makes guards
> >semantically unorthogonal.  I think guards should be thought of as mere
> >syntactic sugar, and the compiler will choose what it determines to be
> >the most efficient manner of implementing the guard.  This would help in
> >writing more readable programs.
> The main criteria is that guard must be side-effect free and guaranteed
> to terminate.  They should preferably also be bounded in time.

OK, I've been thinking about it.  To me, the main criteria for a guard
is that it *establishes the identity of the arguments* apropos to
pattern-matching.  Naturally, the methodology for establishing the
identity of something should be side-effect free and guaranteed to
terminate!

I've noticed that most high-level language are made up of several
sublanguages.  Most languages have a "type system sublanguage": in
Erlang guards serve this purpose, but the typing theme seems to go
almost unspoken (in the docs I've read so far.)

Most languages' type sublanguages are guaranteed to have certain
properties - referential transparency is popular, so that specific types
(or sets of types) can be predicted at compile-time.

> >But say I want to build my own numeric data type.  Naturally my source
> >will be more readable if I can overload the arithmetic operations +-*/
> >on it - could I express this as a parse transformation?  Basically I'd
> >be representing a numeric datum as a tuple, so I'd want to be able to
> >translate {1, etc} + {2, etc} into mynumeric:add({1, etc}, {2, etc}).
> You could express this as a parse transform but you might run into
> trouble with typing.  How do you detect that you really want/need to
> overload a +-*/ ?

Good point; a record would of course be better here.

If you don't care why I want to do this, you can stop reading here...
but for the interested, my beef with Erlang - in fact nigh all modern
programming languages - is that they enforce unnatural abstractions on
the programmer.  My case in point is if you say something like

  A = 3

This simple-looking statement doesn't actually correlate to the
real-world very well, because in the real world the number 3 could mean
a great many things.  3 meters?  3 feet?  300% of something else?  3
system failures?  3 stray cats?  The programmer simply did not say.  If
the programmer did not bother to add a comment to clarify it, it might
not be apparent from the source code, either.

In other words, in real-world models, scalar numbers and units of
measurement have a certain parity that should not be split; also, the
most maintainable programs in the production sphere are the ones that
are closest to their real-world models.

Therefore, one of the most valuable things a production language can
support is a way to store numbers with units of measurement.  But almost
no language does this.  I once worked on writing my own language to
serve this purpose, but it is simply too much work to write an entire
full-featured language for such a small (but critical) concept.  I began
implementing the concept as a numeric type in languages such as Perl. 
Wherein it seems to work fine, but Perl has been proving to be, er, not
the greatest language for real-world models in general.

Erlang strikes me as being a much better fit.  Partly because of a
reason mentioned earlier on, the fact that Erlang types are dynamic, and
can overlap: both properties are required to leverage units of
measurement fully (I've done some experiments with strong typing and
units of measurement, and the results are less than spectacular.)

_chris

-- 
Change rules.
Share and Enjoy on Cat's Eye Technologies' Electronic Mailing List
http://www.catseye.mb.ca/list.html



More information about the erlang-questions mailing list