3.3. functions

Another builtin that creates a nested scope is fn, which is used to create a user-defined function, which can be used to simplify repetitive code, amongst other things:

(import* math)

(def add-and-trace
  (fn
    (a b)
    (trace (+ a b))))

(add-and-trace 1 2)
(add-and-trace 3 4)
trace (+ a b): <num= 3>
trace (+ a b): <num= 7>

Here a function add-and-trace is defined. When defining a function, first the names of the parameters have to be given. The function defined here takes two parameters, a and b. The last part of the function definition is called the function body.

A function created using fn can be called just like an operator. When a function is called, the parameters to the function are defined with the names given in the definition, and then the function body is executed. The previous example is equivalent to the following:

(import* math)

(def add-and-trace
  (fn
    (a b)
    (trace (+ a b)))

(do
  (let a 1
       b 2)
  (trace (+ a b)))

(do
  (let a 3
       b 4)
  (trace (+ a b)))
trace (+ a b): <num= 3>
trace (+ a b): <num= 7>

In alv, functions are first-class values and can be passed around just like numbers, strings, etc. However it is very common to define a function with a name, so there is the defn shorthand, which combines the def and fn builtins into a single expression. Compare this equivalent definition of the add-and-trace function:

(defn add-and-trace (a b)
  (trace (+ a b)))