Lambda Reference

Bill Majoros
September 8, 1999


Introduction

This is a brief reference for the language lambda, which is an implementation of the lambda calculus.  The lambda calculus is an abstract language consisting of only three constructs: lambda expressions (lambda (x) <expr>), function calls (<f> <x>), and atoms, which are variables and literals.

The lambda calculus is normally just used in programming textbooks to teach abstract concepts of programming languages and interpreters.  However, lambda, which is the basis for LISP and Scheme, can be implemented to act as a real programming language, which, given a suitable set of primitives, can support arbitrary computation.

The advantage of lambda is that it has such a simple and consistent syntax that it is relatively easy to implement an intrepter for it.  Because it is Turing-complete, it can easily be used for Genetic Programming, a form of Genetic Algorithms used for evolving algorithms.  The present implementation of the language is written in C++, and provides an API for C++ programs to communicate with lambda, so that Genetic Programming can now be done in an efficient language like C++, while still evolving LISP-like expressions.


Identifiers

An identifier can be any sequences of letters, digits, ?, -, and possibly other characters (I don't remember at the moment).


Literals

1. Character Literals

#a is the character a.  #\n is the newline.  You can also use #\r, #\t, #\\, #', and #".

2. Numeric literals

An integer is something like 123 or -123.  A real number is something like 3.14.

3. String literals

A string literal is something like "Hello, world."

4. Symbols

A symbol literal is something like 'x.  A symbol is not a variable; it does not stand for something.  It just stands for itself.  However, if you (define 'x 6), because of the semantics of the define function, the variable x (not the symbol, 'x) will come to be bound to 6.  But the symbol 'x is still just the symbol 'x, and stands for nothing but itself.


Lambda Expressions

A lambda expression is a function literal.  Such a function literal is a first-class object, because it can be stored in data structures and executed later.  A lambda expression can occur anywhere in a program that any other literal can occur.

A lambda expression is denoted by a set of square brackets containing a parameter list, followed by a vertical bar (|), followed by the function body, which may consist of one or more expressions.  The last expression is the value returned by the function.  All the expressions are evaluated left-to-right, so this feature can be use to execute statements sequentially.

For example, this line:
   [x y z | (print x) (print y) (print z)]
will print x, followed by y, followed by z.


If-Then-Else

Lambda has no built-in if-then-else construct, but it is easy to get the same functionality using lambda expressions.

The pre-defined if function takes 3 arguments.  It evaluates the first, and if it evaluates to true, it executes the second parameter, otherwise the third.  For example:

(if (< x 10) [|(print "less than ten")] [|(print "not less than ten")]

First, the (< x 10) is evaluated.  The then and else parts are not immediately executed, because they occur inside lambda constructs.  They will be wrapped in closures and passed as first-class objects into the if function as its second and third parameters.  The appropriate clause (then or else) will be called by if (with no arguments) depending on the value of the first argument.


True and False

True and false are not built into the lambda language, so it uses 1 to denote true and nil to denote false.  However, two predefined variables, true and false, are bound to these values, so that they may be used in your programs.


nil


The value nil represents the absence of an object.  It is equivalent to NULL in C++ and nil in Smalltalk.


Function Invocation

A function is invoked by listing the function followed by its arguments within parentheses:

(f x y z)

This will call the function currently bound to f, passing in the values currently bound to x, y, and z as it arguments.


Equality

Two distinct objects may have the same value, but they are still two different objects.  Thus, if you compare 6 and 6 using the = function, as in (= 6 6), the value will be true.  However, if you execute (eq? 6 6), the value will be false, because both instances of '6' will evaluate to a new 6 object, and those objects have different addresses.  Thus, eq? compares addresses of objects, and evaluates to true only when both of its arguments evaluate to the address of one object.


Lists

One of the few built-in types in lambda is the cons cell, also called a dotted pair.  A cons cell is an ordered pair of object pointers.  It is denoted in print by (a . b), but this is not legal lambda syntax, so you may not use this in a lambda program.  To create a cons cell containing objects a and b, use (cons a b).

A list can easily be constructed by creating a series of cons cells, where the first element of each pair points to an object to be stored in the list, and the second element of the pair points to the next pair in the list.  The second element of the very last pair in the sequence should be nil, to terminate the list.  When a sequence of cons cells are set up in this way, the result is referred to as a list, but when a cons cell has something other than a another cons cell as its second element, it is instead referred to as an improper list.  An improper list may have a sequence of cons cells but be terminated by something other than nil.  Only when the last cell is terminated by nil is it called a true list.

For example, this is a list: (cons 1 (cons 2 (const 3 nil))).  It contains the numbers 1, 2, and 3.  However, this is an improper list: (cons 1 2), and so is this: (cons 1 (cons 2 3)).


Comments

A comment begins with a semicolon and extends to the end of the line.


Built-in Functions and Objects

(print x) ; prints x to standard out
(if x y z) ; if x evaluates to non-nil, evaluates and returns y, else z
                   (note that y and z must be enclosed in lambda constructs)
nil ; no object = false = a NULL pointer
true ; evaluates to 1
false ; evaluates to nil
(cons x y) ; returns a list just like y, but with x at the front
(car x) ; returns the first element in list x
(cdr x) ; returns the sublist of x starting with the second element
(+ x y) ; addition
(- x y) ; subtraction
(* x y) ; multiplication
(/ x y) ; division
(% x y) ; modulus (integer remainder)
(define 'x y) ; binds variable x to whatever y evaluates to
(< x y) ; less than
(<= x y) ; less than or equal to
(> x y) ; greater than
(>= x y) ; greater than or equal to
(= x y) ; converts x and y to real numbers and then tests for equality
(!= x y) ; not equal (for real numbers)
(load filename) ; loads a file with name  given by string arg filename
(eq? x y) ; tests if x and y evaluate to the same object
(nil? x) ; tests whether x evalutes to nil
(list? x) ; tests whether x is a true list (i.e., a sequence of cons cells)
(is-cons-cell? x) ; tests whether x is a cons cell
(sin x) ; returns the sin of x
(cos x) ; cosine of x
(sqrt x) ; square root of x
(acos x) ; inverse cosine of x
(asin x) ; inverse sin of x
(atan2 x y) ; inverse tangent of y/x (using sign of x and y to determine quadrant)
(exp x) ; e (the Euler number) to the power x
(log x) ; natural logarithm (i.e., base e) of x
(log10 x) ; log base 10 of x
(pow x y) ; x to the y
(ceil x) ; round x up to nearest integer
(floor x) ; round x down to nearest integer
(fabs x) ; absolute value of real value
(abs x) ; absolute value of integer (returns integer)
(make-vector x) ; returns a new vector containing x elements (all nil)
(vector? x) ; tests whether x evalutes to a vector
(vector-ref v i) ; returns element i of vector v (zero-based)
(vector-set v i x) ; stores x at location i in vector v (zero based)
(vector-length v) ; returns length of vector v
(vector-to-list v) ; returns a list containing the elements of v
(list-to-vector x) ; returns a vector containing the elements of list x
(set-local 'lp x) ; stores x at lexical position lp in innermost scope (advanced)
(set-enclosing d p x) ; stores x at lexical address (: d p) (advanced)
(random-real)  ; random real between 0 and 1
(random-int x) ; random integer between 0 and x-1, inclusive
(protected-div x y) ; divides x by y, returning x if y is zero