Conditionals
| Contents |

Conditionals implement decision points in a computer program. Suppose you have a program that performs some task on an image. You may well have a point in the program where you do one thing if the image is a JPEG and quite another thing if the image is a GIF file. Likely, at this point, your program will include a conditional expression to make this decision.

Before learning about conditionals, it is important to
learn about logical expressions. Such expressions are the
core of conditionals and loops.^{3}

A logical expression evaluates to a truth value, in essence true or
false. For example, the expression `(> x 0)`

resolves to true if *x* is positive
and false if *x* is negative or zero. In Scam, truth is represented by
the symbol `#t`

and falsehood
by the symbol `#f`

.
Together,
these two symbols are known as * Boolean* values.

One can assign truth values to variables:

(define c -1) (define z (> c 0)) (inspect z) -> z is #f

Here, the variable *z* would be assigned true
if *c* was positive;
since *c* is negative, however, it is assigned false.

Scam has the following logical operators:

= | numeric equal to |

!= | not equal to |

> | greater than |

>= | greater than or equal to |

< | less than |

<= | less than or equal to |

== | pointer equality |

neq? | pointer inequality |

eq? | pointer equality |

equal? | structural equality |

and | and |

or | or |

not | not |

The first ten operators are used for comparing two (or more) things, while the last three operators are the glue that joins up simpler logical expressions into more complex ones.

When evaluating a logical expression, Scam evaluates the expression from left to right and stops evaluating as soon as it finds out that the expression is definitely true or definitely false. For example, when encountering the expression:

(and (!= x 0) (> (/ y x) 2))

if *x* has a value of 0, the subexpression on the left side of the
*and*
connective resolves to false. At this point, there is no way for the
entire expression to be true (since both the left hand side and the right
hand side must be true for an
*and*
expression to be true), so the right
hand side of the expression is not evaluated. Note that this expression
protects against a divide-by-zero error.

Scam's *if* expressions are used to conditionally execute code,
depending on the truth value of what is known as the
*test* expression. One version of *if* has a single expression
following the test expression:

Here is an example:

(if (equal? name "John") (println "What a great name you have!") )

In this version, when the test expression is true (*i.e.*,
the string `"John"` is bound to the variable *name*),
then the following expression is evaluated
(i.e., the compliment
is printed).
If the test expression is false, however the
expression following the test expression is not evaluated.

Here is another form of *if*:

(if (equal? major "Computer Science") (println "Smart choice!") (println "Ever think about changing your major?") )

In this version, *if* has two expressions following
the test.
As before, the first expression is evaluated if the test expression
is true. If the test expression is false, however,
the second expression is evaluated instead.

You can chain `if` statements together, as in:

(if (== bases 4) (print "HOME RUN!!!") (if (== bases 3) (print "Triple!!") (if (== bases 2) (print "double!") (if (== bases 1) (print "single") (print "out") ) ) ) )

The expression that is eventually evaluated is directly underneath the first test expression that is true, reading from top to bottom. If no test expression is true, the second expression associated with the most nested if is evaluated.

The *cond* function takes care of the awkward indentation
of the above construct:

(cond ((== bases 4) (print "HOME RUN!!!")) ((== bases 3) (print "Triple!!")) ((== bases 2) (print "double!")) ((== bases 1) (print "single")) (else (print "out")) )

The general form of a *cond* function call is:

(cond (expr1 action1) (expr2 action2) ... (else actionN))

where *expr1*, *expr2*, and so on are Boolean expressions. In addition
to its compactness, another advantage of a *cond* is each action
portion of a clause is really an implied block. For example,
suppose we wish to debug an *if* expression and print out a
message if the test resolves to true. We are required to insert
a *begin* block, so:

(if (alpha a b c) (beta y) (gamma z) )

becomes:

(if (alpha a b c) (begin (println "it's true!") (beta y) ) (gamma z) )

On the other hand:

(cond ((alpha a b c) (beta y) ) (else (gamma z) ) )

becomes:

(cond ((alpha a b c) (println "it's true!") (beta y) ) (else (gamma z) ) )

Note the lack of a *begin* block for *cond*.

Conditionals
| Contents |