The Urn Logo

Version 0.2.6 released

Another update. This time, we’ve started adding some much needed features to the standard library. Here are a couple of highlights:

handler-case

handler-case could be thought of a pumped-up try-catch statement. It executes the body like normal, but if you hit an error it will attempt to pattern match against it, meaning you can handle a whole different host of error types:

(handler-case
  (error! "oh-no")
  [(as string? ?x) (print! x)])

use

I’m sure you’ve had that time where you’ve forgotten to close a stray file handle, and not been able to delete it without rebooting your (ComputerCraft) computer? use takes care of that, ensuring every object is closed when the block exits.

(use [(file (io/open "temp")]
  (print! (self file :read "a")))

setf! and over!

setf! and over! provide a uniform way of modifying values. setf! takes a value to modify and sets the given value to it. over! takes a value, applies the given function, and stores it back where it came from. The real advantage of these is that they work on a whole host of different things: symbols, lists indexes, table keys, etc… This means it is simple to create macros which work on a whole range of values. For instance, you could declare the +=* operator as something like:

(defmacro += (selector val) `(over! ,selector (lambda (,'x) (+ ,'x ,val))))

then use it on values, lists, etc…

(+= foo 2)
(+= (nth bar 2) 3)
(+= (.> baz :qux :quux) 4)

Do note, this will ensure you don’t index a variable more than once, meaning the last example gets compiled to something like:

local temp = baz.qux
temp.quux = baz.quux + 4

*Don’t actually call it this, it isn’t very ‘lispy’ a name.