lisp programming

This year, I am trying to get my hands on Advent of Code. One of my aims is to try out programming languages with varying paradigms. As of now, I have attempted the days (problems) intermittently and have not been changing languages that often too, mostly employing Common Lisp. One side effect of that has been a chance to have a deeper look into the CL's package ecosystem.

On first sight, you will notice that a lot of Common Lisp packages are old. Really old. It feels like you don't have a lot of options. I actually started a github project for collecting various handy macros/functions I use (or have seen) in Emacs Lisp, Racket, Clojure etc. In the process, what I found was that many of these are already present in CL. They are just spread out over lots of packages (with lot of duplication). An interesting set of Lisp macros that I have recently started to like is one that provides shortcuts for expressing λ functions. In this post, I try to knot up the options in Common Lisp for these little beauties.


Working in Lisp (or any language with functional inclinations) makes you use a lot of partially applied functions. Consider a list of numbers that you want to increment by 1. In Common Lisp this would be something like:

(mapcar (lambda (n) (+ 1 n)) '(1 2 3 4 5 6))

The lambda in the middle really is just creating a partially applied version of the function #'+ with the first argument set to 1. Now, writing this much code ((lambda (n) (+ 1 n))) for a simple function can get really boring. In this specific case, since we already have a unary function #'1+, we can get rid of the boilerplate like this:

(mapcar #'1+ '(1 2 3 4 5 6))

But, in general, you need to use the full lambda form. Some Lisps, like hy provide a shorter name like fn which is neat, but given that we have macros in hand there can be much cleaner solutions.

1 Cut

One of the solutions I first came across is the -cut macro in Emacs Lisp from dash.el. This has its origin in SRFI-26 where a one line description says Notation for Specializing Parameters without Currying.

In Common Lisp we have cl-cut which follows Scheme's cut specification more completely (as compared to dash in elisp). If you want to (say) replace ? with ! in a list of strings, a cut based solution would be:

;; cut is from cl-cut
;; replace-all is from cl-strings
(mapcar (cut replace-all <> "?" "!") items)

Compare that with the full λ version:

(mapcar (lambda (s) (replace-all s "?" "!")) items)

Not a lot different, but why complicate things if there are shorter ways? Just like in functions, anonymity in arguments helps when the effective name is clear from context. Cut also allows expressing multiple arguments and λs with &rest:

;; Replace ? with different string in different items
(mapcar (cut replace-all <> "?" <>) items replacements)

;; Taken from http://quickdocs.org/cl-cut/
(cut list 1 <> 3 <...>)
;; is equivalent to the following
(lambda (x2 &rest xs)
  (apply #'list 1 x2 3 xs))

One decision made in cut is to only allow <> in flat positions, i.e. the placeholder <> can not be hidden inside parentheses like in the following case:

;; This doesn't work
(funcall (cut + 2 (* <> 3)) 3)

;; <> inside lists are not detected while generating the argument list
;; (macroexpand '(cut + 2 (* <> 3))) gives
(lambda () (+ 2 (* <> 3)))

Sometimes this nesting is needed. For example, if you are converting a list of temperature given in °F to °C, you might want to be able to write something like:

(mapcar (cut * (/ 5 9) (- <> 32)) temperatures)

If you need only unary functions, a simple solution is to make an anaphoric version of λ which captures <>:

(defmacro acut (&rest body)
  `(lambda (<>) ,@body))

;; This works now
(mapcar (acut * (/ 5 9) (- <> 32)) temperatures)

2 Xi

This is another fancy way of creating λs that I came to know from hy. Although its name is going to be changed in a while, according to current stable docs, its usage is like this:

;; (require [hy.extra.anaphoric [*]])
(xi - x1 x2)
;; This is equivalent to
(fn [x1 x2] (- x1 x2)) ; Not that `lambda` is called `fn` in Hy

The important thing to notice is that xi supports positional arguments (and also nesting) by using the number in the placeholders x1, x2 etc. For example, consider the following snippet:

;; Hy
((xi - (+ x1 x2) x3) 2 5 10) ;; -3
((xi - (+ x2 x3) x1) 2 5 10) ;; 13

Xi really is inspired by Clojure's anonymous function syntax which is pretty powerful:

#(+ 10 %)         ;; % acts similar to <> in cut
#(- %1 (+ %3 %2)) ;; We have nesting and positional arguments (%i)
#(some-fun % %&)  ;; We have &rest (as %&) too

Closest looking syntax for this in Common Lisp (at least from what I found out) is of the #L reader macro from arnesi and ^ macro from CL21. Using #L, the above examples in clojure translates to the following Common Lisp code

;; Need to enable sharp-l reader macro
;; (arnesi:enable-sharp-l-syntax)
#L(+ 10 !1)         ;; !i for position i
#L(- !1 (+ !3 !2))
                    ;; No &rest arguments here

In CL21, you have:

^(+ 10 %)
^(- %1 (+ %3 %2))
                    ;; Don't know if &rest is supported yet

Another option is positional-lambda where Clojure's examples go like the following:

(plambda (+ 10 :1))            ;; :i for position i
(plambda (- :1 (+ :3 :2)))
(plambda (some-fun :1 :rest))  ;; &rest is supported

Although using complicated λs signals that you better reconsider your decision of not creating dedicated functions, these fancier variants are pretty useful.

Here is a listing of Common Lisp packages mentioned in this post and some other which are similar in the sense that they allow creating/manipulating functions:

  • cl-cut for cut (and cute) syntax from SRFI-26
  • arnesi for the #L reader macro.
  • CL21 for the ^ macro. Not on quicklisp main repos but can be installed using ql. Instructions on project's page.
  • positional-lambda for plambda macro.
  • There is also #`-reader in rutils providing Clojure-ish but slightly limited shorthands
#`(+ 2 %) ; => (lambda (&optional x y) (+ 2 x)) 
#`((print %) (1+ %)) ; => (lambda (&optional x) (print x) (1+ x))
#`(+ % %%) ; => (lambda (&optional x y) (+ x y)) 
  • fn provides another set of shorthands for λs. Examples from github page:
(fn* (subseq _@ 0 2)) ; =>  (lambda (&rest _@) (subseq _@ 0 2))
;; with reader macros for fn* forms too
λ(+ _ _1) ; =>  (lambda (_ _1) (+ _ _1))
  • curry-compose-reader-macros provides shorthand reader macros for currying and composing functions. A few examples from the github page:
;; partial application `curry'
(mapcar {+ 1} '(1 2 3 4)) ; => (2 3 4 5)
;; function composition
(mapcar [#'list {* 2}] '(1 2 3 4)) ; => ((2) (4) (6) (8))
;; function split and join
(mapcar «list {* 2} {* 3}» '(1 2 3 4)) ; => ((2 3) (4 6) (6 9) (8 12))
  • curly has two reader macros for currying and composition. Examples from homepage
'[foo bar * baz] ; => (lambda (#:g2709) (foo bar #:g2709 baz))

'{foo (bar 16) (baz 23 * 42) quux}
;; => (lambda (#:g2724) (foo (bar 16 (baz 23 (quux #:g2724) 42)))