I recently wrote a macro that expands forms like this into an airline flight itinerary. It's used in test code, in which we don't want to hard-wire the itineraries because we want to be able to test multiple airlines.
What's interesting about this is that it's actually a constraint language where the variables (like $A, $B, $DATE) get filled in and tested to see if they meet the constraints. This requires Prolog-like backtracking, and the final example uses a lazy- evaluation-like technique so that $S1 can be "bound" and used in the same clause.
(Heh, trying doing this in Java.)
;; Binds $S1, $S2, $S3 to specific flights (with-test-itinerary (($S1 (:AC 8334 "2007-11-13" :BOS :CHI)) ($S2 (:AC 8470 "2007-11-13" :CHI :SFO)) ($S3 (:AC 1156 "2007-11-14" :SFO :BOS))) (values $S1 $S2 $S3))
;; Makes a 3-segment itinerary from A to B to C, ;; with the third segment one day later than the first two (with-test-itinerary (($S1 (:hosted :* $DATE $A $B)) ($S2 (:hosted :* $DATE $B $C) ) ($S3 (:hosted :* (plus-days $DATE 1) $C $A))) (values $S1 $S2 $S3))
;; Makes a 3-segment itinerary from A to B to C, ;; with the third segment one day later than the first two, ;; and the first two segments have the same flight number (with-test-itinerary (($S1 (:hosted $F1 $DATE $A $B)) ($S2 (:hosted $F1 $DATE $B $C)) ($S3 (:hosted $F2 (plus-days $DATE 1) $C $A))) (values $S1 $S2 $S3))
;; Makes a 3-segment itinerary with different flight numbers ;; for each segment (with-test-itinerary (($S1 (:hosted $F1 :* :* :*)) ($S2 (:hosted $F2 :* :* :*)) ($S3 (:hosted $F3 :* :* :*))) (values $S1 $S2 $S3))
;; Makes a 4-segment itinerary from A to B to C to D, ;; the last two segments being two days later, and the ;; final airport satisfies the predicate "far away from C" (with-test-itinerary (($S1 (:hosted :* $DATE :* $A)) ($S2 (:hosted :* $DATE $A $B) ) ($S3 (:hosted :* ($DATE2 (plus-days $DATE 1)) $B $C)) ($S4 (:hosted :* $DATE2 (far-away-airport $C) $D) )) (values $S1 $S2 $S3 $S4))
;; See if you can figure this one out (with-test-itinerary (($S1 (($C1 (and (segment-hosted-carrier-p $S1) (OA-operated-p $S1) $C1)) :* :* :* :*)) ($S2 (($C2 (and (segment-hosted-carrier-p $S2) (not (OA-operated-p $S2)) $C2)) :* :* :* :*))) (values $S1 $S2))
On Sep 5, 2010, at 8:24 AM, Kazimir Majorinc wrote:
As first, good luck with this list!
I'm in search for best examples of "code is data" paradigm in Common Lisp. For most CL-ers, it probably means "macros", but eval, backquote, anything that processes the code as data is of interest. As "best" I think on the most surprising, powerful, sophisticated examples, not necessarily of a pedagogical value.
Imagine that someone invited you to write the presentation "Five best CL macros ... I seen" or "Five best CL macros ... I wrote." What would you chose and why?
Kazimir Majorinc
pro mailing list pro@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/pro