This recitation covers:

- higher-order functions
- anonymous functions
- currying
- side-effects and printing
- exceptions

Functions are values just like any other value in OCaml. What does that mean exactly? This means that we can pass functions around as arguments to other functions, that we can store functions in data structures, that we can return functions as a result from other functions. The full implication of this will not hit you until later, but believe us, it will.

Let us look at why it is useful to have higher-order functions. The first
reason is that it allows you to write more general code, hence more reusable
code. As a running example, consider functions *double* and *square*
on integers:

let double (x : int) : int = 2 * x let square (x : int) : int = x * x

Let us now come up with a function to quadruple a number. We could do it
directly, but for utterly twisted motives decide to use the function *double* above:

let quad (x : int) : int = double (double x)

Straightforward enough. What about a function to raise an integer to the fourth power?

let fourth (x : int) : int = square (square x)

There is an obvious similarity between these two functions: what they do is
apply a given function twice to a value. By passing in the function to another function `twice`

as an argument, we can abstract this functionality and thus reuse code:

let twice ((f : int -> int), (x : int)) : int = f (f x)

Using this, we can write:

let quad (x : int) : int = twice (double, x) let fourth (x : int) : int = twice (square, x)

We have exploited the similarity between these two functions to save work. This can be very helpful. If someone comes up with an improved
(or corrected) version of `twice`

, then every function that uses it profits from the improvement.

The function `twice`

is a so-called *higher-order
function*: it is a function from functions to other values. Notice the type of `twice`

is `((int -> int) * int) -> int`

.

To avoid polluting the top-level namespace, it can be useful to define the function locally to pass in as an argument. For example:

let fourth (x : int) : int = let square (y : int) : int = y * y in twice (square, x)

What happens when we evaluate an expression that uses a higher-order
function? We use the same rules as earlier: when a function is applied (called),
we replace the call with the body of the function, with the argument variables
(actually, variables appearing in the argument pattern) bound to the
corresponding actual values. For example, `fourth 3`

evaluates as follows:

fourth 3 --> (fun x -> let square (y : int) : int = y * y in twice (square, x)) 3 --> let square (y : int) : int = y * y in twice (square, 3)) --> twice (fun (y : int) -> y * y, 3) --> (fun (y : int) -> y * y) ((fun (y : int) -> y * y) 3) --> (fun (y : int) -> y * y) (3 * 3) --> (fun (y : int) -> y * y) 9 --> 9 * 9 --> 81

It seems silly to define and name a function simply to pass it in as
an argument to another function. After all, all we really care about is that `twice`

gets a function that doubles its argument.
Fortunately, OCaml provides a better solution — anonymous functions:

let fourth (x : int) : int = twice (fun (y : int) -> y * y, x)

We introduce a new expression denoting "a function that expects an argument of a certain type and returns the value of a certain expression":

`fun`

` (`

```
)
->
```

The `fun`

expression creates an **anonymous
function**: a function without a name. The type makes things actually clearer.
The return type of an anonymous function is not
declared (and is inferred automatically). What is the type of `fun (y : int) -> y = 3`

?

**Answer: **`int -> bool`

Notice that the declaration

let square : int -> int = fun (y : int) -> y * yhas the same effect as

let square (y : int) : int = y * yIn fact, the declaration without

`fun`

is just Anonymous functions are useful for creating functions to pass as arguments to
other functions, but are also useful for writing functions that return other
functions. Let us rewrite the `twice`

function to take a function as an argument and return a new function that applies the original function twice:

let twice (f : int -> int) = fun (x : int) -> f (f x)

This function takes a function `f`

(of type `int -> int`

) as
an argument, and returns the value `fun (x : int) -> f (f x)`

, which is a function which when applied to an argument
applies `f`

twice to that argument. Thus, we can write

let fourth = twice (fun (x : int) -> x * x) let quad = twice (fun (x : int) -> 2 * x)

and trying to evaluate `fourth 3`

does indeed result in `81`

.

