# A Lisp version of the Schwartzian transform

Randal Schwartz stole Lisp's decorate-sort-undecorate idiom when he came up with what we'd later call the Schwartzian transform. All of my Lisp knowledge disappeared through nine half lives, but I gave it a shot in SBCL. I'm aiming for an idiomatic example I can use in a presentation about the history of the Schwartzian transform.

This works (and I know I can generalize it further), but I wonder how Lisp-y it is:

(require :sb-posix)
(defun schwartzian-files-mtime ( glob-pattern )
(map
'list
#'cdr
(stable-sort
(map
'list (
lambda (x) (
cons
(sb-posix:stat-mtime (sb-posix:stat x))
x
)
)
(directory glob-pattern)
)
#'<
:key
#'car
)
)
)

(schwartzian-files-mtime "/etc/*")

• Welcome to codereview! I hope you get some nice answers ! More, feel free to visit our Perl section and answer whatever question might look interesting for you – Grajdeanu Alex. Aug 11 '16 at 11:37
• It's also not spelled LISP the same way that it's not spelled PERL. – ferada Aug 11 '16 at 13:32
• @ferada LISP is LISt Processing. Perl is a name which is not an acronym. Often, LISP is capitalised as Lisp but I would posit that as wrong. – cat Aug 11 '16 at 14:42
• Which LISP? The original LISP? This looks kinda like Scheme but more like CL. Is it CL? Which interpreter do i use to run it, and why isn't this confusing to anyone else? there are like, 10 different kinds of "real" LISP. – cat Aug 11 '16 at 14:44
• @cat (map 'list ...) is certainly CL. Have you missed the I gave it a shot in sbcl in the quesiton? – Will Ness Aug 11 '16 at 16:39

## 2 Answers

What is not enough LISP-y in your function is the style used for the parentheses (they should not be left alone as last element of a line and they should be on the last line of the enclosed form). Another minor point is that you can use the shorter mapcar instead of map 'list.

Here is a version of your function (generalized for any function applied to the data and any predicate) which follows the more conventional style used in Common Lisp.

(defun schwartzian-transform (list costly-function predicate)
"sort a list of objects over the value of a function applied to them,
by applying the Schwartzian Transform (https://en.wikipedia.org/wiki/Schwartzian_transform)
the parameters are the list, the function, and the predicate for the sort."
(mapcar #'cdr
(stable-sort (mapcar (lambda (x)
(cons (funcall costly-function x) x))
list)
predicate
:key #'car)))

(require :sb-posix)
(schwartzian-transform
(directory "/etc/*")
(lambda (x) (sb-posix:stat-mtime (sb-posix:stat x)))
#'<=)

• No documentation string? – Gareth Rees Aug 11 '16 at 13:06
• Nice transformation! The only thing I would change is to add space after lambda, although that's a small one. – MatthewRock Aug 11 '16 at 13:25
• @MatthewRock, thanks! Sometimes I miss that space. – Renzo Aug 11 '16 at 13:27
• @WillNess, in ANSI Common Lisp both forms are equivalent. In the Google Common Lisp Style Guide both forms are allowed. I prefer the form without the #' since it is shorter but still very clear. – Renzo Aug 11 '16 at 20:45
• Yes I know they're equivalent, I had that impression about the style... Thanks for the link. – Will Ness Aug 11 '16 at 23:22

What's certainly extremely very non-LISPy is your opening parens ending the line of code like that. With that, mapcar and explicit #' in front of lambda, it could look like

(defun schwartzian-files-mtime ( glob-pattern )
(mapcar #'cdr
(stable-sort
(mapcar #'(lambda (x)
(cons (sb-posix:stat-mtime (sb-posix:stat x))
x))
(directory glob-pattern))
#'<
:key #'car)))


This looks natural to me, but still may be off w.r.t. official style guidelines. It has a "quick-n-dirty" feel to it, like something you'd scribble on the spot (not unlike Randal's original piece of code), not a proper production code with documentation string etc..