Building Blocks


We’ve already come up with a number of cool functions I’ve been using in the examples. One of these is our fun function that allows us to declare functions in a neater way. We should definitely include this in our standard library.

  1. ; Function Definitions
  2. (def {fun} (\ {f b} {
  3. def (head f) (\ (tail f) b)
  4. }))

We also had our unpack and pack functions. These too are going to be essential for users. We should include these along with their curry and uncurry aliases.

  1. ; Unpack List for Function
  2. (fun {unpack f l} {
  3. eval (join (list f) l)
  4. })
  5. ; Pack List for Function
  6. (fun {pack f & xs} {f xs})
  7. ; Curried and Uncurried calling
  8. (def {curry} unpack)
  9. (def {uncurry} pack)

Say we want to do several things in order. One way we can do this is to put each thing to do as an argument to some function. We know that arguments are evaluated in order from left to right, which is essentially sequencing events. For functions such as print and load we don’t care much about what it evaluates to, but do care about the order in which it happens.

Therefore we can create a do function which evaluates a number of expressions in order and returns the last one. This relies on the last function, which returns the final element of a list. We’ll define this later.

  1. ; Perform Several things in Sequence
  2. (fun {do & l} {
  3. if (== l nil)
  4. {nil}
  5. {last l}
  6. })

Sometimes we want to save results to local variables using the = operator. When we’re inside a function this will implicitly only save results locally, but sometimes we want to open up an even more local scope. For this we can create a function let which creates an empty function for code to take place in, and evaluates it.

  1. ; Open new scope
  2. (fun {let b} {
  3. ((\ {_} b) ())
  4. })

We can use this in conjunction with do to ensure that variables do not leak out of their scope.

  1. lispy> let {do (= {x} 100) (x)}
  2. 100
  3. lispy> x
  4. Error: Unbound Symbol 'x'
  5. lispy>