This may not be much of an example, but it's not only what I have, it's what got me hooked on Lisp.
When I was a young lad, and because I lived not too far from Lake Geneva, I played this newfangled thing called D&D (back when it first came out. Get off my lawn). And one of the things that intrigued me was the tables (the kind where you rolled dice and looked up the results). And also being as I was learning programming (on a mainframe. There were no microcompputers. See my previous comment about lawns.) I thought about writing a table language. One where I could specify not only how many chances a particular result had (because I'd already figured out that that was better than using the dice themselves for a bell curve), but also being able to modify the tables themselves at run-time by feeding them arguments, being able to have sub-tables, detailed results, etc. But at the time all we had was Honeywell mainframe BASIC (supposedly FORTRAN was available, but we couldn't get a manual), and even the instructor didn't know anything about writing parsers, let alone languages.
Fast forward, and the idea stuck with me. I mean, I'd gone to school and doubles in ECE and Comp. Sci., I should be able to do this. But I never did, because it's a very big hassle to write your own language. Especially in languages like C.
So when I started using Lisp, I read up all this stuff about DSLs. Hm, I wonder if I could use Lisp to do my language. Well, half an hour and 15 lines of code later, I not only had my language, but more than I wanted. And here it is (ta da):
(defmacro table (name args &rest rest) `(defun ,name (,@args) (declare (special ,@args)) (let* ((base ',(loop for x in rest collect (car x))) (results ',(loop for x in rest collect (cadr x))) (chances (loop for x in base collect (eval x))) (total (loop for x in chances sum x)) (roll (+ 1 (random total)))) ;(format t "Base:~{~a~^, ~}~%Chances:~{~a~^, ~}~%Results:~{~a~^, ~}~%total:~A roll:~A~%" ; base chances results total roll) (do ((n chances (cdr n)) (cnt 0) (item 0 (+ item 1))) ((eq n nil) nil) (setf cnt (+ cnt (car n))) (when (<= roll cnt) (return (eval (nth item results))))))))
and it's used like this (a simple example):
(table my-table (added-chances) (1 "one") (1 "two") ((+ 1 added-chances) "three") )
I've done some stuff with it that's been quite a bit of fun. Like another layer of macro on top for those who think in terms of dice.
The upshot is that it's a project I didn't do for 25 years because it was too big a pain. And I did it in Lisp in half an hour, including figuring out that I had to use dynamic scoping for args. I have to use dynamic scoping because the forms being eval'ed need to be able to access args, but args is not in their lexical scope (though it looks as if they are in the macro invocation -- which is the point).
Neil Gilmore raito@raito.com