"argument" "function" "rec" "recursion" "side effect" "tail recursion" Syntax: let [rec] [arg] [. . .] = ;; A "function" is code that may take arguments as input and produce a single argument as output. In a 'pure' functional language a function has no other contact with the rest of the program besides taking arguments and returning a value, but OCaml (like languages that have a more imperative syntax) allows limited side effects. Usually, it's a good idea to avoid side effects, particularly when doing functional programming. "Recursion" is where a function calls itself. A favored optimization of recursive functions is to use "tail recursion", where the call to itself is the absolute last action taken by the function in each run-through. An "argument" is a value passed to a function. Calling a function with arguments involves naming the function and the arguments that are passed to it. Such arguments may be a literal "expression", a literal "value" such as a "string" or "integer", or a "named expression". "Side effects" are changes to "state" in other parts of the program that are caused by behavior within a function. Because OCaml is primarily a functional, rather than imperative, programming language, it does not by default encourage the use of side effects. Instead, altering state outside of a given function is accomplished using the return value of the function. Because OCaml includes imperative and object oriented programming constructs, however, it is possible to program with side effects when that is needed. Named function definitions can take this form: let foo bar baz = code; more code;; In this example, 'foo' is the name of the function, while 'bar' and 'baz' are the names given to incoming, lexically scoped arguments. Named functions can be made recursive thusly: let rec foo = if condition then return-value else foo;; In this example, we see the "rec" keyword before the function name, used to indicate that the function should allow recursion. The 'rec' keyword can be used for nonrecursive functions as well, though it's usually a good idea to avoid using the keyword when the function isn't recursive, simply for clarity of your source code. This is a working example of a normal function definition and a call to it in an assignment: let increment i = i + 1;; let number = increment 7;; The above code causes 'number' to produce a value of 8. It starts by using the 'let' keyword to declare a named expression 'increment', which takes exactly one argument. The argument is given the label 'i' within the function so that it may be used without having to know values or named expressions will be passed to the function as arguments at the time it is defined. This is analogous to using a lexical or local variable in another language inside your function called 'i', except that unlike other languages 'i' is not a variable and cannot be assigned a different value later in its scope. It is, like the named function to which it belongs, a named expression -- in this case, a "named local expression" that is contained within the scope of the function declared with the name 'increment'. The expression 'i' names is the expression passed to it by the function call, in this example 'increment 7'. In practical terms, this means that 'i' names the expression '7' within the scope of the function 'increment'. This is not a "reference" to the same expression that may be named elsewhere, though. Instead, it is a named local expression: a copy of the argument that was passed to it, with scope local to the named function for which it is defined (in this case, increment). Once that function exits, the named local expression 'i' ceases to exist, and any named local expressions that existed in an enclosing scope are unchanged -- because of the lack of side effects. This is a working example of a recursive function definition, and a call to the function: let rec increment_loop n i = if i <= 1 then n else increment_loop (n + 1) (i - 1);; let number = increment_loop 357 10;; The above code causes 'number' to produce a value of 366. When the function is called with the values 357 and 10 as arguments 'n' and 'i', respectively, it first tests to determine whether 'i' is less than or equal to 1. If so, it prints 'n' to standard out. Because 'i' begins at 10, the else condition is met, and the function calls itself, decrementing 'i' and incrementing 'n' in the process. With an initial value of 10, that means that recursions occur for a total of ten function executions. Because the decrement and increment operations are both part of the recursive call, that means that nine decrements of 'i' and increments of 'n' occur, total. Because the call to increment_loop is the last operation performed by increment_loop (the two arguments are part of that call), this is a tail-recursive function. As you might have guessed, based on the above examples, functions may be called after they are defined. If the above function calls were placed before the function definitions, however, they would not operate properly because lines ending in ;; are executed in sequential procedural order. In other words, a function must already exist, reading from top to bottom, before a call to it can be executed.