## Variables

Let's consider how you would write a function to convert from dollars to pounds. The procedure is as follows:

- Multiply the number of dollars by the exchange rate.

The exchange rate is the number of pounds in 1 dollar; let's say today it's 0.61. So our procedure definition is simply:

(defun convert (dollars) (* dollars 0.61))

We call it as follows:

CL-USER > (convert 100) 61.0

In the definition of **convert**, the symbol **dollars** is a *variable*. It's like a box into which we put any value we want to convert to pounds.

Furthermore, it's called a *local variable* because the value is only available inside the body of the function. If we try and evaluate **dollars** outside the procedure we get:

CL-USER > dollars

Error: The variable DOLLARS is unbound.

Unbound is another way of saying that it doesn't have a value.

### Defining a variable: defparameter

But one problem with **convert** is that we have to redefine it if the exchange rate changes. What we need is a variable that we can set to the current exchange rate. We can do that with **defparameter**:

(defparameter exchange-rate 0.61)

Variables defined by **defparameter** are called *global variables* because you can refer to them anywhere.

CL-USER > exchange-rate 0.61

So now we can redefine **convert** to use the **exchange-rate** variable:

(defun convert (dollars) (* dollars exchange-rate))

A common convention is to give each global variable a name starting and ending with an asterisk, such as ***exchange-rate***, to remind you that it's global.

### Changing the value of a variable: setf

To change the value of a variable we can use **setf**. For example, if the exchange rate changes to 0.7:

(setf exchange-rate 0.7)

Now the **convert** procedure will automatically reflect the new exchange rate:

CL-USER > (convert 100) 70.0

### Creating local variables: let*

The **let*** construct allows you to define one or more variables, with specified initial values, which are local to the body of the **let*** construct. It is written like this:

(let* ((var1 value1) (var2 value2) ...) body)

where:

**var1**is the first local variable and**value1**is its initial value.**var2**is the second local variable and**value2**is its initial value, and so on.**body**is one or more Lisp procedures that can refer to**var1**and**var2**.

As an example of its use, remember our definition of the **average** procedure:

(defun average (1st-number 2nd-number)

(/ (+ 1st-number 2nd-number) 2))

The parameters **1st-number** and **2nd-number** are local variables, local to the body of the procedure.

But suppose we wanted to break the calculation into steps, using a local variable **sum** to store the sum of the two numbers, and another local variable **result** to store the result of dividing this by 2.

We could do this with **let***:

(defun average (1st-number 2nd-number) (let* ((sum (+ 1st-number 2nd-number)) (result (/ sum 2))) result))

Note that the asterisk in **let*** is part of the name - **let*** is a more general version of an operator called **let**; we won't worry about the differences at this stage.

### Exercises

#### 1. Convert between km and miles

Define a variable using **defparameter** to represent:

1 kilometer = 0.621371192 miles

Use this to define two procedures, **convert-km** and **convert-miles**, that convert miles to km and km to miles, and check that 80 km converts to about 50 miles.

#### 2. Find the average of three numbers

Define a procedure **average3** that finds the average of three numbers.

Check that:

(average3 21 7 8)

gives 12.

#### 3. Cube the sum of two numbers

Here's a procedure **cubesum **that calculates (a + b) x (a + b) x (a + b):

(defun cubesum (a b) (* (+ a b) (+ a b) (+ a b)))

Use **let*** to write it so (a + b) is only calculated once.

Check that:

(cubesum 3 4)

gives 343.

#### 4. Substitute values into a quadratic equation

Write a procedure **pseudo-primes** that substitutes x into the quadratic equation:

*x*^{2} - *x* + 41

Check that:

(pseudo-primes 40)

gives 1601.

blog comments powered by Disqus