The Misp Chronicles X: Environmental Functions

Applying Functions: A Review

A function in Misp has two parts: a head and a body. The head is a list of symbols or a single symbol. These symbols are assigned values when a function is applied. The body of a function is any Misp expression. When you evaluate the body, the symbols in the head refer to their associated values.

Consider the self pairing function (fn (x) (pair x x)). The head is (x). The body is (pair x x). To apply it with ‘hello, we write ((fn (x) (pair x x)) ‘hello). First we associate x with the symbol hello. Then we evaluate (pair x x) by looking up each symbol and applying when were done. pair is a primitive, so we move on to the other two terms. They are both x. Since x is associated with hello, we pair hello with hello to get (hello . hello). Hello!

Syntactic Sugar: Soul Sweetener

When a programmer is born into the world, he is given a lifetime supply of parenthesis. Unfortunately I wasn’t in the Lisp line. I’ve already used up most of mine. In an effort to avoid an untimely end, I’ll use a block syntax like Ruby for functions.

BlandSugaryArgsReturns
(fn (x) (pair x x)){|x|(pair x x)}‘hi(hi . hi)
(fn (x y z) z){|x y z| z}‘a ‘bnil
(fn (ls) ((fn (x . xs) xs) . ls)){|ls|({|x . xs| xs} . ls)}‘(a b c)(b c)
(fn xs xs){|.xs| xs}‘a ‘b ‘c(a b c)

The second example shows that z gets bound to nil when there is no corresponding argument. The third example shows that a function can be used inside of a function.

Improving the Environment

It would be great if we could give functions names instead of explicitly defining them whenever we use them. For instance, (list ‘a ‘b ‘c) is clearer than ({|.xs| xs} ‘a ‘b ‘c). Misp only has one way of assigning meaning to symbols: function application. An assignment of symbols to values is called an environment or a context. The association created in function application extends Misp’s environment thereby enriching the expressivity of the language.

To give the symbol list a meaning in the expression (list ‘a ‘b ‘c), list must be the argument to a function {|list|(list ‘a ‘b ‘c)}. What happens when we evaluate ({|list|(list ‘a ‘b ‘c)} {|.xs| xs})? We extend the environment so that symbol list refers to {|.xs| xs}. When we evaluate the body (list ‘a ‘b ‘c), we look up list in the environment. Since list refers to {|.xs| xs}, the result of the body is (a b c).

Suppose that instead of building a the list (a b c), we want to append a and b to the front of any list, (c d e) for example. Assuming we have an environment where the symbol list refers to {.xs|xs}, we say (list ‘a ‘b . ‘(c d e)). How do we generalize from (c d e) to any given list ls? For starters, we replace ‘(c d e) with a symbol ls. Then we make (list ‘a ‘b . ls) the body of the function {|ls| (list ‘a ‘b . ls)}. That’s it except we’re assuming the definition of list. To make our assumption explicit we say ({|list|{|ls|(list ‘a ‘b . ls)}} {.xs| xs}). The function application simply extends the environment so that list is defined in the inner function {|ls|(list ‘a ‘b . ls)}.

Though simple, clear, and intuitive, Lisp didn’t build environments in this way for a long time. Scheme was the first Lisp-like language to do it, Common Lisp followed in the ‘80s. What took so long? What’s the fuss about? Next time: The Closure Conundrum.