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