Sorting By Functions in Lisp

(defun len-cmp (a b)
  (- (length a) (length b)))

(defun main ()
  (let ((fruits '("peach" "banana" "kiwi")))
    ;; We implement a comparison function for string lengths.
    ;; In Lisp, we can directly compare lengths without needing a separate cmp.Compare function.

    ;; Now we can use the sort function with this custom comparison function
    ;; to sort 'fruits' by name length.
    (setq fruits (sort fruits #'len-cmp))
    (format t "~A~%" fruits))

  ;; We can use the same technique to sort a list of values that aren't built-in types.
  (defstruct person
    name
    age)

  (let ((people (list
                 (make-person :name "Jax" :age 37)
                 (make-person :name "TJ" :age 25)
                 (make-person :name "Alex" :age 72))))

    ;; Sort 'people' by age using the sort function.
    ;; Note: In Lisp, we're working with the actual objects, not references,
    ;; so there's no need to worry about the size of the struct affecting performance.
    (setq people (sort people #'(lambda (a b)
                                  (- (person-age a) (person-age b)))))
    (format t "~A~%" people)))

(main)

Sometimes we’ll want to sort a collection by something other than its natural order. For example, suppose we wanted to sort strings by their length instead of alphabetically. Here’s an example of custom sorts in Lisp.

We start by defining a comparison function len-cmp that compares the lengths of two strings. In Lisp, we can directly subtract the lengths to get the comparison result.

In the main function, we first demonstrate sorting a list of fruits by their length. We use the sort function, which takes a sequence and a predicate function. Our len-cmp function serves as this predicate.

Next, we show how to sort custom structures. We define a person struct with name and age fields. We create a list of person instances and then sort them by age. For this, we use an anonymous function (lambda) as our sorting predicate, which compares the age fields of two person instances.

To run the program, save it to a file (e.g., sorting-by-functions.lisp) and use your Lisp interpreter. For example, if you’re using SBCL:

$ sbcl --script sorting-by-functions.lisp
("kiwi" "peach" "banana")
(#S(PERSON :NAME "TJ" :AGE 25) #S(PERSON :NAME "Jax" :AGE 37) #S(PERSON :NAME "Alex" :AGE 72))

This example demonstrates how Lisp’s flexible function handling allows for easy implementation of custom sorting logic, both for built-in types and user-defined structures.