# Procedure Definitions

## The Problem: Naming Expressions

In previous labs, you've seen that it's possible to define complex expressions from simpler expressions. For example, we might write the following for ```grade` is between 0 and 100, inclusive''.

```> (and (>= grade 0) (<= grade 100))
```

What happens when we want to try this expression using different grades? One possibility is to redefine grade and then reexecute the expression.

```> (define grade 55)
#t
#f
#t
```

But this seems cumbersome. It would be nice to simply give a name to this expression and use that name. Unfortunately, our current way of naming doesn't quite work.

```> (define valid (and >= grade 0) (<= grade 100)))
> (valid)
#t
> (valid)
#t
```

What's going on? Scheme evaluated the expression that accompnaies `valid` once, when it was first defined. Hence, since the expression was true then, it remains true forever after.

What we'd really like to do is to say that ```valid` is a procedure that takes a grade as an input and returns true if khe grade is valid and false otherwise''. You know that Scheme has procedures, since you've used lots of built-in procedures, including `sqrt`, `*`, `cons`, and `list`. But can you define your own procedures? Yes.

## Defining Procedures

You use `define` to give names to procedures, just as you use it to give names for values. The values just look different. The general form of a procedure is

```(lambda (formal-parameters)
expression)
```

For example, we might write our `valid` procedure as

```(define valid
)
)
```

Our `valid` procedure can now be called as if it were a built-in procedure.

```> (valid 100)
#t
> (valid -2)
#f
> (valid 44)
#t
```

We can define procedures for anything we already know how to do in Scheme. For example, here is a simple `square` procedure.

```(define square
(lambda (n)
(* n n)
)
)
```

We can test it.

```> (square 2)
4
> (square -4)
16
> (square square)
*: expects type <number> as 1st argument, given: #<procedure:square>; other arguments were: #<procedure:square>
> (square 'a)
*: expects type <number> as 1st argument, given: a; other arguments were: a
```

Convention in Scheme (and all programming languages) is that we carefully document what our procedures do, including input values, output values, and assumptions. We use comments to provide information to the reader of our program (that is, to people instead of the computer). In Scheme, comments begin with a semicolon and end with the end of the line.

```;;; square: multiply a given number by itself

;;; Samuel A. Rebelsky
;;; Department of Mathematics and Computer Science
;;; Grinnell College
;;; rebelsky@cs.grinnell.edu

;;; Based on code created by John David Stone dated March 17, 2000
;;; and contained in the Web page
;;; http://www.math.grin.edu/~stone/courses/scheme/procedure-definitions.xhtml

;;; Changes to
;;;   Parameter names
;;;   Formatting

;;; Given:
;;;   value, an exact number.

;;; Result:
;;;   squared, an exact number.

;;; Preconditions:
;;;   None.

;;; Postcondition:
;;;   squared is the square of value.

(define square
(lambda (value)
(* value value)
)
)
```
```;;; valid: Determine if a grade is valid.

;;; Samuel A. Rebelsky
;;; Department of Mathematics and Computer Science
;;; Grinnell College
;;; rebelsky@cs.grinnell.edu

;;; Created 4 September 2000

;;; Given:

;;; Result:
;;;   a boolean value

;;; Preconditions:
;;;   None.

;;; Postcondition:
;;;   Returns #t if the grade is valid according to our definition.
;;;   Returns #f otherwise.

(define valid
)
)
```

## Procedures with More Than One Parameter

At times, we'll want to write procedures that take more than one parameter. Such procedures look just like procedures with one parameter, except that you can list more parameters between the parentheses.

```(lambda (param1, param2 ... paramn)
expression
)
```

For example, here is a simple procedure that finds the average of two nubmers

```;;; pairave: Compute the average of two numbers.

;;; Samuel A. Rebelsky
;;; Department of Mathematics and Computer Science
;;; Grinnell College
;;; rebelsky@cs.grinnell.edu

;;; Created 4 September 2000

;;; Given:
;;;   val1, val2, two exact numbers.

;;; Result:
;;;   ave, an exact number.

;;; Preconditions:
;;;   None.

;;; Postcondition:
;;;   ave is the average of val1 and val2, a value equidistant from
;;;   val1 and val2.

(define pairave
(lambda (val1 val2)
(/ (+ val1 val2) 2)
)
)
```

## History

Monday, 4 September 2000

• Created.

Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.