the let expression is the main way to bind a name to a value
since functions are values just like ints or strings, let is also used to define functions
to define simple values:
let name = value
examples:
let filename = "/etc/motd"
let chan = open_in filename
let size = 4 * 1024
to define a function:
let funcname parm1 parm2 ... = body
examples:
let f n m = n * n + m
let mkfilename name = (String.lowercase name) ^ ".ml"
There are two type of let binding: global and local.
Global | Local |
---|---|
let name = value | let name = value in expression |
A name defined via a global let is defined up to the end of the source file (except where shadowed).
A name defined via a local let is defined only within the attached expression.
Legend: let name = expr1 in expr2
let n = 2 in n * n
let list = ["foo";"bar";"baz"] in List.sort list
let x = 10 in print_int (x * 2)
let str = "this is a long string" in Printf.printf "%s, %s, %s!\n" str str str
Local let's can nest:
let x = 10 in let y = 2 in print_int (x * y)
let x = 10 in let y = 2 in print_int (x * y)
Functions being values, you can of course define local functions:
let f n = let m = 456 in let g n = n * n + 1 in m / g n
Confused? You can always redundantly parenthesize:
let f n = ( let m = 456 in ( let g n = n * n + 1 in ( m / g n ) ) )
(But this is unidiomatic.)
A local let is itself an expression:
1 + (let n = 456 in n * n + n * n)
This is why they can nest.
Since let's can nest, inner names can shadow identical outer names.
(let n = 10 in let n = 1 in n * n) = 1
(let n = 10 in n + (let n = 1 in n * n)) = 11
A local let can shadow a global one:
let n = 100 let print100 () = print_int n let print6 () = let n = 6 in print_int n
Global let's can shadow too:
let f x = x + 1 let f x = x ^ "\n"
What happens if the name being defined occurs on the right-hand side of the equals sign (but not after the in), as in this (broken) recursive function definition?
let f x = x * f x in f 6
Answer: the green f is not the same as the blue f! The blue f is either undefined, or a different, previously defined f:
let f x = x + 1 in let f x = x * f x in f 6
The value of the above expression is 42.
Ordinary non-recursive let is useful for re-defining values; especially handy when working interactively. But to write a recursive function, you need to use let rec. Here is factorial:
let rec fac n = if n = 1 then 1 else n * fac (n - 1)