[erlang-questions] erlang sucks

David Holz david_holz@REDACTED
Tue Mar 18 01:35:58 CET 2008

> The differences really boil down to this:
> guards are for INDEXING.
> ... optimization ... reordering ... lack of side effects ...

In that, I agree with you.  I don't want this for anything other than indexing.  I want to _externalize_ the _purely functional_ indexing analysis of whatever is being checked, instead of being forced to always write it in-line wherever any match takes place.

I am of the opinion that if I call anything including side effects inside guards, I am doing bad things and things will break.  As I said, have it detect what functions are pure functional and only allow those if you want.  Everything will then work with user-defined guards, and everybody's happy.  I do not understand the resistance to this.

There are at least 3 ways to detect pure functional guard use, as has been discussed by myself and others on this list:

1) Have some internal state flag for "inside a guard?", and check that on side-effectful BIFs, tossing an error if it is inside one.  Since side effects are generally slower than functional BIFs, adding the overhead there should be less of a hit than the internal reduction counter for process switching.

2) Do compile- and module-load-time deep checking, marking what is known as pure functional, tossing errors earlier than the above.  This is weaker in that it can't detect variable-based M:F or fun calls until they're actually invoked; it could simply consider all such calls as dirty.

3) Only allow user-defined pure functional guards from the local module, to avoid any runtime issues.

Also, there's the option to make Dialyzer detect these sorts of things.

There is no good reason to keep user functions out of guards completely.  The whole "oh no, some idiot might put side effects in guards!" is nothing but a strawman, and as I listed above, it can be a sensibly detectable error condition with no difficulty in hot code loading.

But honestly I don't see any problem whatsoever in simply allowing anything in guards, side effects or not.  It would be nice to be able to send logging info regardless of guard context if you're debugging.  The caveats of calling side-effectful code from guards would not be new.  Threaded GUI systems are notorious for this yet still work fine; you simply know if you do things a certain way, some function gets called>=0 times.  What's the big deal?  Pure functional user defined functions in guards would be the norm, as is the case that I want.  Calling receive from within another receive guard should throw an error.

> If you are generating Erlang code from a DSL, then why not just fix your
> code generator?

The problem is user-written code that uses the generated stuff.  As it is, the human cannot easily defer to the generated stuff for guard decisions without resorting to weird tricks.

> f(Msg = #hello{}) -> ...
> is necessarily safe, whereas

It may be "safe", but it doesn't abstract what "Hello" is.  It still relies on there being a record called "hello" and if the codegen decides to represent it in any other way, this assumption breaks.  Hence the need to be able to defer guards to external code.

Climb to the top of the charts! Play the word scramble challenge with star power.

More information about the erlang-questions mailing list