QoL addition to Common Lisp :start/:end
Thought I'd share a pretty cool "go go gadget" I added to the good old :start
/:end
keyword parameters found in various sequence and string
functions (e.g. find
): a duo of helpers to strictly augment their interface in order to change
;; Some ways to extract "cde" (let ((str "abcdefg")) (subseq str (+ (position #\b str) 1) (position #\f str)) (subseq str (position #\c str) (+ (position #\e str) 1)) (subseq str (search "cd" str) (+ (search "de" str) 2)))
into
(let ((str "abcdefg")) (subseq str '(:after #\b) '(:before #\f)) (subseq str '(:from #\c) '(:until #\e)) (subseq str '(:from "cd") '(:until "de")))
which I find greatly improves readability and helps prevent off-by-X errors. In general, I really like it when CL reads like a dialect of English, it's easy on the eye and the brain.
Their use is pretty streamlined too, as our wrapper's triviality shows:
(declaim (inline subseq)) (defun subseq (seq start &optional end (test #'eql)) "Improved version of cl:subseq accepting %rel-start/end specs for :start/:end." (let* ((%start (%rel-start start seq :test test)) (%end (%rel-end end seq :test test :start %start))) (cl:subseq seq %start %end)))
A last little example to show the optional :last
:
(subseq "https://foo.bar/page.html" '(:after :last #\/)) ;; => "page.html"
PS: I think this'll be very useful for the next Advent of Code, together with these reader extensions.