One minor frustration the Icon programmer may encounter is the problem of storing boolean values in a variable. Icon of course has no boolean type, and it doesn’t really make sense to add one, because its conditional tests in if
expressions and loops aren’t based on a boolean evaluation (rather, they’re based on whether an expression succeeds or not, which is a very different thing).
So, the following simple code in Java is actually a little awkward to translate into Icon :-
boolean b;
int i;
....
b = (i > 0);
....
if (b) {
/* i is > 0 */
....
}
Since there is no boolean type in Icon, we have to choose values to represent true and false. It makes sense to choose &null
for false, since we can then use the \
and /
operators to test the variable for its boolean value. We then have to choose a value for true, which just has to be any non-null value, say the string “yes”. The above java code can then be translated as :-
local b, i
....
b := if i > 0 then "yes" else &null
....
if \b then {
# i is > 0
....
}
The thing I never really liked about the above technique was the arbitrary nature of the non-null value for representing true. Whatever value is chosen, it won’t match well with &null
, and will be impossible to distinguish from a value having a non-flag meaning.
Therefore Object Icon has a value (and type) especially for the purpose of a flag value. This value is &yes
, and it is the only value of a builtin type, “yes”. In a way, it is a mirror of &null
, which is of course the only value of type “null”. Like &null
, &yes
doesn’t support any operators (other than /
and \
), and it is always quite clear that it’s being used as a flag.
The above example works the same, but the assignment to b
now looks rather more symmetrical :-
b := if i > 0 then &yes else &null
For the sake of readability, there is also a keyword, &no
, which is just a synonym for &null
(they are both entirely interchangeable).
Yes
and No
proceduresThe util.Yes
procedure takes an expression, and returns &yes
or &no
depending on whether the expression succeeds or fails. Yes
never fails. util.No
is just the same, but returns &no
instead of &yes
on success of the expression, and vice versa.
They are very useful to reduce the clutter caused by if
expressions, such as the one assigning to b
in the example above. Using Yes
, it can be rewritten :-
b := Yes{ i > 0 }
which is much more concise.
There are a handful of other utility procedures which make flag handling a little easier. util.flag
is a conversion procedure which tries to deduce a &yes
or &no
value from its parameter. util.need_flag
checks if its parameter is &yes
or &no
and exits with a runtime error otherwise. Finally, util.toggle_flag
inverts a flag value. The source for these very simple procedures, as well as Yes
and No
, can be seen in this file.