11.5.1 if, else, and elseif

We showed the simplest use of if in Section 5.1.3, page 54. Consider the case where there is more than one test involved. Suppose that we want to write a method that describes a vote. Here are sample calls to interpret-votes:

? interpret-votes(yes: 4, no: 0);
"unanimously approved"
? interpret-votes(yes: 3, no: 1);
"approved"
? interpret-votes(yes: 2, no: 2);
"tie"
? interpret-votes(yes: 1, no: 3);
"not approved"

We can define the interpret-votes method using the if control structure and the else clause:

define method interpret-votes 
    (#key yes :: <nonnegative-integer> = 0, no :: <nonnegative-integer> = 0) 
 => (interpretation :: <string>)
  if (yes > 0 & no = 0) 
    "unanimously approved";
  else if (yes > no) 
    "approved";
  else if (yes = no) 
    "tie"; 
  else
    "not approved";
  end if;
  end if;
  end if;
end method interpret-votes;

We defined the <nonnegative-integer> type in Section 9.2, page 110, using limited. Only positive integers and the integer 0 are instances of <nonnegative-integer>. We use this type in the interpret-votes method parameter list to ensure that no negative vote counts are accepted.

Quick summary of & infix operator: arg1 & arg2

The infix operator & does the and logical operation. If either or both of the arguments to the & operator are false, then & returns false.

Note that the & operator is actually a control-flow operator. If the first argument to the & operator is false, then the value of the second argument is never computed, and false is returned. If the value of the first argument is true, then the value of the second argument is computed and returned.

The | operator (logical or) behaves in a similar manner, except that its second argument is computed and returned only if the first argument is false.

The syntax for the if control structure allows elseif clauses, which makes this style of conditionalization slightly more compact:

define method interpret-votes 
    (#key yes :: <nonnegative-integer> = 0, no :: <nonnegative-integer> = 0)
 => (interpretation :: <string>)
  if (yes > 0 & no = 0) 
    "unanimously approved";
  elseif (yes > no) 
    "approved";
  elseif (yes = no) 
    "tie";
  else 
    "not approved";
  end if;
end method interpret-votes;