Interesting Functions

Function Definition

Lambdas are clearly a simple and powerful way of defining functions. But the syntax is a little clumsy. There are a lot of brackets and symbols involved. Here is an interesting idea. We can try to write a function that defines a function itself, using some simpler syntax.

Essentially what we want is a function that can perform two steps at once. First it should create a new function, and then it should define it to some name. Here is the trick. We let the user supply the name and the formal arguments altogether in one list, and then separate these out for them, and use them in the definition. Here is a function that does that. It takes as input some arguments and some body. It takes the head of the arguments to be the function name and the rest to be the formal arguments. It passes the body directly to a lambda.

  1. \ {args body} {def (head args) (\ (tail args) body)}

We can name this function something like fun by passing it to def as usual.

  1. def {fun} (\ {args body} {def (head args) (\ (tail args) body)})

This means that we can now define functions in a much simpler and nicer way. To define our previously mentioned add-together we can do the following. Functions that can define functions. That is certainly something we could never do in C. How cool is that!

  1. fun {add-together x y} {+ x y}

Currying

At the moment functions like + take a variable number of arguments. In some situations that’s great, but what if we had a list of arguments we wished to pass to it. In this situation it is rendered somewhat useless.

Again we can try to create a function to solve this problem. If we can create a list in the format we wish to use for our expression we can use eval to treat it as such. In the situation of + we could append this function to the front of the list and then perform the evaluation.

We can define a function unpack that does this. It takes as input some function and some list and appends the function to the front of the list, before evaluating it.

  1. fun {unpack f xs} {eval (join (list f) xs)}

In some situations we might be faced with the opposite dilemma. We may have a function that takes as input some list, but we wish to call it using variable arguments. In this case the solution is even simpler. We use the fact that our & syntax for variable arguments packs up variable arguments into a list for us.

  1. fun {pack f & xs} {f xs}

In some languages this is called currying and uncurrying respectively. This is named after Haskell Curry and unfortunately has nothing to do with our favourite spicy food.

  1. lispy> def {uncurry} pack
  2. ()
  3. lispy> def {curry} unpack
  4. ()
  5. lispy> curry + {5 6 7}
  6. 18
  7. lispy> uncurry head 5 6 7
  8. {5}

Because of the way our partial evaluation works we don’t need to think of currying with a specific set of arguments. We can think of functions themselves being in curried or uncurried form.

  1. lispy> def {add-uncurried} +
  2. ()
  3. lispy> def {add-curried} (curry +)
  4. ()
  5. lispy> add-curried {5 6 7}
  6. 18
  7. lispy> add-uncurried 5 6 7
  8. 18

Have a play around and see what other interesting and powerful functions you can try to come up with. In the next chapter we’ll add conditionals which will really start to make our language more complete. But that doesn’t mean you won’t be able to come up with some other interesting ideas. Our Lisp is getting richer.