Functions

Other topics

Defining a Function with a let Binding

Values can be given names using let:

# let a = 1;;
val a : int = 1 

You can use similar syntax to define a function. Just provide additional parameters for the arguments.

# let add arg1 arg2 = arg1 + arg2;;
val add : int -> int -> int = <fun> 

We can call it like this:

# add 1 2;;
- : int = 3 

We can pass values in directly like that, or we can pass values bound to names:

# add a 2;;
- : int = 3 

The line that the interpreter gives us after we define something is the value of the object with its type signature. When we gave it a simple value bound to a, it came back with:

val a : int = 1

Which means a is an int, and its value is 1.

The type signature of our function is a little more complicated:

val add : int -> int -> int = <fun> 

The type signature of add looks like a bunch of ints and arrows. This is because a function that takes two arguments is actually a function which just takes one argument, but returns another function that takes the next argument. You could instead read it like this:

val add : int -> (int -> int) = <fun>

This is useful when we want to create different sorts of functions on the fly. For example, a function that adds 5 to everything:

# let add_five = add 5;;
val add_five : int -> int = <fun>
# add_five 5;;
- : int = 10
# add_five 10;;
- : int = 15 

Using the function keyword

The function keyword automatically has pattern matching when you define the body of your function. Observe it below:

# let foo = function
0 -> "zero"
| 1 -> "one"
| 2 -> "couple"
| 3 -> "few"
| _ -> "many";;
val foo : int -> bytes = <fun>

# foo 0;;
- : bytes = "zero"

# foo 3;;
- : bytes = "few"                                                                         

# foo 10;;
- : bytes = "many"                                                                        

# let bar = function
"a" | "i" | "e" | "o" | "u" -> "vowel"
| _ -> "consonant";;
val bar : bytes -> bytes = <fun>                                                          

# bar "a";;
- : bytes = "vowel"

# bar "k";;
- : bytes = "consonant" 

Anonymous functions

Since functions are ordinary values, there is a convenient syntax for creating functions without names:

List.map (fun x -> x * x) [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)

This is handy, as we would otherwise have to name the function first (see let) to be able to use it:

let square x = x * x
(* val square : int -> int = <fun> *)

List.map square [1; 2; 3; 4]
(* - : int list = [1; 4; 9; 16] *)

Recursive and Mutually Recursive Functions

You can define a function to be recursive with the rec keyword, so it can call itself.

# let rec fact n = match n with
    | 0 -> 1
    | n -> n * fact (n - 1);;

val fact : int -> int = <fun>

# fact 0;;
- : int = 1
# fact 4;;
- : int = 24

You can also define mutually recursive functions with the and keyword, so they can call each other.

# let rec first x = match x with
    | 1 -> 1
    | x -> second (x mod 10)

  and second x = first (x + 1);;

val first : int -> int = <fun>
val second : int -> int = <fun>

# first 20;;
- : int = 1
# first 12345;;
- : int = 1

Notice that the second function does not have the req keyword.

Contributors

Topic Id: 2793

Example Ids: 9420,9421,10940,30713

This site is not affiliated with any of the contributors.