Conditional Expressions and Predicates

Review on Conditionals

We used if and conditionals in our first lab. In this section, we will flesh out more details.

We generally use an if or a cond when we want our function to behave differently depending on a certain condition. Note that these two functions are special forms in Racket; we don't evaluate them using the usual "evaluate the operands fully, and then apply the operator" method.

cond Examples

The general form of a cond expression is:

(cond  (<test1> <result1>)
       (<test2> <result2>)
       ...
       (<testn> <resultn>)
       (else <default>))  ;; The 'else' case is optional

Each (<test> <result>) pair is called a clause. The first part of each pair (the <test>) is a predicate—an expression that must evaluate to either true or false.

To evaluate a cond expression, start by evaluating <test1>. If it is true, evaluate and return <result1>. If <test1> is false, repeat for <test2>, and so on until there are no more tests. If you hit an else, return the value corresponding to it (the "default value").

You can write a cond expression as a series of 'if' statements:

(if <test1>
    <result1>
    (if <test2>
        <result2>
        ...
        (if <testn>
            <resultn>
            <default>) ;; Closing parentheses omitted

Exercise

The function plural below takes in a word and returns its plural form. For example, (plural 'carrot) returns 'carrots and (plural 'body) returns 'bodies. It does not perform correctly for (plural 'boy), which should return 'boys; the buggy version below returns 'boies instead.

(define (plural wd) 
  (if (equal? (last wd) 'y) 
      (word (bl wd) 'ies)
      (word wd 's)))
Choose which line of code to add in the blank below so that (plural 'boy) behaves correctly (that is, it should return boys). Suppose `vowel?` is defined as before.
(define (plural wd) 
  (if __________________
      (word (bl wd) 'ies)
      (word wd 's)))

Predicate and Style

A predicate is any expression that returns true or false. Some examples include (< 3 4),(> 10 -2), and (= 'apple 'orange). You can form compound predicates by using and, or, and not.

Here is an example of a predicate:

(define (even? x)
  (= (remainder x 2) 0))

When defining a predicate, it is conventional to end the name of the procedure with a question mark (?).

Here's another way to define even?:

(define (even? x)
  (if (= (remainder x 2) 0)
      #t
      #f))

Although this definition is equivalent to the original definition above, it contains redundancies. We urge you to avoid writing code like this. Redundant code can make your programs more difficult to understand, and is typically considered an example of bad programming style.

Exercises

We define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers

For example, (max-sum-squares 1 2 3) returns 13, which is 4 + 9

Why isn't the code below correct?
(define (square x) (* x x))

    (define (max-sum-squares a b c) (max (+ (square a) (square b)) (+ (square b) (square c)) (+ (square a) (square c))))

PRACTICE QUESTION: Write a procedure pigl that takes a word as an argument and returns that word in pig latin. Here are the rules for pig latin:

If the input word starts with a vowel then we append "ay" to the input.

If the input word starts with a consonant then we move all the starting consonants to the end of the word and then append "ay" to the end.

Here are some examples:

(pigl 'hello) ; ellohay 
(pigl 'open) ; openay 
(pigl 'scheme) ; emeschay

What happens if our input doesn't have a vowel, like (pigl 'my)? Make sure your pigl checks if a word has no vowels and just returns that word directly.

(pigl my) ; my

Check your answer in your Racket interpreter with the examples above!