KRL supports functions as first-class objects. KRL supports only anonymous functions, but they can be given names by binding them to a variable in a declaration. Here's an example:

add5 = function(x) { x + 5 };

Functions are declared using the keyword `function`

followed by a possibly empty, parentheses-delimited, comma-separated list of parameters and a block of code. The code block of the function is delimited by curly braces and contains a list of semicolon-separated declarations and a single expression. The declarations are optional, but every function code block must end with an expression. The value of the final expression is the return value of the function.

Functions are statically executed (i.e., free variables are bound in the environment in which they are defined, not the environment in which they are executed) and can be recursive. KRE limits the number of times a function can be called in any given ruleset evaluation to protect against runaway code. The value of the recursion threshold is installation specific. Here's an example of a recursive function in KRL:

fact = function(n) { (n <= 0) => 1 | n * fact(n-1) }

This example also shows the syntax for function application (e.g., `fact(n-1)`

). An expression resulting in a function is followed by a possibly empty, parentheses-delimited, comma-separated list of expressions. Function application is applicative-order; the expressions representing the function and the arguments are evaluated and the result of executing the function expression (the operator, or rator) is then applied to the results of the evaluation of the arguments (the operands, or rands). Obviously, the operator must be a function.

To see how declarations appear in the body of a function, consider the following example, which uses Newton's method to calculate square roots (Adapted from section 1.1.8 of *Structure and Interpretation of Computer Programs*.):

sqrt = function(x) { average = function(x,y) { (x + y) / 2 }; good_enough = function(guess, x) { v = (guess * guess) - x; v < 0.01 && v > -0.01 }; improve = function(guess, x) { average(guess, (x / guess)) }; sqrt_iter = function(guess, x) { good_enough(guess, x) => guess | sqrt_iter(improve(guess,x), x) }; sqrt_iter(1.0, x) }

Functions can return functions as values and can be passed as arguments to other functions and operators in KRL. The following example defines a generalized summation function called `sum`

that sums the numbers from `a`

to `b,`

incrementing using the function `inc`

and applying the function `f`

to each term:

sum = function(f, a, inc, b) { (a > b) => 0 | f(a) + sum(f, inc(a), inc, b) };

You can use sum to define a function that sums the cubes from a to b:

plus1 = function(x) { x + 1 }; cube = function(x) { x * x * x }; sum_cubes = function(a, b) { sum(cube, a, plus1, b) }

As another example, you can define a function that creates incrementor functions. When given a number, it returns a function that increments by that value:

inc_gen = function(x) { function(){ x + n } };

Now you use `inc_gen`

to generate other functions:

plus1 = inc_gen(1); plus25 = inc_gen(25);

Overview

Content Tools