exported variables (was: RE: How to make GS Widgets)

Richard A. O'Keefe ok@REDACTED
Mon Apr 19 04:56:29 CEST 2004


Cedric Shock <cedricpublic@REDACTED> wrote:
	For its brevity and the way it makes the purpose of the code clear. I 
	have been bothered by the weekness of my quards, but I do not know how 
	to make them stronger. How can I put gaurds on the values of members of 
	tuples? For example, I would like the SuppliedColor to be integers in 
	the range [0, 255]. How could I write this guard clause? Is this the 
	right thing to do?
	
	{Red,Green,Blue} = case SuppliedColor of
	                         {TestRed,TestGreen,TestBlue} when
	                           is_integer(TestRed),
	                           is_integer(TestGreen),
	                           is_integer(TestBlue),
	                           TestRed =< 255, TestRed => 0,
	                           TestGreen =< 255, TestGreen => 0,
	                           TestBlue =< 255, TestBlue => 0,  ->
	                             SuppliedColor;
	                         _ ->
	                             {0,0,0}
	                    end
	
Good programmers are lazy and have excellent precognitive skills.
More truthfully, they have learned a number of language-independent
rules of thumb which do the precognition for them.  One of those
rules of thumb is

    "If you have a data type, you probably want a recogniser for it."

If I'm going to be dealing with colours in a program, I'm going to
start by writing a comment that says what a "colour" looks like AND
by writing a function which checks whether something is a colour.
Even in a statically typed language there are often aspects of a data
structure which cannot be checked by the type checker; in Haskell I'd
have

    type Colour = (Int,Int,Int)
    
    is_colour (r,g,b) =
        0 <= r <= 255 && 0 <= g <= 255 && 0 <= b <= 255

because the Haskell type system cannot express the range constraints.

So in Erlang, let's write

    is_colour({R,G,B})
       when integer(R), 0 <= R, R <= 255, % Red component
            integer(G), 0 <= G, G <= 255, % Green component
            integer(B), 0 <= B, B <= 255  % Blue component
       -> true;
    is_colour(_) -> false.

and then write

    {Red,Green,Blue} = case is_colour(SuppliedColor) of
                           true  -> SuppliedColor;
                           false -> {0,0,0}
                       end
                           

If the alternatives are "a valid colour" and "something which is not
a 3-tuple", then there's no need to do the full check; on the other hand
there's no harm in it either.

The abstract patterns stuff I proposed a few years ago (which turns out to
be _almost_ but not quite the same thing as 'views' that have been implemented
in some versions of Haskell) would let you set up an abstract pattern:

    #colour(R,G,B)
        when integer(R), 0 <= R, R <= 255,
             integer(G), 0 <= G, G <= 255,
             integer(B), 0 <= B, B <= 255
        -> {R,G,B}.

and then you would be able to write

    {Red,Green,Blue} = case SuppliedColor of
		           #colour(_,_,_) -> SuppliedColor;
		           _              -> {0,0,0}
		       end

Just as Joe Armstrong would really like to see !! in Erlang because it can
do a lot of things, so I would like to see abstract patterns in Erlang because
they can make some code a lot clearer.

Until then, is_colour/1 is the way to go.



More information about the erlang-questions mailing list