Functions that return other functions are so common in functional programming that OCaml provides a special syntax for them. For example, we could write the twice function above as

let twice (f : int -> int) (x : int) : int = f (f x)

The "second argument" `x`

here is not an argument to `twice`

, but rather an argument to `twice f`

. The function `twice`

takes only one argument, namely a function `f`

, and returns *another* function that takes an argument `x`

and returns an `int`

. The distinction here is critical.

This device is called *currying* after the logician H. B. Curry. At
this point you may be worried about the efficiency of returning an intermediate
function when you're just going to pass all the arguments at once anyway. Run a
test if you want (you should find out how to do this), but rest
assured that curried functions are entirely normal in functional languages, so
there is no speed penalty worth worrying about.

The type of twice is `(int -> int) -> int -> int`

. The
`->`

operator is right associative, so this is equivalent to
`(int -> int) -> (int -> int)`

. Notice that if we had left
out the parentheses on the type of `f`

, we would no
longer long have a function that took in another function as an argument, since
`int -> int -> int -> int`

is equivalent to `int -> (int -> (int -> int))`

.

Here are more examples of useful higher-order functions that we will leave you to ponder (and try out at home):

let compose ((f, g) : (int -> int) * (int -> int)) (x : int) : int = f (g x)

let rec ntimes ((f, n) : (int -> int) * int) = if n = 0 then (fun (x : int) -> x) else compose (f, ntimes (f, n - 1))

Up until now, we have only shown you pure functional programming. But
in certain cases, imperative programming is unavoidable. One such case is
printing a value to the screen. By now you may have found it difficult to
debug your OCaml code without any way to display intermediate values on the
screen. OCaml provides the function `print_string : string -> unit`

to print a string to the screen.

Printing to the screen is called a *side-effect* because it alters the
state of the computer. Until now we have been writing functions that do
not change any state but merely compute some value. Later on we will show
you more examples of side-effects, but printing will suffice for now.

Because of OCaml's type system, `print_string`

is not overloaded like Java's `System.out.println`

.
To
print an `int`

, `float`

, `bool`

, etc, you must first convert it to a string. Fortunately, there are built-in functions to do this conversion.
For
example, `string_of_int`

converts an `int`

to a `string`

. So to print 3, we can
write `print_string (string_of_int 3)`

. The parentheses are needed here bacause OCaml
evaluates expressions left to right.

So how can you put print statements in your code? There are two
ways. The first is with a `let`

expression. These can be placed inside other `let`

expressions,
allowing you to print intermediate values.

let x = 3 in let () = print_string ("Value of x is " ^ (string_of_int x)) in x + 1

There is a second way as well. For this we introduce new syntax.

`(`

`;`

... `;`

` )`

This expression tells OCaml to evaluate expressions *e*_{1},...,*e _{n}*
in order
and return the result of evaluating

let x = 3 in (print_string ("Value of x is " ^ (string_of_int x)); x + 1)

To handle errors, OCaml provides built in exceptions, much like Java. To declare an exception named `Error`

, you write

exception Error

Then to throw the exception, we use the `raise`

keyword. An example using the square root function is

let sqrt1 (x : float) : float = if x < 0 then raise Error else sqrt x

The type of an exception matches the code in which the exception is
thrown. So for example, in the `sqrt1`

function, the type of `Error`

will be
`float`

since the expression must evaluate to a real.

Exceptions can also carry values.
An example is the built-in exception `Failure`

, defined as

exception Failure of string

To raise this exception, we write

raise (Failure "Some error message")

We can also catch exceptions by use of the `try-with`

keywords. It is important not
to abuse this capability. Excessive use of exceptions can lead to
unreadable spaghetti code. For this class, it will probably never be
necessary to handle an exception. Exceptions should only be raised in
truly exceptional cases, that is, when some unrecoverable damage has been
done. If you can avoid an exception by checking bounds or using options,
this is far preferable.
Refer to the OCaml style guide for more examples and info on how to use
exceptions properly.