# Scheme Programming/Conditionals

 Scheme Programming ← Using Variables Conditionals Procedures →

In this section we introduce Scheme's conditional expressions. These forms allow us to make choices--something that's been lacking from the simple programs we've seen so far.

## Truth values in Scheme

We've already seen the boolean values `#t` ("true") and `#f` ("false") in previous examples, as the values of expressions like `(< 3 5)`. Booleans have few procedures ; the most commonly seen is probably `not`, which negates its argument:

```> (not #t)
#f
> (not #f)
#t
```

In Scheme, booleans are not the only objects with truth values; the convention of Scheme is to consider `#f` to be false and every other Scheme value to be true. A very common idiom in Scheme is for procedures to return some useful value (which is rarely `#t`) on success, and `#f` otherwise. While our procedures will stick to the practice of returning `#t`, it's important to be aware of this idiom.

## and and or

The `and` and `or` forms let us manipulate truth values in familiar ways:

```> (and #t #f)
#f
> (or #f (not #f))
#t
> (and (> 3 2) #t)
#t
> (or (<= 3 2) (zero? (- 10 3)))
#f
```

In this basic usage, these forms give us the Boolean AND and OR, respectively, of their two arguments (called tests). This is often perfectly sufficient. The `and` and `or` forms, however, are a bit more flexible. For one thing, they can take any number of tests:

```> (and (> 3 2) (>= 5 4) (> 10 9))
#t
> (or (<= 2 3)
(zero? (- 10 3))
#f
(> 3 5))
#t
```

An `and` expression is thus true if all the tests are true, and an `or` expression is true if at least one of the tests is true.

As mentioned above, we can also have tests that evaluate to things other than `#t` and `#f`:

```> (and (> 3 2) 5)
5  ; ?
```

Since the first test expression evaluates to `#t` and the second to `5` (which is not `#f`, the only Scheme value considered false), this `and` expression must be true--but why does it evaluate to `5`? The Scheme convention is that `and`, when all the tests are true, returns the value of the last test; `or` returns the value of the first true test. In this way, we can return values more useful than `#t` without affecting the truth values of our expressions.

## Simple Conditionals: if

The simplest conditional in Scheme is the `if` form. Here are some examples:

```> (if #t 1 0)
1
> (if (>= 5 8) 3 (+ 7 2))
9
```

Like `and` and `or`, `if` is a special form with its own syntax. Here's the general form:

```(if test consequent alternative)
```

The first component of an `if` expression is a test expression, which is evaluated first. If its value is true, the value of the second component expression (the consequent) is returned. If the test evaluates to false, on the other hand, we get the value of the third component (the alternative). Let's see how this works in the above examples. In the first, the test expression is just `#t`, so the value of the `if` form is the value of the consequent expression, `1`. To evaluate the second example, we first consider the test, `(>= 5 8)`. This evaluates to `#f`, so we evaluate the alternative `(+ 7 2)` and return its value as the value of the entire `if` expression.

Using `if`, we can write some useful procedures. A simple example:

```(define (absolute-value n)
(if (positive? n)
n
(- n)))  ; with one argument, - gives the additive inverse
```

Using `and` and `or` forms in our test expressions, we can combine several tests:

```(define (days-in-year y)
(if (or (= (floor-remainder y 400) 0)
(and (= (floor-remainder y 4) 0)
(not (= (floor-remainder y 100) 0))))
366  ; leap year
365))
```
Exercises
1. Rewrite `days-in-year` without `and` or `or`; express the test using only `if`.

## cond

We can write a great number of useful Scheme programs with `if`. In fact, by chaining together `if`s, we can write any conditional expression we want. Unfortunately, these expressions get complicated very quickly. When nesting `if`s, it can be difficult to keep track of all the clauses and it may be necessary to write results several times. (For example, in the last exercise, how many cases are there in which `366` is the answer?) In these cases, we'd like something more convenient.

For this reason, Scheme provides `cond`, an extremely flexible conditional form which allows multi-way choices to be expressed easily. Here's a short example:

```(cond ((> 5 6) 7)
((= 3 (+ 1 2)) 4)
(else 8))
```

In its simplest form, `cond` takes a number of clauses, each of which consists of a test and a result expression. To evaluate a `cond` expression, we evaluate the tests of each clause in turn; if one evaluates to true, `cond` returns the value of that clause's result expression, skipping any remaining clauses. A test which is just the word `else` is always true, and thus a `cond` will always "choose" the result of a clause with `else` as its test. Typically, the last clause of a `cond` is an "else clause".

A simplified version of the form of a `cond` expression is:

```(cond clause1 clause2 ...)
```

where each clause is of the form `(test result)` or `(else result)`.

Let's step through the evaluation of a simple `cond` expression.

```(cond ((>= 5 8) 3)
(else (+ 7 2)))
```

To evaluate this expression, we look at the first clause, `((>= 5 8) 3)`. The test expression of this clause is `(>= 5 8)`, so we evaluate that; since its value is `#f`, we skip this clause and go on to the next, `(else (+ 7 2))`. The test of this clause is `else`, which is "always true". We evaluate this clause's result expression, `(+ 7 2)`, and return its value, `9`, as the value of the whole `cond` expression. Since this `cond` expression returns `3` when the first clause's test is true and `9` otherwise, it's precisely equivalent to the following `if` form:

```(if (>= 5 8) 3 (+ 7 2))
```

Thus, we can replace any `if` expression with an equivalent `cond`. In fact, `cond` is so general that we can use it in place of any other conditional form.