In computer code, one may want to formulate an expression to achieve some particular purpose, such as to express some condition about the states of variables involved in the code. For example, suppose that you want to express the condition that a sequence s contains at least two members, and that the second member of s is not the space character (with ASCII code 32). This condition holds when the expression below is true.
(SIZE(s) > Int 1) ∧ (NOT(ASC(AT(2,s)) = Int 32))
When writing expressions involving functions and binary operations, there are some points to be careful about. One needs to be careful to use brackets as necessary to ensure that operations are applied in the desired order. This is particularly important in expressions using infix notation. You also need to apply each process in a way that is consistent with its signature. And you must apply each process in a way that is consistent with any precondition that it has. We say that an expression is not valid if it uses a function in a way that is inconsistent with its signature or its precondition. For example, ‘Q’ =Int 32 is not valid, since =Int compares two integers, and ‘Q’ is a character, while PUT(7, “This”, ‘Q’) is not valid, since 7 does not satisfy the precondition of PUT. (The precondition of PUT requires that 7≤ SIZE(“This”), but SIZE(“This”) is 4.)
The functions SIZE and AT were described in Activity 16, and the function ASC was described in Section 4.3. The binary operations =Int , >Int and ∧ are defined earlier in this section.
(a) With s = “I#am.”, evaluate each of the expressions:
(i) AT(2, s).
(ii) ASC(AT(2, s)).
(iii) ASC(AT(2, s)) =Int 35.
(iv) NOT(ASC(AT(2, s)) =Int 35).
(v) (SIZE(s) >Int 3) ∧ (NOT (ASC (AT (2, s)) =Int 35)).
(b) Let s be a general string. Under what circumstances does the expression in (a) (v) give the value true? Under what circumstances is that expression valid?
(c) With s = “I#am.”, why is it not possible to evaluate the expression
(ASC(AT(2,s)) = Int 35)?
(a) (i) AT(2, s) = ‘#’.
(ii) ASC(AT(2, s)) = 35.
(iii) ASC(AT(2, s)) =Int 35 becomes 35 =Int 35, which evaluates to true.
(iv) NOT(ASC(AT(2, s)) =Int 35) becomes NOT (true) = false.
(v) We have SIZE(s) = 5 (the number of characters in the string “I#am.”), so (SIZE(s) >Int 3) becomes (5 >Int 3) which is true. So the expression in (v) becomes true ∧ false = false.
(b) The given expression will be true only if each of SIZE(s) >Int 3 and NOT(ASC(AT(2, s)) =Int 35) is true. The first of these is true if the string s contains at least four characters. The second is true if the second character is s is not the character ‘#’. So the expression in (a) (v) will be true if:
the string s contains at least four characters and its second character is not ‘#’.
The precondition of AT requires here that the string s contains at least two characters. The expression in (a) (v) will be valid so long as this is true. (All the other functions in the expression are total. The example in part (a) indicates that the expression is put together in a way that is consistent with the signatures of the functions.)
(c) AT(2,s) = ‘#’. Then AT(2,s) =Int 35 becomes ‘#’ =Int 35. This expression is not valid, since =Int requires two integers as inputs, and ‘#’ is a character. So the given expression is not valid.
Notice how important the brackets are in a complicated expression. The order in which the bits of the overall expression are to be evaluated is determined by the way the brackets appear in the expression. We need to follow this carefully in evaluating an expression such as that in Activity 28 (a) (v). A slip in placing one bracket can easily lead to an expression that is not valid, as in (c) above. On the whole, it is good practice when writing computing code to seek to avoid writing complicated expressions. Usually one can split the code into intermediate steps, as indicated by the steps in the evaluation in (a) above.