<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Dad, Hubbie, Haskeller, Doom Metalhead

Copyright 2013 Michael J. Forster</description><title>Michael J. Forster</title><generator>Tumblr (3.0; @michaeljforster)</generator><link>http://michaeljforster.tumblr.com/</link><item><title>Compiling lparallel under SBCL 1.0.50</title><description>&lt;a href="http://michaeljforster.tumblr.com/post/47112390831/upgrading-sbcl-and-loading-lparallel"&gt;Compiling lparallel under SBCL 1.0.50&lt;/a&gt;: &lt;p&gt;&lt;a href="http://michaeljforster.tumblr.com/post/47112390831/upgrading-sbcl-and-loading-lparallel"&gt;Previously&lt;/a&gt; I wrote that lparallel 2.3.2 failed to compile
for me under SBCL 1.0.50.  James was kind enough to contact me by email
to say that he has fixed that.  I’m guessing we’ll see that in a future
Quicklisp update.&lt;/p&gt;

&lt;p&gt;In the near future, I plan to write about my grokking and use of
lparallel in a commercial project.&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/47510226733</link><guid>http://michaeljforster.tumblr.com/post/47510226733</guid><pubDate>Mon, 08 Apr 2013 21:44:00 -0500</pubDate><category>lisp</category></item><item><title>Upgrading SBCL and loading lparallel</title><description>&lt;p&gt;&lt;a href="http://lparallel.org/"&gt;lparallel&lt;/a&gt; 2.3.2 failed to compile with my &lt;a href="http://www.sbcl.org"&gt;SBCL&lt;/a&gt;
1.0.50&amp;#160;&lt;a href="http://michaeljforster.tumblr.com/post/21147626573/installing-sbcl-on-slackware"&gt;installation&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;amp;gt; (ql:quickload "lparallel")
To load "lparallel":
  Load 1 ASDF system:
    lparallel
; Loading "lparallel"
[package alexandria.0.dev]........................
[package bordeaux-threads]........................
[package lparallel.util]..........................
[package lparallel.thread-util]...................
[package lparallel.raw-queue].....................
[package lparallel.cons-queue]....................
[package lparallel.vector-queue]..................
[package lparallel.queue].........................
[package lparallel.biased-queue]..................
[package lparallel.counter].......................
[package lparallel.spin-queue]....................
[package lparallel.kernel]........................
[package lparallel.kernel-util]...................
[package lparallel.ptree].........................
[package lparallel.promise].......................
[package lparallel.defpun]........................
[package lparallel.cognate].......................
[package lparallel].........

