This repo contains a collection of small Common Lisp toys I’ve written over the last thirty-odd years. These are explicitly toys: they’re little things which I wrote for amusement and which I decided might one day be useful either to me or someone else.
The documentation is generally rather sparse. Some of the toys may work, some may not. Some may never have worked.
All of these things are independent modules, providing something which looks like
org.tfeb.toys.<module>. There is no ASDF or other system definition for all of them. If they need other things either from amongst themselves or from other modules I’ve written they’ll do so using
require-module which you’ll need to have installed in that case. In the case that they need things written by other people or other larger systems they’ll do that using Quicklisp. Currently none of them do either.
All of the toys purport to be portable Common Lisp.
The repo from which the toys are published was invented in 2021, but some of them are 20 years older than that. Some of that history exists but not in the publication repo.
All of the toys use domain-structured names: packages, modules, features and so on have names which start with a reversed DNS domain and then continue to divide further. The prefix for all of the toys is
org.tfeb.toys. See the TFEB.ORG tools documentation for a little more on this.
This lets you define iterators for objects by defining methods on
iter which typically returns a function.
next (another generic function) should then know how to get the next element from an iterator: for an iterator which is a function it just calls it.
for is a macro which will loop over objects, calling
iter to make the iterator &
next to get the next values. There are also
ranges, and finally a
gather macro which is a bit like Python’s list comprehensions (or what I thought they were like in 2004).
As an example the method on
iter for lists is this:
(defmethod iter ((l list) &key) (lambda () (if l (multiple-value-prog1 (values (car l) t) (setf l (cdr l))) (values nil nil))))
(In fact it’s
#'(lambda ...) which tells you how old this code is.) You could then gather the even integers in a list:
(gather (* x x) for (x '(1 2 t 3)) when (numberp x) when (oddp x))
when are not
gather turns them into
(when ...), so they’re just the normal CL macros:
(gather (* x x) for (x '(1 2 t 3)) when (numberp x) when (oddp x)) -> (let ((#:a 'nil) (#:at 'nil)) (for (x '(1 2 t 3)) (when (numberp x) (when (oddp x) (if #:a (setf (cdr #:at) (list (* x x)) #:at (cdr #:at)) (setf #:a (list (* x x)) #:at #:a))))) #:a)
for lives in
org.tfeb.toys.for and provides
caseinto an explicit jump table:
ncase is just like
casebut it can turn
case statements into explicit jump tables if they are large enough. From the comments in the file:
This is actually not a really good example because the compiler is likely to be able to do a better job of the decisions involved, and it can also use real jumps rather than function calls which only may turn into jumps.
I can’t see a case where
ncase would be useful today, but it’s there.
ncase lives in
org.tfeb.toys.ncase and provides
CL only has global special variables, which are dynamically scoped. But it’s easy to fake global variables which are lexically scoped using symbol macros. That’s what
defglex is like
(defglex x) will define
x as a global lexical but not give it an initial value, while
(defglex x 1) will give it an initial value as well. You can provide documentation strings.
defglex* is like
defparameter: you can’t omit the value and it is set each time.
glex lives in
org.tfeb.toys.glex and provides
This lets you wrap special variables in functions and provides forms which will
bind these named functions.
define-parameter is like
define-parameter* is like
parameterize is like
parameterize* is like
(define-parameter hugeness 10 "how huge a thing is") (print (hugeness)) (parameterize ((hugeness 20)) (print (hugeness)))
10 and then
parameters lives in
org.tfeb.toys.parameters and provides
The TFEB.ORG Lisp toys are copyright 2000-2021 Tim Bradshaw. See
LICENSE for the license.