11) X and Y are both Booleans. Which of the following always assigns True? Why?

(a) Z = Not X Or Y = X Imp Y

(b) Z = X Imp Y = Not X Or Y

(c) Z = X Eqv Y = Not X XOr Y

(d) Z = Not X XOr Y = X Eqv Y

(a) assigns False if X and Y are both False. The others assign True no matter what X and Y are. However, these are not as straightforward as you might think.

Imp is the "logical implication" operator. X Imp Y means "If X is True then Y is True". It is always True unless X is True and Y is False.

Eqv is the "logical equivalence" operator. X Eqv Y is True if X and Y are both True or both False.

Why do we need Eqv -- isn't that the definition of "equals"? The difference is that if given numbers instead of Booleans, these do the same logic on corresponding pairs of bits.

If two logical expressions are always equal no matter what the values of their variables are, then they are logically identical. Such a relationship is called an "identity". These are clearly identities:

(a) Z = ((Not X) Or Y) = (X Imp Y)

(b) Z = (X Imp Y) = ((Not X) Or Y)

(c) Z = (X Eqv Y) = (Not (X XOr Y))

(d) Z = (Not (X XOr Y)) = (X Eqv Y)

No matter what Boolean values X and Y are, Z will always be True. The trick here though is the operator precedence. Just like 1 + 2 * 3 is 7, not 9, these guys all have precedence. To show the precedence with brackets, the expressions I actually asked about are equivalent to

(a) Z = (((Not X) Or (Y = X)) Imp Y)

(b) Z = (X Imp ((Y = (Not X)) Or Y))

(c) Z = (X Eqv ((Y = (Not X)) XOr Y))

(d) Z = (((Not X) XOr (Y = X)) Eqv Y)

It is much less clear now that the last three are identities. The moral of the story is to be very careful with operator precedence when using logical operators -- equals binds tighter than Or!

12) Consider this program:

s = "Eric read Æsop's Fables"

arr = Split(s, "e", -1, 1)

arr is an array with how many elements?

(a) 2

(b) 3

(c) 4

(d) 5

It's (c). The parts are "", "ric r", "ad Æsop's Fabl", "s"

The 1 means "go case insensitive". I agonized over whether or not Split should split on matches to ligature characters. It gave me grief because this *does* work:

print Instr(1, "xxxÆxxx", "e", 1)

That finds the "e" inside the ligature, so why shouldn't Split split on the ligature? Basically, we just decided that it was *too weird* to split a string in the middle of a ligature. I was never very happy with this decision, and if I had to do it again, I probably would decide the other way. But it's too late now!

Wow, that took longer than I expected. Coming up next, a short break from scripting.