[erlang-questions] Reading, Learning, Confused

Richard A. O'Keefe ok@REDACTED
Wed Jul 23 03:17:58 CEST 2008

On 22 Jul 2008, at 9:56 pm, Thomas Lindgren wrote:
> Here are the two broad classes of guard macros I have seen:
> One case is when you want to hide representation.
>  -define(is_equipment_foo(X), (record(X, eqm1) orelse record(X,  
> eqm2)).

This is a perfect application for abstract patterns.
> Another is when you refactor or name a commonly occurring test.  
> Something like:
>  -define(is_non_empty_list(X), (is_list(X) andalso X =/= [])).
>  -define(is_byte(X), (X >= 0 andalso X =< 255)).

Again, these things could be done beautifully by abstract patterns.
For example,

	#byte(X) when is_integer(X), X >= 0, X =< 255 -> X.

In the mean time, there is nothing wrong with

		is_integer(X), X >= 0, X =< 255

for use in guards.  (See my previous message for an example
showing that the current compiler isn't terribly good with
'orelse' in guards.  This also applies to 'andalso'.  Look
at the code using 'S' yourself if you don't believe me.)
[Abstract patterns would have to be inlined when known to
the compiler, of course.]

Using 'andalso' means that ?is_byte(E) can be used in an
expression, but alas, the macro does double evaluation,
so for general expressions E you should not use it.

I have just written up a new EEP about a type/range test
is_between(Term, Lower_Bound, Upper_Bound).

> For concreteness, here are three guard macros from xmerl.hrl (R12B3):
> %% whitespace consists of 'space', 'carriage return', 'line feed' or  
> 'tab'
> -define(whitespace(H), H==?space ; H==?cr ; H==?lf ; H==?tab).

Oddly enough, I already have an EEP (the one on enumerations)
that would handle that with a single guard test.
> %% non-caharacters according to Unicode: 16#ffff and 16#fffe
> -define(non_character(H1,H2),  
> H1==16#ff,H2==16#fe;H1==16#ff,H2==16#ff).

Again, the enumerations EEP would handle that:

	-enum(illegal_unicode, {fffe=16#fffe, ffff=16#ffff}).
	... is_enum_integer(H1*256+H2, illegal_unicode) ...

and so would the is_between/3 EEP:

	... is_between(H1*256+H2, 16#fffe, 16#ffff).


> -define(non_ascii(H), list(H),hd(H)>=128;integer(H),H>=128).

This one makes me slightly queasy; I feel that integers and
strings really ought not to be mushed together like that.

> I would guess these macros were written before the new guard  
> operators, since they can only be used in specific contexts and  
> would be more useful with andalso/orelse. But, mutatis mutandis, I  
> think they are reasonable examples of what is done.

Thank you, they provide clear evidence that we COULD do better.
With hindsight, the need for is_between/3 was always there, we
just hadn't noticed.
>>> 2. I seem to recall that ';' is implemented by
>> duplicating the
>>> clauses, while andalso/orelse is not. If so,
>> andalso/orelse _may_
>>> yield somewhat more compact code.
>> Ah, the old "I seem to recall" trick.
> "Trick"? You got me, Richard. I always argue in bad faith.

Sorry, too much "Get Smart" lately.
"The old .... trick" never refers to bad faith,
but to a bad idea (like relying on recollection instead of
what the compiler does).  Before I did the check, I was
sure the compiler did the sensible thing; imagine my surprise
that it didn't!

More information about the erlang-questions mailing list