; file: /home/mjf/quicklisp/dists/quicklisp/software/lparallel-20130312-git/src/spin-queue/cas-spin-queue.lisp
; in: DEFUN PUSH-SPIN-QUEUE
;     (LPARALLEL.SPIN-QUEUE::CAS
;      (LPARALLEL.SPIN-QUEUE::NODE-CDR
;       (LPARALLEL.SPIN-QUEUE::SPIN-QUEUE-TAIL LPARALLEL.SPIN-QUEUE::QUEUE))
;      NIL LPARALLEL.SPIN-QUEUE::NEW)
; --&amp;amp;gt; EQ 
; ==&amp;amp;gt;
;   (COMPARE-AND-SWAP
;    (LPARALLEL.SPIN-QUEUE::NODE-CDR
;     (LPARALLEL.SPIN-QUEUE::SPIN-QUEUE-TAIL LPARALLEL.SPIN-QUEUE::QUEUE))
;    NIL LPARALLEL.SPIN-QUEUE::NEW)
; 
; caught ERROR:
;   during macroexpansion of (SB-EXT:COMPARE-AND-SWAP (NODE-CDR #) NIL ...). Use
;   *BREAK-ON-SIGNALS* to intercept:
;   
;    Invalid first argument to COMPARE-AND-SWAP: (NODE-CDR (SPIN-QUEUE-TAIL QUEUE)).
; 
; compilation unit aborted
;   caught 1 fatal ERROR condition
;   caught 1 ERROR condition
; Evaluation aborted on #.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We deploy applications on more recent versions of SBCL, so there was no
reason to not upgrade.  However, warned by Christophe Rhodes&amp;#8217;s
&lt;a href="http://www.advogato.org/person/crhodes/diary/163.html"&gt;post&lt;/a&gt;, I chose to avoid version 1.1.6.  I
&lt;a href="http://prdownloads.sourceforge.net/sbcl/sbcl-1.1.5-x86-64-linux-binary.tar.bz2"&gt;downloaded&lt;/a&gt; 1.1.5 and tweaked my copy of the
&lt;a href="http://slackbuilds.org"&gt;Slackbuilds&lt;/a&gt; SBCL &lt;a href="http://slackbuilds.org/repository/13.37/development/sbcl/"&gt;script&lt;/a&gt; to build it.&lt;/p&gt;

&lt;p&gt;Following the upgrade, I was able to load lparallel and run its tests
successfully.&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/47112390831</link><guid>http://michaeljforster.tumblr.com/post/47112390831</guid><pubDate>Thu, 04 Apr 2013 10:46:00 -0500</pubDate><category>unix</category><category>lisp</category></item><item><title>Kids, Hacking, and Mars Rovers (and Lisp ;-)</title><description>&lt;p&gt;Work has kept me from writing about this until now.  In late January,
I volunteered to run a &amp;#8220;Computer Programmers&amp;#8221; cluster for thirteen
grade seven and eight students at a local early and middle years
school.  We would meet for an hour six times over five weeks.&lt;/p&gt;

&lt;p&gt;On the first day, to keep the focus on programming rather than
computers (and to break the ice), we played a game inspired by NASA&amp;#8217;s
&lt;a href="http://marsrovers.jpl.nasa.gov/home/index.html"&gt;&lt;em&gt;Curiosity&lt;/em&gt; rover&lt;/a&gt;.  After watching short video about
&lt;a href="http://www.cs.cmu.edu/~vandi/"&gt;rover driver&lt;/a&gt; &lt;a href="http://www.youtube.com/watch?v=D8CUC8iRxJE"&gt;Vandi Verma&lt;/a&gt;, students paired up and
took turns playing the roles of programmer and rover.  The goal,
initially, was to program a rover to circumnavigate the rectangular
room.  Then, programmers tested their rovers on different levels of
the terraced octagonal pit in the middle of the room.&lt;/p&gt;

&lt;p&gt;A programmer wrote the program on a sheet of paper in the rover
language.  When handed the paper, the rover began to interpret the
program, reading it from top to bottom, following each instruction
before going on to the next.  Additionally, a rover would listen for
its programmer to say &amp;#8220;REBOOT&amp;#8221;, a powerful command that would
terminate the current program and instruct the rover to return to home
base.&lt;/p&gt;

&lt;h2&gt;Rover 1.0&lt;/h2&gt;

&lt;p&gt;Rover 1.0 had a very limited language:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;p&gt;(STEP)&lt;/p&gt;

&lt;p&gt;Rover steps forward, one foot immediately in front of the other.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(TURN-LEFT degrees)&lt;/p&gt;

&lt;p&gt;Rover turns left &lt;em&gt;degrees&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(TURN-RIGHT degrees)&lt;/p&gt;

&lt;p&gt;Rover turns right &lt;em&gt;degrees&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(REBOOT)&lt;/p&gt;

&lt;p&gt;Rover stops whatever it&amp;#8217;s doing and returns to home base.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Everyone succeeded in driving her rover around the perimeter of the room:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(STEP)
(STEP)
...
(STEP)
(TURN-RIGHT 90)
(STEP)
(STEP)
...
(STEP)
(TURN-RIGHT 90)
(STEP)
(STEP)
...
(STEP)
(TURN-RIGHT 90)
(STEP)
(STEP)
...
(STEP)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, navigating the different levels of the pit required a major
rewrite, and this was all the more tedious given the limited Rover 1.0
language.&lt;/p&gt;

&lt;h2&gt;Rover 2.0&lt;/h2&gt;

&lt;p&gt;We upgraded the rover language, adding three very useful operations:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;p&gt;(SENSE-OBSTACLE)&lt;/p&gt;

&lt;p&gt;A test that is true if the rover&amp;#8217;s front foot touches an obstacle
and false otherwise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(IF test then-command else-command)&lt;/p&gt;

&lt;p&gt;Do the &lt;em&gt;test&lt;/em&gt;.  If it&amp;#8217;s true, do &lt;em&gt;then-command&lt;/em&gt;.  If it&amp;#8217;s not, do
&lt;em&gt;else-command&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(REPEAT count commands)&lt;/p&gt;

&lt;p&gt;Do the list of &lt;em&gt;commands&lt;/em&gt;, in order, then do them again, a total of
&lt;em&gt;count&lt;/em&gt; times.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;With these in hand, most students eliminated the individual step
commands for each side of the room:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(REPEAT 40 (STEP))
(TURN-RIGHT 90)
(REPEAT 35 (STEP))
(TURN-RIGHT 90)
(REPEAT 40 (STEP))
(TURN-RIGHT 90)
(REPEAT 35 (STEP))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some recognised that that pit was a regular octagon and used nested loops:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(REPEAT 8
    (REPEAT 16 (STEP))
    (TURN-RIGHT 45))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, following a little demonstration and Socratic method, a few
of them discovered how to handle the room or any of the levels of the
pit with a single change:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(REPEAT 40
    (IF (SENSE-OBSTACLE)
         (TURN-RIGHT 45)
         (REPEAT 4 (STEP)))

(REPEAT 32
    (IF (SENSE-OBSTACLE)
         (TURN-RIGHT 45)
         (REPEAT 4 (STEP)))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Lisp?&lt;/h2&gt;

&lt;p&gt;What has any of this to do with Lisp&amp;#8230; besides the parentheses?  In
this case, it&amp;#8217;s about the parentheses:  the students neither asked nor
complained about them.&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/43348926781</link><guid>http://michaeljforster.tumblr.com/post/43348926781</guid><pubDate>Sun, 17 Feb 2013 16:56:00 -0600</pubDate><category>education</category><category>computing</category><category>lisp</category></item><item><title>L-99: P07 - Flatten a nested list structure</title><description>&lt;p&gt;The seventh &lt;a href="http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html"&gt;L-99&lt;/a&gt; problem, MY-FLATTEN, highlights the richness of
Common Lisp&amp;#8217;s operators on conses.&lt;/p&gt;

&lt;p&gt;In Common Lisp, a structure of conses can &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/14_a.htm"&gt;represent&lt;/a&gt; either: a)
a list, where the car of each cons points to the element, and the cdr
points to the next cons or a terminating atom; or b) a tree, where the
car and cdr, both, can point to subtrees of conses or to atoms, the
&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#leaf"&gt;leaves&lt;/a&gt; of the tree.&lt;/p&gt;

&lt;p&gt;MY-FLATTEN is defined not for trees but for lists, possibly with nested
lists as elements.  MY-FLATTEN must observe the &lt;strong&gt;separate&lt;/strong&gt; &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#list_structure"&gt;list
structures&lt;/a&gt; of the list and any nested lists: the first
cons of a nested list is not part of the structure of the parent list.&lt;/p&gt;

&lt;p&gt;To illustrate, compare the expected behaviour of MY-FLATTEN with a
function LEAVES that traverses a tree, collecting the terminal atoms:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun leaves (tree)
  (labels ((recur (tree list)
             (if (consp tree)
                 (recur (car tree) (recur (cdr tree) list))
                 (cons tree list))))
    (recur tree '())))

(leaves '(a (b (c . d) nil e) nil . f))
=&amp;gt; (A B C D NIL E NIL NIL F)

(my-flatten '(a (b (c . d) nil e) nil . f))
=&amp;gt; (A B C D NIL E NIL F)

(leaves 'a)
=&amp;gt; A

(my-flatten 'a) ; TYPE-ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the list literal above is interpreted as a tree, the terminal
&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/v_nil.htm"&gt;NILs&lt;/a&gt; are revealed; they aren&amp;#8217;t by MY-FLATTEN.&lt;/p&gt;

&lt;p&gt;Note, in the above example, that MY-FLATTEN is assumed to accept
&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_p.htm#proper_list"&gt;proper&lt;/a&gt; or &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#dotted_list"&gt;dotted&lt;/a&gt; lists and nested lists,
and that the resulting &amp;#8220;flattened&amp;#8221; list will not be dotted in any case.&lt;/p&gt;

&lt;p&gt;MY-FLATTEN, then, should work as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(my-flatten 42) ; TYPE-ERROR
(my-flatten '()) =&amp;gt; '()
(my-flatten '(a b c d e)) =&amp;gt; (A B C D E)
(my-flatten '(a b c d nil e nil)) =&amp;gt; (A B C D NIL E NIL)
(my-flatten '(a b c d . e)) =&amp;gt; (A B C D E)
(my-flatten '((a) b c d e)) =&amp;gt; (A B C D E)
(my-flatten '(a (b) c d e)) =&amp;gt; (A B C D E)
(my-flatten '(a b (c) d e)) =&amp;gt; (A B C D E)
(my-flatten '(a b c (d) e)) =&amp;gt; (A B C D E)
(my-flatten '(a b c d (e))) =&amp;gt; (A B C D E)
(my-flatten '(a b (c) d . e)) =&amp;gt; (A B C D E)
(my-flatten '(a b c (d) . e)) =&amp;gt; (A B C D E)
(my-flatten '(a b c (d . e))) =&amp;gt; (A B C D E)
(my-flatten '(a (b (c d) e))) =&amp;gt; (A B C D E)
(my-flatten '(a (b (c d) . e))) =&amp;gt; (A B C D E)
(my-flatten '(a (b (c . d) e))) =&amp;gt; (A B C D E)
(my-flatten '(a (b (c . d) nil e) nil)) =&amp;gt; (A B C D NIL E NIL)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Compared to LEAVES, the definition of MY-FLATTEN is complicated by
handling nested list structures and dotted lists.&lt;/p&gt;

&lt;p&gt;The following skeleton identifies the cases for
&lt;a href="http://michaeljforster.tumblr.com/post/22497707114/l-99-p01-find-the-last-box-of-a-list"&gt;traversing&lt;/a&gt; a proper or dotted list structure and
letting &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_rest.htm"&gt;REST&lt;/a&gt; &lt;a href="http://michaeljforster.tumblr.com/post/23412626669/laying-the-blame-on-lisp"&gt;blame&lt;/a&gt; MY-FLATTEN if the argument, list, is
not a list (&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_firstc.htm"&gt;FIRST&lt;/a&gt; and REST are used instead of &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_car_c.htm"&gt;CAR and
CDR&lt;/a&gt; to emphasise the traversal of lists rather than trees):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun my-flatten (list)
  (labels ((recur (list new-list)
             (cond ((consp (rest list))
                    ;; follow list structure
                    ... list ... new-list ...)

                   ((not (null (rest list)))
                    ;; last cons of dotted list
                    ... list ... new-list ...)

                   ((consp list)
                    ;; last cons of proper list
                    ... list ... new-list ...)

                   (t
                    ;; terminating NIL of proper list
                    new-list))))
    (nreverse (recur list '()))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In each of the first three cases, before proceeding, MY-FLATTEN must
flatten a nested list if one exists:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun my-flatten (list)
  (labels ((recur (list new-list)
             (cond ((consp (rest list))
                    (if (consp (first list))
                        ;; flatten nested list, then follow list
                        ;; structure
                        ... list ... new-list ...
                        ;; follow list structure
                        ... list ... new-list ...))

                   ((not (null (rest list)))
                    (if (consp (first list))
                        ;; flatten nested list, then last cons of
                        ;; dotted list
                        ... list ... new-list ...
                        ;; last cons of dotted list
                        ... list ... new-list ...))

                   ((consp list)
                    (if (consp (first list))
                        ;; flatten nested list, then last cons of
                        ;; proper list
                        ... list ... new-list ...
                        ;; last cons of proper list
                        ... list ... new-list ...))

                   (t
                    new-list))))
    (nreverse (recur list '()))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun my-flatten (list)
  (labels ((recur (list new-list)
             (cond ((consp (rest list))
                    (if (consp (first list))
                        (recur (rest list)
                               (recur (first list) new-list))
                        (recur (rest list)
                               (cons (first list) new-list))))
                   ((not (null (rest list)))
                    (if (consp (first list))
                        (cons (rest list)
                              (recur (first list) new-list))
                        (cons (rest list)
                              (cons (first list) new-list))))
                   ((consp list)
                    (if (consp (first list))
                        (recur (first list) new-list)
                        (cons (first list) new-list)))
                   (t
                    new-list))))
    (nreverse (recur list '()))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;MY-FLATTEN should exhibit time and space complexities, both, of O(n^m),
where &amp;#8220;n&amp;#8221; is the length of a list, top level or nested, and &amp;#8220;m&amp;#8221; is the
depth of nesting.  The run times (non-GC) and consed bytes of the
following rough benchmarks suggest as much:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun benchmark (function data count)
  (let ((result))
    (cl-user::gc :all t)
    (time (dotimes (i count) (setf result (funcall function data))))))

CL-USER&amp;gt; (compile 'my-flatten)
=&amp;gt; MY-FLATTEN

CL-USER&amp;gt; (dolist (n '(100 1000 10000))
           (benchmark #'my-flatten (loop for i below n collect i) 1000))
Evaluation took:
  0.002 seconds of real time
  0.001000 seconds of total run time (0.001000 user, 0.000000 system)
  50.00% CPU
  3,252,278 processor cycles
  798,720 bytes consed

Evaluation took:
  0.013 seconds of real time
  0.012998 seconds of total run time (0.012998 user, 0.000000 system)
  100.00% CPU
  25,410,202 processor cycles
  7,999,488 bytes consed

Evaluation took:
  0.164 seconds of real time
  0.164975 seconds of total run time (0.160976 user, 0.003999 system)
  [ Run times consist of 0.030 seconds GC time, and 0.135 seconds non-GC time. ]
  100.61% CPU
  327,087,555 processor cycles
  80,010,016 bytes consed

=&amp;gt; NIL

CL-USER&amp;gt; (progn
          (benchmark #'my-flatten
                     (loop for i below 100 collect i)
                     1000)
          (benchmark #'my-flatten
                     (loop for i below 100 collect
                           (loop for j below 100 collect j))
                     1000)
          (benchmark #'my-flatten
                     (loop for i below 100 collect
                           (loop for j below 100 collect
                                 (loop for k below 100 collect k)))
                     1000))
Evaluation took:
  0.002 seconds of real time
  0.001999 seconds of total run time (0.001999 user, 0.000000 system)
  100.00% CPU
  3,193,193 processor cycles
  798,720 bytes consed

Evaluation took:
  0.163 seconds of real time
  0.164975 seconds of total run time (0.152977 user, 0.011998 system)
  [ Run times consist of 0.031 seconds GC time, and 0.134 seconds non-GC time. ]
  101.23% CPU
  326,155,035 processor cycles
  80,006,376 bytes consed

Evaluation took:
  74.040 seconds of real time
  74.008748 seconds of total run time (66.343914 user, 7.664834 system)
  [ Run times consist of 58.111 seconds GC time, and 15.898 seconds non-GC time. ]
  99.96% CPU
  147,707,388,885 processor cycles
  8,000,104,416 bytes consed

=&amp;gt; NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rewriting MY-FLATTEN using tail recursive calls would not reduce the
order of growth in space required to construct the resulting list; the
list must be built regardless.  Doing so, however, would, in most Common
Lisp implementations, prevent exhaustion of the call stack.&lt;/p&gt;

&lt;p&gt;The L-99&amp;#160;&lt;a href="http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/p07.lisp"&gt;solution&lt;/a&gt; is simpler than MY-FLATTEN, but it
doesn&amp;#8217;t solve the same problem: it fails on dotted lists and discards
elements that are NIL.&lt;/p&gt;

&lt;p&gt;Pascal J. Bourguignon provides four alternative
&lt;a href="http://www.informatimago.com/develop/lisp/l99/p07.lisp"&gt;solutions&lt;/a&gt;.  Of the three recursive implementations only
that with the worst performance works on dotted lists.  The iterative
one, referred to here as PJB-FLATTEN-3, avoids stack exhaustion and
works on dotted lists.  However, the behaviour of PJB-FLATTEN-3 belies
its intent.&lt;/p&gt;

&lt;p&gt;While the source and comment for PJB-FLATTEN-3 name its parameter
&amp;#8220;tree&amp;#8221;, it certainly doesn&amp;#8217;t collect the leaves of a Common Lisp tree:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (PB-FLATTEN-3 'NIL)
=&amp;gt; NIL ; Expected (NIL)

CL-USER&amp;gt; (PB-FLATTEN-3 '(A B C D E))
=&amp;gt; (A B C D E) ; Expected (A B C D E NIL)

CL-USER&amp;gt; (PB-FLATTEN-3 '(A (B (C . D) NIL E) NIL))
=&amp;gt; (A B C D E) ; Expected (A B C D NIL E NIL NIL NIL)
&lt;/code&gt;&lt;/pre&gt;</description><link>http://michaeljforster.tumblr.com/post/37612637569</link><guid>http://michaeljforster.tumblr.com/post/37612637569</guid><pubDate>Sun, 09 Dec 2012 21:33:00 -0600</pubDate><category>lisp</category><category>l-99</category></item><item><title>Building an Application with the Closure Library... and Lisp!</title><description>&lt;p&gt;Using the project directory and &lt;a href="http://weitz.de/hunchentoot/"&gt;Hunchentoot&lt;/a&gt; infrastructure I
created &lt;a href="http://michaeljforster.tumblr.com/post/31923719929/getting-started-with-google-closure-and-lisp"&gt;previously&lt;/a&gt;, I will use &lt;a href="http://cliki.net/"&gt;Common Lisp&lt;/a&gt; to write the
notepad application described in Google&amp;#8217;s &lt;a href="https://developers.google.com/closure/library/docs/tutorial"&gt;Building an Application
with the Closure Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Google tutorial illustrates the &lt;a href="https://developers.google.com/closure/"&gt;Closure&lt;/a&gt; namespace mechanism,
&lt;a href="http://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt; construction, and use of a Closure Library class.  I&amp;#8217;m
interested in the first two features, in particular.&lt;/p&gt;

&lt;h2&gt;A First Pass&lt;/h2&gt;

&lt;p&gt;I start by creating and editing a notepad.lisp file to define
Hunchentoot easy handlers corresponding to the notepad.html and
notepad.js from the tutorial:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(hunchentoot:define-easy-handler (notepad-js :uri "/notepad.js") ()
  (setf (hunchentoot:content-type*) "text/javascript")
  (ps:ps
    (ps:chain goog (provide "tutorial.notepad"))

    (ps:chain goog (require "goog.dom"))
    (ps:chain goog (require "goog.ui.Zippy"))

    (setf (ps:@ tutorial notepad append-notes)
          (lambda (data note-container)
            (dolist (datum data)
              (ps:chain goog dom
                        (append-child note-container
                                      (ps:chain tutorial notepad
                                                (make-note-dom datum)))))))

    (setf (ps:@ tutorial notepad make-note-dom)
          (lambda (note-datum)
            (let ((header-element
                   (ps:chain goog dom
                             (create-dom "div"
                                         (ps:create :style "background-color:#EEE")
                                         (ps:@ note-datum :title))))
                  (content-element
                   (ps:chain goog dom
                             (create-dom "div"
                                         nil
                                         (ps:@ note-datum :content)))))
              (ps:new (ps:chain goog ui (-Zippy header-element content-element)))
              (ps:chain goog dom
                        (create-dom "div"
                                    nil
                                    header-element
                                    content-element)))))))

(hunchentoot:define-easy-handler (notepad-html :uri "/notepad.html") ()
  (cl-who:with-html-output-to-string (*standard-output* nil :prologue t)
    (:html
     (:head
      (:title "Notepad")
      (:script :src "/js/goog/base.js")
      (:script :src "/notepad.js"))
     (:body
      (:div :id "notes")
      (:script
        (cl-who:str
         (ps:ps
           (defun main ()
             (let ((note-data
                    (list (ps:create :title "Note 1"
                                     :content "Content of Note 1")
                          (ps:create :title "Note 2"
                                     :content "Content of Note 2")))
                   (note-list-element
                    (ps:chain goog dom (get-element "notes"))))
               (ps:chain tutorial notepad
                         (append-notes note-data
                                       note-list-element))))
           (main))))))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, I add notepad.lisp to the components list of the system
definition in grok-google-closure-lisp.asd.  Then, I stop the
Hunchentoot acceptor, reload the project, and start the Hunchentoot
acceptor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GROK-GOOGLE-CLOSURE-LISP&amp;gt; (stop)
GROK-GOOGLE-CLOSURE-LISP&amp;gt; (ql:quickload "grok-google-closure-lisp")
...
=&amp;gt; ("grok-google-closure-lisp")
GROK-GOOGLE-CLOSURE-LISP&amp;gt; (start)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, I can browse the application URL
&lt;a href="http://localhost:4242/notepad.html"&gt;http://localhost:4242/notepad.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want to note that I did not translate the tutorial&amp;#8217;s Javascript to
&lt;a href="http://common-lisp.net/project/parenscript/"&gt;Parenscript&lt;/a&gt; directly.  That was deliberate.&lt;/p&gt;

&lt;p&gt;The debate over the pros and cons (even the definition) of OOP rages
elsewhere, but, here, I am concerned only with the simplicity,
directness, and clarity of the program.  I think the tutorial is less
simple, direct, and clear than it could be.&lt;/p&gt;

&lt;p&gt;To begin with, the definition of &lt;code&gt;main()&lt;/code&gt; represents note data simply
enough.  However, the call to &lt;code&gt;makeNotes()&lt;/code&gt; doesn&amp;#8217;t just make
notes (it doesn&amp;#8217;t even make &lt;em&gt;notes&lt;/em&gt;, it makes DOM &lt;em&gt;nodes&lt;/em&gt;), it also,
ultimately, appends them to the parent DOM.&lt;/p&gt;

&lt;p&gt;Of course, &lt;code&gt;makeNotes()&lt;/code&gt; doesn&amp;#8217;t append the nodes itself:  the
&lt;code&gt;makeNoteDom()&lt;/code&gt; method of the &lt;code&gt;Note&lt;/code&gt; object does that, &lt;em&gt;after&lt;/em&gt; it
constructs the node from its internal data, and using a reference to
the parent DOM included in the data for each note!&lt;/p&gt;

&lt;p&gt;Why do &lt;code&gt;makeNotes()&lt;/code&gt; and &lt;code&gt;makeNoteDom()&lt;/code&gt; make DOM nodes and have the
side effect of changing the parent DOM?  Why does the &lt;code&gt;Note&lt;/code&gt; object
have and use a reference to the parent DOM?&lt;/p&gt;

&lt;p&gt;One more annoyance (a smaller one):  Why does &lt;code&gt;makeNotes()&lt;/code&gt; build and
return an unused array of the constructed nodes?&lt;/p&gt;

&lt;p&gt;This, as Rich Hickey might &lt;a href="http://www.infoq.com/presentations/Simple-Made-Easy"&gt;say&lt;/a&gt;, is &lt;em&gt;complected&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Thus, I represent and access the data as a list of property lists
(which Parenscript will translate to an array of Javascript objects)
and eliminate the &lt;code&gt;Note&lt;/code&gt; constructor, I use &lt;code&gt;MAKE-NOTE-DOM&lt;/code&gt; only to
construct a DOM node from a note and eliminate the note field
referencing the parent DOM, and I have &lt;code&gt;APPEND-NOTES&lt;/code&gt; append the
constructed nodes to the parent DOM.&lt;/p&gt;

&lt;p&gt;I also want to draw attention to the definitions of &lt;code&gt;APPEND-NOTES&lt;/code&gt; and
&lt;code&gt;MAKE-NOTE-DOM&lt;/code&gt;.  To work with Closure&amp;#8217;s namespace convention I use
&lt;code&gt;goog.provide()&lt;/code&gt; and, rather than &lt;code&gt;DEFUN&lt;/code&gt;ing the functions, I assign
anonymous functions to those property names in the namespace object:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(ps:chain goog (provide "tutorial.notepad"))
...

(setf (ps:@ tutorial notepad append-notes)
      (lambda (data note-container)
        ...))

(setf (ps:@ tutorial notepad make-note-dom)
      (lambda (note-datum)
        ...))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, of course, rather than calling the functions directly, I must
use Parenscript&amp;#8217;s &lt;code&gt;CHAIN&lt;/code&gt; to access the property in the namespace:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(ps:chain tutorial notepad
          (append-notes note-data
                        note-list-element))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I would like to suppress these details of defining functions in a
Closure-like namespace.&lt;/p&gt;

&lt;h2&gt;Parenscript Namespaces&lt;/h2&gt;

&lt;p&gt;Parenscript &lt;a href="http://common-lisp.net/project/parenscript/reference.html#section-namespace"&gt;offers&lt;/a&gt; a mechanism to prefix Javascript names when
translating symbols in a Lisp package.  Using that, I can rewrite the
function definitions, storing them in a tutorial-notepad.paren file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(in-package "TUTORIAL.NOTEPAD")

(ps:chain goog (require "goog.dom"))
(ps:chain goog (require "goog.ui.Zippy"))

(defun tutorial.notepad::append-notes (data note-container)
  (dolist (datum data)
    (ps:chain goog dom
              (append-child note-container
                            (ps:chain tutorial
                                      notepad
                                      (make-note-dom datum))))))

(defun tutorial.notepad::make-note-dom (note-datum)
  (let ((header-element
         (ps:chain goog dom
                   (create-dom "div"
                               (ps:create :style "background-color:#EEE")
                               (ps:@ note-datum :title))))
        (content-element
         (ps:chain goog dom
                   (create-dom "div"
                               nil
                               (ps:@ note-datum :content)))))
    (ps:new (ps:chain goog ui (-Zippy header-element content-element)))
    (ps:chain goog dom
              (create-dom "div"
                          nil
                          header-element
                          content-element))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, I can define a Lisp package, set the Parenscript prefix, and
compile the tutoral-notepad.paren file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defpackage #:tutorial.notepad
  (:use #:cl))
(in-package #:tutorial.notepad)
(setf (ps:ps-package-prefix "TUTORIAL.NOTEPAD")
      "tutorial.notepad.")
(ps:ps-compile-file "/tmp/tutorial-notepad.paren")
=&amp;gt; ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, that won&amp;#8217;t work.  It doesn&amp;#8217;t provide the Closure namespace.
It prefixes all symbols in the package, including those from external
Javascript libraries, generating&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tutorial.notepad.goog.require('goog.dom');
tutorial.notepad.goog.require('goog.ui.Zippy');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;instead of&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;goog.require('goog.dom');
goog.require('goog.ui.Zippy');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, it defines a Javascript function with a prefixed name rather
than assigning an anonymous function to the property in the namespace,
generating&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function tutorial.notepad.appendNotes(tutorial.notepad.data,
                                      tutorial.notepad.noteContainer) {
    for (var tutorial.notepad.datum = null, _js_idx4 = 0;
         _js_idx4 &amp;lt; tutorial.notepad.data.length;
         _js_idx4 += 1) {
        tutorial.notepad.datum = tutorial.notepad.data[_js_idx4];
        tutorial.notepad.goog.tutorial.notepad.dom.tutorial.notepad.appendChild(tutorial.notepad.noteContainer,
            tutorial.notepad.tutorial.tutorial.notepad.notepad.tutorial.notepad.makeNoteDom(tutorial.notepad.datum));
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;instead of&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tutorial.notepad.appendNotes = function (data, noteContainer) {
    for (var datum = null, _js_idx101 = 0;
          _js_idx101 &amp;lt; data.length;
         _js_idx101 += 1) {
        datum = data[_js_idx101];
        goog.dom.appendChild(noteContainer, tutorial.notepad.makeNoteDom(datum));
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;A Simple Solution to a Simple Problem&lt;/h2&gt;

&lt;p&gt;Tempting as it is to consider patching Parenscript to address the
above issues, it&amp;#8217;s important to remember that Parenscript trades
complete translation of Common Lisp for a reduction in Javascript
runtime overhead.&lt;/p&gt;

&lt;p&gt;Following Parenscript&amp;#8217;s lead (and, indeed, that of Common Lisp&amp;#8217;s
&lt;code&gt;DEFUN&lt;/code&gt;), I can write a Parenscript macro (using &lt;code&gt;DEFPSMACRO&lt;/code&gt;) that
simply hides the details of building a function and assigning it to a
name in the namespace:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(ps:defpsmacro defun-in-namespace (namespace-list lambda-list &amp;amp;body body)
  "Defines a new function with the fully qualified Google
namespace /namespace-list/.  Assumes the namespace has been
defined via goog.provide()."
  `(setf (ps:@ ,@namespace-list)
         (lambda (,@lambda-list)
           ,@body)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, I can define the functions in the &lt;code&gt;NOTEPAD-JS&lt;/code&gt; handler as
follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun-in-namespace (tutorial notepad append-notes) (data note-container)
  (dolist (datum data)
    (ps:chain goog dom
              (append-child note-container
                            (ps:chain tutorial notepad
                                      (make-note-dom datum))))))

(defun-in-namespace (tutorial notepad make-note-dom) (note-datum)
  (let ((header-element
         (ps:chain goog dom
                   (create-dom "div"
                               (ps:create :style "background-color:#EEE")
                               (ps:@ note-datum :title))))
        (content-element
         (ps:chain goog dom
                   (create-dom "div"
                               nil
                               (ps:@ note-datum :content)))))
    (ps:new (ps:chain goog ui (-Zippy header-element content-element)))
    (ps:chain goog dom
              (create-dom "div"
                          nil
                          header-element
                          content-element))))
&lt;/code&gt;&lt;/pre&gt;</description><link>http://michaeljforster.tumblr.com/post/32885840431</link><guid>http://michaeljforster.tumblr.com/post/32885840431</guid><pubDate>Thu, 04 Oct 2012 14:33:00 -0500</pubDate><category>lisp</category></item><item><title>ASDF Mismagic</title><description>&lt;p&gt;Late last night, while reading &lt;a href="http://common-lisp.net/project/asdf/ilc2010draft.pdf"&gt;Evolving ASDF: More Cooperation, Less
Coordination&lt;/a&gt;, ASDF:SYSTEM-RELATIVE-PATHNAME caught my eye.  Handy
piece of magic, that, I thought as I pondered the hardwired pathname
variables littering specials.lisp files on my drives.&lt;/p&gt;

&lt;p&gt;Or not.  Fortunately, I had seen Zach Beane&amp;#8217;s post on &lt;a href="http://xach.livejournal.com/294639.html"&gt;Resource access
and ASDF&lt;/a&gt; earlier that day, and I agree:  ASDF should not serve as a
utility library.&lt;/p&gt;

&lt;p&gt;So, I begin this morning with a little mundane editing, the following
lifted shamelessly from Zach&amp;#8217;s post:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defpackage #:app-config (:export #:*base-directory*))
(defparameter app-config:*base-directory*
  (make-pathname :name nil :type nil :defaults *load-truename*))
&lt;/code&gt;&lt;/pre&gt;</description><link>http://michaeljforster.tumblr.com/post/31980308866</link><guid>http://michaeljforster.tumblr.com/post/31980308866</guid><pubDate>Fri, 21 Sep 2012 07:08:00 -0500</pubDate><category>lisp</category></item><item><title>Getting Started with Google Closure... and Lisp!</title><description>&lt;p&gt;At &lt;a href="http://www.sharedlogic.ca/"&gt;Shared Logic&lt;/a&gt;, we use Google&amp;#8217;s &lt;a href="https://developers.google.com/closure/"&gt;Closure Tools&lt;/a&gt; and &lt;a href="http://cliki.net/"&gt;Common
Lisp&lt;/a&gt; to write and deploy rich web applications.  In this article I
demonstrate our approach by writing the Hello, World! described in
Google&amp;#8217;s &lt;a href="https://developers.google.com/closure/library/docs/gettingstarted"&gt;Getting Started with the Closure Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, I create a project directory and download the Closure Library:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir -p ~/src/mjf/grok-google-closure-lisp/closure
cd ~/src/mjf/grok-google-closure-lisp/closure

svn checkout &lt;a href="http://closure-library.googlecode.com/svn/trunk/"&gt;http://closure-library.googlecode.com/svn/trunk/&lt;/a&gt; \
    closure-library
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By convention and regardless of web server infrastructure, we serve
static resources from a www sub-directory tree.  Here, I link in the
Javascript root of the Closure Library:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir -p ~/src/mjf/grok-google-closure-lisp/www/js
cd ~/src/mjf/grok-google-closure-lisp/www/js
ln -s ../../closure/closure-library/closure/goog .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Second, I create a Lisp project using Zach Beane&amp;#8217;s &lt;a href="http://www.quicklisp.org/"&gt;Quicklisp&lt;/a&gt; and
&lt;a href="https://github.com/xach/quickproject"&gt;Quickproject&lt;/a&gt;.  I will use &lt;a href="http://weitz.de/hunchentoot/"&gt;Hunchentoot&lt;/a&gt; to serve the
application, &lt;a href="http://weitz.de/cl-who/"&gt;CL-WHO&lt;/a&gt; to generate the HTML, and &lt;a href="http://common-lisp.net/project/parenscript/"&gt;Parenscript&lt;/a&gt; to
generate the Javascript:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (ql:quickload "quickproject")
...
=&amp;gt; ("quickproject")

CL-USER&amp;gt; (quickproject:make-project
          "~/src/mjf/grok-google-closure-lisp/"
          :depends-on '(hunchentoot cl-who
          parenscript))
=&amp;gt; "grok-google-closure-lisp"

CL-USER&amp;gt; (ql:quickload "grok-google-closure-lisp")
...
=&amp;gt; ("grok-google-closure-lisp")

CL-USER&amp;gt; (in-package #:grok-google-closure-lisp)
=&amp;gt; #&amp;lt;PACKAGE "GROK-GOOGLE-CLOSURE-LISP"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Third, I edit the grok-google-closure-lisp.lisp file to tweak some
Hunchentoot settings and define variables and utility functions to
manage the Hunchentoot acceptor and the dispatch table.  I add a folder
dispatcher to Hunchentoot&amp;#8217;s &lt;em&gt;DISPATCH-TABLE&lt;/em&gt; to serve static Javascript
files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;;;; grok-google-closure-lisp.lisp

(in-package #:grok-google-closure-lisp)

;;; "grok-google-closure-lisp" goes here. Hacks and glory await!

(setf hunchentoot:*catch-errors-p* nil) ; T for production
(setf hunchentoot:*show-lisp-errors-p* t)
(setf hunchentoot:*show-lisp-backtraces-p* t)

(defparameter *project-pathname*
  (merge-pathnames "src/mjf/grok-google-closure-lisp/"
                   (user-homedir-pathname)))

(defparameter *http-port* 4242)

(defvar *my-acceptor* nil)

(defun start ()
  (unless *my-acceptor*
    (push (hunchentoot:create-folder-dispatcher-and-handler
           "/js/"
          (merge-pathnames "www/js/"
                           *project-pathname*))
      hunchentoot:*dispatch-table*)
    (setf *my-acceptor*
          (hunchentoot:start (make-instance
                              'hunchentoot:easy-acceptor
                              :port *http-port*)))))

(defun stop ()
  (when *my-acceptor*
    (hunchentoot:stop *my-acceptor*)
    (setf hunchentoot:*dispatch-table*
          (last hunchentoot:*dispatch-table*))
    (setf *my-acceptor* nil)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Fourth, I create and edit a hello.lisp file to define Hunchentoot easy
handlers corresponding to the hello.js and hello.html from the Google
example.  I modify the script URLs according to our convention:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;;;; hello.lisp

(in-package #:grok-google-closure-lisp)

(hunchentoot:define-easy-handler (hello-js :uri "/hello.js") ()
  (setf (hunchentoot:content-type*) "text/javascript")
  (ps:ps
    (ps:chain goog (require "goog.dom"))

    (defun say-hi ()
      (let ((new-header
             (ps:chain goog dom
                       (create-dom "h1"
                                   (ps:create
                                    :style "background-color:")
                                    "Hello world!"))))
        (ps:chain goog dom
                  (append-child (ps:@ document body)
                                new-header))))))

(hunchentoot:define-easy-handler (hello :uri "/hello") ()
  (cl-who:with-html-output-to-string (*standard-output* nil :prologue t)
    (:html
     (:head
      (:script :src "/js/goog/base.js")
      (:script :src "/hello.js"))
     (:body :onload (ps:ps-inline (say-hi))))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Fifth, I add hello.lisp to the components list of the system definition
in grok-google-closure-lisp.asd, reload the project, and start the
Hunchentoot acceptor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GROK-GOOGLE-CLOSURE-LISP&amp;gt; (ql:quickload "grok-google-closure-lisp")
...
=&amp;gt; ("grok-google-closure-lisp")

GROK-GOOGLE-CLOSURE-LISP&amp;gt; (start)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, I can browse the application URL
&lt;a href="http://localhost:4242/hello"&gt;http://localhost:4242/hello&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yes, the Parenscript definition is a few lines longer than hello.js,
and, yes, I could &lt;a href="http://langnostic.blogspot.ca/2011/03/parenscript.html"&gt;shorten&lt;/a&gt; it with Lisp macros.  However, I have a
better plan.&lt;/p&gt;

&lt;p&gt;The Closure API, too, is more verbose than that of JQuery, Prototype,
YUI, and other Javascript libraries.  However, the latter are libraries
only, and their use of terse naming conventions and minifiers to control
code growth and its impact on performance is limited.  The Closure
Library is intended for use with the Closure Compiler, which provides
greater optimisation than minification alone, including dead code
elimination.&lt;/p&gt;

&lt;p&gt;As Google does with it&amp;#8217;s compiler, I will trade some terseness now for
much greater gain later using Lisp&amp;#8217;s magic in creating embedded domain
specific languages.  More to come.&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/31923719929</link><guid>http://michaeljforster.tumblr.com/post/31923719929</guid><pubDate>Thu, 20 Sep 2012 10:15:00 -0500</pubDate><category>lisp</category></item><item><title>L-99: P06 - Find out whether a list is a palindrome</title><description>&lt;p&gt;The sixth &lt;a href="http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html"&gt;L-99&lt;/a&gt; problem is to write a predicate that detects a list
that is a &lt;a href="http://en.wikipedia.org/wiki/Palindrome"&gt;palindrome&lt;/a&gt;: a sequence that can be read the same way
forward or backward.&lt;/p&gt;

&lt;p&gt;The simplest (and an efficient) solution is right there in the
definition of a palindrome, but it&amp;#8217;s easy to &amp;#8220;follow your nose&amp;#8221; through
the &lt;em&gt;construction&lt;/em&gt; of palindromes and end up writing something more
complicated.  The real lesson of the sixth L-99 problem is less about
lists and more about &amp;#8220;forests&amp;#8221; and &amp;#8220;trees&amp;#8221;.&lt;/p&gt;

&lt;p&gt;The problem description immediately restricts us to a list
representation, and, although it isn&amp;#8217;t specified, I&amp;#8217;ll assume the list
must be proper.  LIST-PALINDROME-P should work as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(list-palindrome-p 42) ; TYPE-ERROR: 42
(list-palindrome-p '(a b c d . e)) ; TYPE-ERROR: E
(list-palindrome-p '()) =&amp;gt; T
(list-palindrome-p '(a b b a)) =&amp;gt; T
(list-palindrome-p '(a b c b a)) =&amp;gt; T
(list-palindrome-p '(a b c b a b)) =&amp;gt; NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, I&amp;#8217;ll write a utility function to construct palindrome lists:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defparameter *alphabet* "abcdefghijklmnopqrstuvwxyz")

(defparameter *alphabet-length* 26)

(defun random-character ()
  (elt *alphabet*
       (random *alphabet-length*)))

(defun make-palindrome (length)
  (let ((l '()))
    (multiple-value-bind (quotient remainder)
        (floor length 2)
      (dotimes (i quotient)
        (push (random-character) l))
      (let ((middle (if (plusp remainder)
                        (list (random-character))
                        '())))
        (append l middle (reverse l))))))

CL-USER&amp;gt; (make-palindrome 11)
=&amp;gt; (#\y #\i #\z #\d #\j #\y #\j #\d #\z #\i #\y)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While scratching that out, I was thinking about a point in the Wikipedia
article on &lt;a href="http://en.wikipedia.org/wiki/Palindrome"&gt;palindromes&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In addition, the set of palindromes may not be reliably tested by a
  deterministic pushdown automaton and is not LR(k)-parsable. When
  reading a palindrome from left-to-right, it is, in essence, impossible
  to locate the &amp;#8220;middle&amp;#8221; until the entire word has been read completely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The middle&amp;#8230; right!  If I can find the middle of the list, I can
traverse the list from both ends at once, comparing corresponding
elements.  If a pair of elements differs, the list is not a palindrome;
otherwise, when the pointers meet or pass, I have a palindrome.  Easy
enough to write:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun list-palindrome-p (list)
  (do ((i 0 (1+ i))
       (j (1- (length list)) (1- j)))
      ((or (= i j) (&amp;lt; j i)) t)
    (unless (equal (nth i list)
                   (nth j list))
      (return nil))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That will run in O(1) space and O(n^2) time.  To measure the performance
gain, if any, of the list-specific accessor &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_nth.htm"&gt;NTH&lt;/a&gt;, I wrote a version
using the more general &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_elt.htm"&gt;ELT&lt;/a&gt; sequence accessor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun seq-palindrome-p (seq)
  (do ((i 0 (1+ i))
       (j (1- (length seq)) (1- j)))
      ((or (= i j) (&amp;lt; j i)) t)
    (unless (equal (elt seq i)
                   (elt seq j))
      (return nil))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To measure the performance hit of list element access, O(n) on average,
I wrote a vector-based version using the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_svref.htm"&gt;SVREF&lt;/a&gt; vector accessor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun vector-palindrome-p (vector)
  (do ((i 0 (1+ i))
       (j (1- (length vector)) (1- j)))
      ((or (= i j) (&amp;lt; j i)) t)
    (unless (equal (svref vector i)
                   (svref vector j))
      (return nil))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are some benchmarks under SBCL 1.0.50 on my machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (compile 'list-palindrome-p)
=&amp;gt; LIST-PALINDROME-P

CL-USER&amp;gt; (compile 'seq-palindrome-p)
=&amp;gt; SEQ-PALINDROME-P

CL-USER&amp;gt; (compile 'vector-palindrome-p)
=&amp;gt; VECTOR-PALINDROME-P

CL-USER&amp;gt; (defparameter *palindrome* (make-palindrome 100001))
=&amp;gt; ...

CL-USER&amp;gt; (defparameter *vpalindrome* (coerce *palindrome* 'vector))
=&amp;gt; *VPALINDROME*

CL-USER&amp;gt; (defparameter *result* nil)
=&amp;gt; *RESULT*

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000 (setf *result* (list-palindrome-p *palindrome*)))))
Evaluation took:
  9.641 seconds of real time
  10.133459 seconds of total run time (10.133459 user, 0.000000 system)
  105.10% CPU
  19,234,325,700 processor cycles
  66,096 bytes consed
=&amp;gt; T

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000 (setf *result* (seq-palindrome-p *palindrome*)))))
Evaluation took:
  38.109 seconds of real time
  39.323022 seconds of total run time (39.323022 user, 0.000000 system)
  103.19% CPU
  76,026,725,220 processor cycles
  254,312 bytes consed
=&amp;gt; T

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000 (setf *result* (vector-palindrome-p *vpalindrome*)))))
Evaluation took:
  0.002 seconds of real time
  0.002000 seconds of total run time (0.002000 user, 0.000000 system)
  100.00% CPU
  3,609,922 processor cycles
  0 bytes consed
=&amp;gt; T
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The list-specific accessor NTH is faster and conses less than ELT.
Unsurprisingly, where repeated arbitrary element access is required, a
vector is the better choice.  VECTOR-PALINDROME-P runs in O(n) time and
O(1) space.&lt;/p&gt;

&lt;p&gt;However, I can write a list-based solution that is simpler and faster
than LIST-PALINDROME-P.  It trades space (O(n)) for speed (O(n)).  As I
noted above, a palindrome is a sequence that reads the same forward or
backward:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun simple-list-palindrome-p (list)
  (equal list (reverse list)))

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000 (setf *result* (simple-list-palindrome-p *palindrome*)))))
Evaluation took:
  0.002 seconds of real time
  0.002000 seconds of total run time (0.002000 user, 0.000000 system)
  100.00% CPU
  4,399,568 processor cycles
  802,816 bytes consed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;#l-99&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/31663169464</link><guid>http://michaeljforster.tumblr.com/post/31663169464</guid><pubDate>Sun, 16 Sep 2012 11:05:00 -0500</pubDate><category>lisp</category><category>l-99</category></item><item><title>L-99: P05 - Reverse a list</title><description>&lt;p&gt;CL&amp;#8217;s &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_revers.htm"&gt;REVERSE&lt;/a&gt; returns a new sequence of elements in reverse order
from the given sequence.  The given sequence must be proper, either
a proper list or vector, and REVERSE should be prepared to signal a
TYPE-ERROR otherwise.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html"&gt;L-99&lt;/a&gt;&amp;#8217;s REVERSE-A-LIST is a list-only version of REVERSE and should
work as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(reverse-a-list 42) ; TYPE-ERROR: 42
(reverse-a-list '(a b c d . e)) ; TYPE-ERROR: E
(reverse-a-list '()) =&amp;gt; NIL
(reverse-a-list '(a b c d e)) =&amp;gt; (E D C B A)
(reverse-a-list '(a (b c) d e)) =&amp;gt; (E D (B C) A)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Constructing the reverse of a list can be simple and efficient if you
realise that it occurs in the direction (tail to head) opposing the
traversal of the original list (head to tail).  Recursion juxtaposes
these two operations elegantly:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun reverse-a-list (list)
  (labels ((recur (list1 reversed)
             (if (null list1)
                 reversed
                 (recur (cdr list1)
                        (cons (car list1) reversed)))))
    (recur list '())))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, an imperative solution needn&amp;#8217;t be inelegant thanks to CL&amp;#8217;s
&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_dolist.htm"&gt;DOLIST&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun reverse-a-list-1 (list)
  (let ((reversed '()))
    (dolist (x list reversed)
      (push x reversed))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are some benchmarks under SBCL 1.0.50 on my machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (compile 'reverse-a-list)
=&amp;gt; REVERSE-A-LIST

CL-USER&amp;gt; (compile 'reverse-a-list-1)
=&amp;gt; REVERSE-A-LIST-1

CL-USER&amp;gt; (defvar *list* (loop for i below 1000000 collect i))
=&amp;gt; ...

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (setf *list2* (reverse *list*))))
Evaluation took:
  68.795 seconds of real time
  68.730550 seconds of total run time (62.520495 user, 6.210055 system)
  [ Run times consist of 59.584 seconds GC time, and 9.147 seconds non-GC time. ]
  99.91% CPU
  137,244,569,535 processor cycles
  8,000,125,152 bytes consed
=&amp;gt; NIL

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (setf *list2* (reverse-a-list *list*))))
Evaluation took:
  69.083 seconds of real time
  69.000510 seconds of total run time (62.492499 user, 6.508011 system)
  [ Run times consist of 59.851 seconds GC time, and 9.150 seconds non-GC time. ]
  99.88% CPU
  137,819,915,692 processor cycles
  8,000,128,320 bytes consed
=&amp;gt; NIL

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (setf *list2* (reverse-a-list-2 *list*))))
Evaluation took:
  68.533 seconds of real time
  68.494587 seconds of total run time (62.094560 user, 6.400027 system)
  [ Run times consist of 59.382 seconds GC time, and 9.113 seconds non-GC time. ]
  99.94% CPU
  136,721,884,103 processor cycles
  8,000,122,856 bytes consed
=&amp;gt; NIL
&lt;/code&gt;&lt;/pre&gt;</description><link>http://michaeljforster.tumblr.com/post/25311443913</link><guid>http://michaeljforster.tumblr.com/post/25311443913</guid><pubDate>Sun, 17 Jun 2012 15:07:00 -0500</pubDate><category>lisp</category><category>l-99</category></item><item><title>Dead Code is Fast Code</title><description>&lt;p&gt;I use the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_time.htm"&gt;TIME&lt;/a&gt; macro to benchmark my &lt;a href="http://www.ic.unicamp.br/&amp;amp;;meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html"&gt;L-99&lt;/a&gt; solutions, as the
ANSI CL Specification advises, not &amp;#8220;for marketing comparisons&amp;#8221; but &amp;#8220;for
tuning purposes.&amp;#8221;  I want to know how well a solution that I optimise
for &lt;a href="http://www.infoq.com/presentations/Simple-Made-Easy"&gt;simplicity&lt;/a&gt; fares against others, especially a standard CL
function.&lt;/p&gt;

&lt;p&gt;Still, for my purposes, I could improve my methodology.  I should run
the benchmarks on both of the CL implementations that I use for work,
&lt;a href="http://www.sbcl.org/"&gt;SBCL&lt;/a&gt; and &lt;a href="http://www.lispworks.com/"&gt;LispWorks&lt;/a&gt;.  I should invoke the garbage collector
before each run to reduce the impact of previous runs.  And, as I just
discovered, I shouldn&amp;#8217;t benchmark &lt;a href="http://en.wikipedia.org/wiki/Dead_code_elimination"&gt;dead code&lt;/a&gt;, because dead code is
deceptively quick!&lt;/p&gt;

&lt;p&gt;Consider the following, run under SBCL 1.0.50 on my machine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (defvar *list* (loop for i below 1000000 collect i))
=&amp;gt; ...

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (last *list*)))
Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  6,052 processor cycles
  0 bytes consed
=&amp;gt; NIL

CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (reverse *list*)))
Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  14,783 processor cycles
  0 bytes consed
=&amp;gt; NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I didn&amp;#8217;t expect &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_last.htm"&gt;LAST&lt;/a&gt; to take very long or cons much, but
&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_revers.htm"&gt;REVERSE&lt;/a&gt; should have ticked and consed a detectable amount since it
returns a fresh list.  If I introduce a O(1) side effect into the loop,
then I get different results:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER&amp;gt; (gc :all t)
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (setf *list2* (last *list*))))
Evaluation took:
  2.430 seconds of real time
  2.429630 seconds of total run time (2.427631 user, 0.001999 system)
  100.00% CPU
  4,847,069,902 processor cycles
  13,008 bytes consed
=&amp;gt; NIL

CL-USER&amp;gt; (time (dotimes (i 1000) (setf *list2* (reverse *list*))))
Evaluation took:
  68.795 seconds of real time
  68.730550 seconds of total run time (62.520495 user, 6.210055 system)
  [ Run times consist of 59.584 seconds GC time, and 9.147 seconds non-GC time. ]
  99.91% CPU
  137,244,569,535 processor cycles
  8,000,125,152 bytes consed
=&amp;gt; NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It seems that SBCL eliminates dead code evaluated in the REPL.
LispWorks 6.0.1 on my machine does not appear to do so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER 10 &amp;gt; (defvar *list* (loop for i below 1000000 collect i))
=&amp;gt; ...

CL-USER 11 &amp;gt; (gc-if-needed)
=&amp;gt; NIL

CL-USER 12 &amp;gt; (time (dotimes (i 1000) (last *list*)))
Timing the evaluation of (DOTIMES (I 1000) (LAST *LIST*))

User time    =        2.957
System time  =        0.002
Elapsed time =        2.944
Allocation   = 46864 bytes
0 Page faults
Calls to %EVAL    15056
NIL

CL-USER 13 &amp;gt; (gc-if-needed)
=&amp;gt; NIL

CL-USER 14 &amp;gt; (time (dotimes (i 1000) (reverse *list*)))
Timing the evaluation of (DOTIMES (I 1000) (REVERSE *LIST*))

User time    =       29.313
System time  =        0.054
Elapsed time =       29.398
Allocation   = 18446744072824721376 bytes
0 Page faults
Calls to %EVAL    15056
NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Indeed, introducing the same side effect as before does not change the
results appreciably:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CL-USER 15 &amp;gt; (gc-if-needed)
=&amp;gt; NIL

CL-USER 16 &amp;gt; (time (dotimes (i 1000) (setf *list2* (last *list*))))
Timing the evaluation of (DOTIMES (I 1000) (SETF *LIST2* (LAST *LIST*)))

User time    =        2.981
System time  =        0.002
Elapsed time =        2.963
Allocation   = 1411712 bytes
0 Page faults
Calls to %EVAL    19056
NIL

CL-USER 17 &amp;gt; (gc-if-needed)
=&amp;gt; NIL

CL-USER 18 &amp;gt; (time (dotimes (i 1000) (setf *list2* (reverse *list*))))
Timing the evaluation of (DOTIMES (I 1000) (SETF *LIST2* (REVERSE *LIST*)))

User time    =       38.678
System time  =        0.012
Elapsed time =       38.682
Allocation   = 18446744072826093508 bytes
0 Page faults
Calls to %EVAL    19056
NIL
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I will be sure to include this simple side effect in future L-99
benchmarks.&lt;/p&gt;</description><link>http://michaeljforster.tumblr.com/post/25290922760</link><guid>http://michaeljforster.tumblr.com/post/25290922760</guid><pubDate>Sun, 17 Jun 2012 08:53:00 -0500</pubDate><category>lisp</category></item></channel></rss>
