Clojure has two useful macros that I find myself missing when I’m working in Guile: Thread-first and Thread-last. Both are just convenient little abstractions over deeply nested s-expressions, and when used tastefully help make Lisp significantly more readable.

Thread-first

Thread First ( -> ) is a macro that inserts its first argument into the first position of the s-expression that follows it, and then places that evaluated s-expression’s result into the next s-expression, and so on ad infimum.

(-> '(5 3 2) (sort <) (car))

We’d like this to expand to:

(car (sort '(5 3 2) <))

To be honest, this macro took me a couple of attempts to get right. I finally became satisfied with this definition:

(define-syntax -> (syntax-rules () ((_ value) value) ((_ value (f1 . body) next ...) (-> (f1 value . body) next ...))))

Thread-last

Thread-last ( ->> ) inserts a value into the last part of the following s-expression, then places the result of evaluating that s-expression into the last position of the next s-expression, and so on. So, given a piece of code like:

(->> value (f1 v1) (f2 v2) ... (fn vn))

We want an expansion like:

(fn vn (f(n-1) v(n-1) (f(n-2) ...))

Once I had Thread-first defined, I could basically just copy the definition, just changing the cons to an append . Here’s its definition:

(define (thread-last-helper f value . body) (apply f (append body (list value)))) (define-syntax ->> (syntax-rules () ((_ value) value) ((_ value (f1 . body) next ...) (->> (thread-last-helper f1 value . body) next ...))))

Let’s use SRFI-1’s alists and use the Thread-last macro like the classic Clojure example of accessing values in a dictionary data structure. Consider this example:

(->> '() (alist-cons "persons" '(("bob" . "bob@example.com") (name . "alice@example.com"))) (assoc "persons") (cdr) (assoc "bob") (cdr))

Obviously, this expression evaluates to "bob@example.com"

While there’s certainly nothing wrong with deeply nested s-expressions, sometimes when you’re sequentially accessing data this macro makes the source code somewhat clearer.

Partials

This last bit of functionality is another part of Clojure I really like: builtin partial function application. Fortunately, this is an extremely simple function to define:

(define (partial f . args) (lambda (. rest) (apply f (append args rest))))

This function works by returning a new function who’s body is the application of the given function f to the list of arguments. Since we use the . , this function can partially apply functions of any order we like.

Suppose we want to create a function that cons’ a value into each sublist within a list. We’ll call this function into-lists . Now, we can define it as:

(define (into-lists value lst) (map (partial cons value) lst))

This is a very simple abstraction, yet adequately captures patterns we tend to repeat many time in a program.