构筑模块

我们已经提出了一些在示例中使用过的很酷的函数。其中之一就是fun函数,它允许我们以更整洁的方式声明函数。我们绝对应该将它放在我们的标准库中。

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

除此之外,也应该有我们的unpackpack函数。这些对用户来说也是必不可少的。我们应该将它们以及它们的curryuncurry别名一起包括在内。

  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)

假设我们想要按顺序做几件事。我们这样做的办法可以简单为将每个事件设置为函数中的参数。我们知道参数按从左到右的顺序进行计算,这实际上是对各个事件进行排序。对于诸如此类的函数,例如printload 等,我们并不关心他们所计算的内容,而是关心它发生的顺序。

因此,我们可以创建一个 do 函数,按顺序计算多个表达式并返回最后一个。这依赖于 last 函数,该函数会返回列表的最后一个元素。我们稍后会定义它。

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

有时我们希望使用=运算符将结果保存到局部变量。当我们在函数内部时,这将隐式地仅在本地保存结果,但有时我们想要打开其更加广阔的本地范围。为此,我们可以创建一个函数let,为代码创建一个空函数,并对其进行计算。

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

我们可以结合 do 使用它来确保变量不会泄漏到其范围之外。

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