<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-12983281</id><updated>2011-09-10T07:06:50.555-07:00</updated><category term='robot'/><category term='scheme'/><category term='lisp'/><category term='NXT'/><category term='common lisp'/><title type='text'>I Need Closure(s)</title><subtitle type='html'>A blog about Lisp, general topics that interest me, and other programming languages, in that order.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-12983281.post-5670435238129360931</id><published>2008-01-30T08:19:00.000-08:00</published><updated>2008-12-09T19:14:50.428-08:00</updated><title type='text'>'Programming Collective Intelligence' in Common Lisp, Chapter 5 - Optimizations</title><content type='html'>Back from the holidays and plowing through the chapters again. The explanation for the various optimizations was good, but I had a hard time figuring out a more "Lisp-like" way of doing the code. Either there isn't, or I haven't quite reached Zen-like Lisp nirvana. I'm open to improvements, here's the code for &lt;a href="http://blubparadox.googlepages.com/optimize.lisp"&gt;the generic optimizations&lt;/a&gt; and &lt;a href="http://blubparadox.googlepages.com/socialnetwork.lisp"&gt;the social network&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For these python translations I'm growing fond of the &lt;a href="http://superadditive.com/projects/incf-cl/"&gt;(incf cl) utilities&lt;/a&gt;. It includes macros to make list comprehensions in Lisp, so&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;sol=[random.randint(domain[i][0],domain[i][1])&lt;br /&gt;     for i in range(len(domain))]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;becomes&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(defun range-random (low high)&lt;br /&gt; (+ low (random (1+ (- high low)))))&lt;br /&gt;...&lt;br /&gt;(let ((sol (assemble (range-random (car x) (cdr x)) (&lt;- x domain)))) &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I know that one would be just as easy with mapcar, see incf-cl for better examples.&lt;br /&gt;&lt;br /&gt;Here's a graph made from a simulated annealing optimization of the social network graph:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HdYrIZK4E04/R6CkfiCDFFI/AAAAAAAAADI/pGM6AANlla8/s1600-h/social.jpg"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_HdYrIZK4E04/R6CkfiCDFFI/AAAAAAAAADI/pGM6AANlla8/s400/social.jpg" alt="" id="BLOGGER_PHOTO_ID_5161306034584884306" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-5670435238129360931?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/5670435238129360931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=5670435238129360931' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/5670435238129360931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/5670435238129360931'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2008/01/programming-collective-intelligence-in.html' title='&apos;Programming Collective Intelligence&apos; in Common Lisp, Chapter 5 - Optimizations'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HdYrIZK4E04/R6CkfiCDFFI/AAAAAAAAADI/pGM6AANlla8/s72-c/social.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-2247153525085221912</id><published>2007-10-11T05:25:00.001-07:00</published><updated>2008-12-09T19:14:50.722-08:00</updated><title type='text'>Programming Collective Intelligence - Viewing Data in Two Dimensions</title><content type='html'>An example of taking data in multiple dimensions and "scaling" it to two dimensions, where the distances between data points is proportional to the multi-dimensional distance. Again, this one is basically an imperative rewrite. I hope to be able to exploit more of Lisp's power in the next chapter, which includes some neural networks. The big revelation from this, if anyone says Lisp is unreadable, I'd show them&lt;br /&gt;&lt;code&gt;&lt;br /&gt;fakedist[i][j] = sqrt(sum([pow(loc[i][x] - loc[j][x], 2)&lt;br /&gt;                                             for x in range(len(loc[i]))]))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I replaced &lt;a href="http://blubparadox.googlepages.com/clusters.lisp"&gt;clusters.lisp&lt;/a&gt;, new code is in it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HdYrIZK4E04/Rw4X9201efI/AAAAAAAAAC4/oU6kyXRqNR0/s1600-h/twod.png"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_HdYrIZK4E04/Rw4X9201efI/AAAAAAAAAC4/oU6kyXRqNR0/s400/twod.png" alt="" id="BLOGGER_PHOTO_ID_5120056177823414770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Zooming in,&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HdYrIZK4E04/Rw4YJW01egI/AAAAAAAAADA/b8UUBqb9uu8/s1600-h/twod-portion.png"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_HdYrIZK4E04/Rw4YJW01egI/AAAAAAAAADA/b8UUBqb9uu8/s400/twod-portion.png" alt="" id="BLOGGER_PHOTO_ID_5120056375391910402" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-2247153525085221912?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/2247153525085221912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=2247153525085221912' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/2247153525085221912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/2247153525085221912'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2007/10/programming-collective-intelligence.html' title='Programming Collective Intelligence - Viewing Data in Two Dimensions'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HdYrIZK4E04/Rw4X9201efI/AAAAAAAAAC4/oU6kyXRqNR0/s72-c/twod.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-7930627205570606708</id><published>2007-09-27T18:57:00.000-07:00</published><updated>2008-12-09T19:14:51.060-08:00</updated><title type='text'>'Programming Collective Intelligence' in Common Lisp, Chapter 3 - Hierarchical Clusters</title><content type='html'>I have Common Lisp code for Chapter 3 up to Hierarchical Clusters. It's longer and not that interesting, so I'll just put up a &lt;a href="http://blubparadox.googlepages.com/clusters.lisp"&gt;link to the code&lt;/a&gt;. Once again, map and reduce are taking the place of list comprehensions, but other than that it's not particularly Lispy, no macrology or anything. Maybe next time.&lt;br /&gt;&lt;br /&gt;Last time's tangent was a shortcut to hash syntax. This time I'm not happy with deleting items out of the middle of adjustable arrays. The code puts items on the end of an array and deletes them out of the middle, from a particular position.&lt;br /&gt;In Python it's&lt;br /&gt;&lt;code&gt;del clust[lowestpair[0]]&lt;/code&gt;&lt;br /&gt;What I have is&lt;br /&gt;&lt;code&gt;&lt;br /&gt;(defun truep (x) (declare (ignore x)) t)&lt;br /&gt;(setf clust (delete-if #'truep clust :start (car lowestpair) :end (1+ (car lowestpair))))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Instead of PCI's use of the Python Imaging Library or some Lisp equivalent, I used cl-pdf, which was easy to use to make the simple graphs, lines and text. This is the full hierarchical cluster, then a zoom view.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HdYrIZK4E04/Rvxow201edI/AAAAAAAAACQ/X2Oc-KSKZ5g/s1600-h/ch03-hcluster-dendogram.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_HdYrIZK4E04/Rvxow201edI/AAAAAAAAACQ/X2Oc-KSKZ5g/s400/ch03-hcluster-dendogram.jpg" alt="" id="BLOGGER_PHOTO_ID_5115078465346173394" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HdYrIZK4E04/Rvxo9G01eeI/AAAAAAAAACY/RcxO6-Begfc/s1600-h/ch03-hcluster-dendogram-piece.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_HdYrIZK4E04/Rvxo9G01eeI/AAAAAAAAACY/RcxO6-Begfc/s400/ch03-hcluster-dendogram-piece.jpg" alt="" id="BLOGGER_PHOTO_ID_5115078675799570914" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-7930627205570606708?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/7930627205570606708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=7930627205570606708' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/7930627205570606708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/7930627205570606708'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2007/09/programming-collective-intelligence-in_27.html' title='&apos;Programming Collective Intelligence&apos; in Common Lisp, Chapter 3 - Hierarchical Clusters'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HdYrIZK4E04/Rvxow201edI/AAAAAAAAACQ/X2Oc-KSKZ5g/s72-c/ch03-hcluster-dendogram.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-9213041307681232671</id><published>2007-09-12T11:35:00.000-07:00</published><updated>2007-09-12T11:40:08.642-07:00</updated><title type='text'>'Programming Collective Intelligence' in Common Lisp, Chapter 2</title><content type='html'>Like many others, I've been reading Toby Segaran's &lt;a href="http://www.amazon.com/Programming-Collective-Intelligence-Building-Applications/dp/0596529325/ref=pd_bbs_sr_1/103-3854821-2635829?ie=UTF8&amp;s=books&amp;qid=1189621369&amp;sr=8-1"&gt;Programming Collective Intelligence&lt;/a&gt;. Toby's examples are in Python. Inspired by loucal's &lt;a href="http://loucal.net/index.php?title=programming_collective_intelligence_with&amp;more=1&amp;c=1&amp;tb=1&amp;pb=1"&gt;posting of code examples in Ruby&lt;/a&gt;, I've decided to put up my own Common Lisp examples. These are from Chapter 2, going up to page 15, "Ranking the Critics".&lt;br /&gt;&lt;br /&gt;In order to just have the recommendations in the file, I used assoc lists instead of hashes. One place where Python (and Ruby) has it over Lisp is in hash syntax, just &lt;code&gt;critics[person]&lt;/code&gt; instead of &lt;code&gt;(gethash person critics)&lt;/code&gt; or &lt;code&gt;(cdr (assoc person critics :test #'equalp))&lt;/code&gt;. I made a 'critics' function to keep down the verbosity. Is there a good way to change the syntax for hash lookup?&lt;br /&gt;&lt;br /&gt;The other big difference is my use of &lt;code&gt;mapcar&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt; everywhere instead of Python's list comprehensions, with the occaisional &lt;code&gt;intersection&lt;/code&gt; thrown in.&lt;br /&gt;&lt;br /&gt;If the Python source code gets posted, I may try some benchmarks with later examples.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(defparameter *RECOMMENDATIONS* &lt;br /&gt;  '(&lt;br /&gt;    ("Lisa Rose" . (("Lady in the Water" . 2.5) ("Snakes on a Plane" . 3.5) ("Just My Luck" . 3.0) &lt;br /&gt;                    ("Superman Returns" . 3.5) ("You, Me and Dupree" . 2.5) ("The Night Listener" . 3.0)))&lt;br /&gt;    ("Gene Seymour" . (("Lady in the Water" . 3.0) ("Snakes on a Plane" . 3.5) ("Just My Luck" . 1.5) &lt;br /&gt;                       ("Superman Returns" . 5.0) ("The Night Listener" . 3.0) ("You, Me and Dupree" . 3.5)))&lt;br /&gt;    ("Michael Phillips" . (("Lady in the Water" . 2.5) ("Snakes on a Plane" . 3.0) &lt;br /&gt;                           ("Superman Returns" . 3.5) ("The Night Listener" . 4.0)))&lt;br /&gt;    ("Claudia Puig" . (("Snakes on a Plane" . 3.5) ("Just My Luck" . 3.0) ("The Night Listener" . 4.5) &lt;br /&gt;                       ("Superman Returns" . 4.0) ("You, Me and Dupree" . 2.5)))&lt;br /&gt;    ("Mick LaSalle" . (("Lady in the Water" . 3.0) ("Snakes on a Plane" . 4.0) ("Just My Luck" . 2.0) &lt;br /&gt;                       ("Superman Returns" . 3.0) ("The Night Listener" . 3.0) ("You, Me and Dupree" . 2.0)))&lt;br /&gt;    ("Jack Matthews" . (("Lady in the Water" . 3.0) ("Snakes on a Plane" . 4.0) ("The Night Listener" . 3.0) &lt;br /&gt;                        ("Superman Returns" . 5.0) ("You, Me and Dupree" . 3.5)))&lt;br /&gt;    ("Toby" . (("Snakes on a Plane" . 4.5) ("You, Me and Dupree" . 1.0) &lt;br /&gt;               ("Superman Returns" . 4.0)))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(defun critics (reviewer &amp;optional movie)&lt;br /&gt;  (labels ((get-movie (ms m)&lt;br /&gt;             (cdr (assoc m ms :test #'equalp))))&lt;br /&gt;    (let ((movies (cdr (assoc reviewer *RECOMMENDATIONS* :test #'equalp))))&lt;br /&gt;      (if movie (get-movie movies movie) movies))))&lt;br /&gt;&lt;br /&gt;(defun similar (person1 person2 distance)&lt;br /&gt;  (let* ((movies1 (critics person1))&lt;br /&gt;         (movies2 (critics person2))&lt;br /&gt;         (common-movies (mapcar #'car (intersection movies1 movies2 &lt;br /&gt;                                                    :test #'(lambda (x y) (equalp (car x) (car y)))))))&lt;br /&gt;    (if (null common-movies)&lt;br /&gt;        nil&lt;br /&gt;        (funcall distance person1 person2 common-movies))))&lt;br /&gt;&lt;br /&gt;(defun euclidean-distance (person1 person2 common-movies)&lt;br /&gt;  (let* ((sum-of-squares (reduce #'+ (mapcar &lt;br /&gt;                                      #'(lambda (cm) &lt;br /&gt;                                          (expt (- (critics person1 cm) (critics person2 cm)) 2)) &lt;br /&gt;                                      common-movies)))&lt;br /&gt;         (distance (/ 1 (1+ sum-of-squares))))&lt;br /&gt;    distance))&lt;br /&gt;&lt;br /&gt;(defun sim-distance (person1 person2)&lt;br /&gt;  (similar person1 person2 #'euclidean-distance))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(defun pearson-distance (person1 person2 common-movies)&lt;br /&gt;  (let* ((n (length common-movies))&lt;br /&gt;         (scores1 (mapcar #'(lambda (x) (critics person1 x)) common-movies))&lt;br /&gt;         (scores2 (mapcar #'(lambda (x) (critics person2 x)) common-movies))&lt;br /&gt;         (sum1 (reduce #'+ scores1))&lt;br /&gt;         (sum2 (reduce #'+ scores2))&lt;br /&gt;         (sum1-sq (reduce #'+ (mapcar #'(lambda (x) (* x x)) scores1)))&lt;br /&gt;         (sum2-sq (reduce #'+ (mapcar #'(lambda (x) (* x x)) scores2)))&lt;br /&gt;         (psum (reduce #'+ (mapcar #'* scores1 scores2)))&lt;br /&gt;         (num (- psum (/ (* sum1 sum2) n)))&lt;br /&gt;         (den (sqrt (* (- sum1-sq (/ (expt sum1 2) n)) (- sum2-sq (/ (expt sum2 2) n))))))&lt;br /&gt;    (if (zerop den) 0 (/ num den))))&lt;br /&gt;&lt;br /&gt;(defun sim-pearson (person1 person2)&lt;br /&gt;  (similar person1 person2 #'pearson-distance))&lt;br /&gt;         &lt;br /&gt;(defun top-matches (person &amp;optional (n 5) (similarity #'sim-pearson))&lt;br /&gt;  (let* ((scores (mapcar #'(lambda (x) (cons (funcall similarity person x) x)) &lt;br /&gt;                         (remove-if #'(lambda (x) (equalp x person)) (mapcar #'car *RECOMMENDATIONS*))))&lt;br /&gt;         (sorted-scores (sort scores #'&gt; :key #'car))&lt;br /&gt;         (len (length sorted-scores)))&lt;br /&gt;    (if (&lt;= len n)&lt;br /&gt;        sorted-scores&lt;br /&gt;        (butlast sorted-scores (- len n)))))&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-9213041307681232671?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/9213041307681232671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=9213041307681232671' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/9213041307681232671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/9213041307681232671'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2007/09/programming-collective-intelligence-in.html' title='&apos;Programming Collective Intelligence&apos; in Common Lisp, Chapter 2'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-285187211121865200</id><published>2007-05-17T21:06:00.000-07:00</published><updated>2008-12-09T19:14:51.340-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='NXT'/><category scheme='http://www.blogger.com/atom/ns#' term='robot'/><title type='text'>Redefining it</title><content type='html'>"The best way to solve a problem is often to redefine it." - &lt;span style="font-style: italic;"&gt;Michael Rabin, via Paul Graham&lt;/span&gt;&lt;br /&gt;"I don't like assembly language." - &lt;span style="font-style: italic;"&gt;Richard Cook&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Last August I got a Lego NXT robot, and of course I wanted to program it in Lisp. I got Frank Klassner's RCXLisp code and the NXT programming manual, and made a start, looking at opcodes and twiddling bits, and jump offsets, but it was, well, opcodes and bits, and I just wanted to make the robot do things, and it was a big hurdle, and so I procrastinated, and did other things. All that munging with assembly wasn't that interesting a problem to me, and when (if?) I got some output, and it didn't work, then I'd have to try to decipher the disassembled code, and act like the NXT VM, and "run" it...&lt;br /&gt;&lt;br /&gt;The light bulb went off a couple of weeks ago. Other people have done most of the heavy lifting for me - there were compilers for other languages for the NXT. I didn't have to get from Lisp to assembly, I just had to get from Lisp to the intermediary language, which would catch syntax errors and I could look at my program's output without going crazy. After some looking around I decided to go with NXC, which has a C syntax. The advantage of a C syntax instead of, say, Basic or Lua is that I have a pretty good head start. Since Javascript has a syntax that's close to C, I started with parenscript and am modifying it to turn it from a Lisp-&gt;Javascript compiler into a Lisp-&gt;NXC compiler.&lt;br /&gt;&lt;br /&gt;I've made a few changes, enough to let me compile a test program&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defconstant *MYNUM* 100)&lt;br /&gt;&lt;br /&gt;(defun runout (offset multiplier)&lt;br /&gt;(-num-out 0 offset (* *MYNUM* multiplier)))&lt;br /&gt;&lt;br /&gt;(defthread (main :primary t) ()&lt;br /&gt;(let ((x 0))&lt;br /&gt; (setf x 1)&lt;br /&gt; (runout *LCD_LINE1* x)&lt;br /&gt; (setf x 2)&lt;br /&gt; (runout *LCD_LINE2* x)&lt;br /&gt; (-wait 10000)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;into&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include "NXCDefs.h"&lt;br /&gt;&lt;br /&gt;#define MYNUM 100&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;sub runout(int &lt;br /&gt;           offset,&lt;br /&gt;           int &lt;br /&gt;           multiplier) {&lt;br /&gt;  NumOut(0, offset, MYNUM * multiplier);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;task main() {&lt;br /&gt;  int x = 0;&lt;br /&gt;  x = 1;&lt;br /&gt;  runout(LCD_LINE1, x);&lt;br /&gt;  x = 2;&lt;br /&gt;  runout(LCD_LINE2, x);&lt;br /&gt;  Wait(10000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which produces&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HdYrIZK4E04/Rk0m9RXU9YI/AAAAAAAAAAM/UASmL_4MNgg/s1600-h/NXTNumOut.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer;" src="http://1.bp.blogspot.com/_HdYrIZK4E04/Rk0m9RXU9YI/AAAAAAAAAAM/UASmL_4MNgg/s320/NXTNumOut.jpg" alt="" id="BLOGGER_PHOTO_ID_5065747989936797058" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I may pretty it up more when I understand parenscript more, but it compiles and runs and it isn't meant to be read by humans.&lt;br /&gt;&lt;br /&gt;The next "architectual/philosophical" decision is how closely to follow the original RCXLisp syntax. That would give me some access to more example programs, but the NXT has more capabilities than the RCX, and there's a Google Summer of Code project "NXTLISP" working on a (I'm assuming) a Lisp-&gt;NXT VM compiler, so I may wait to see the syntax for that.&lt;br /&gt;&lt;br /&gt;Or not. NXC has a rich set of C-style macros for things like turning on multiple sets of motors that's different than how RCXLisp does it, plus I'm thinking about keeping the language more generic so it can target multiple robot C compilers, such as the First VEX.&lt;br /&gt;&lt;br /&gt;I'll post more as I go - the next thing to ponder is the best way to handle typing of NXC variables; int, short, long, byte, bool and string. Other robot C compilers may have other types. I may try Common Lisp type declares, or I may put the types in a list with the variable name, with just the variable name meaning "int".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-285187211121865200?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/285187211121865200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=285187211121865200' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/285187211121865200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/285187211121865200'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2007/05/redefining-it.html' title='Redefining it'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HdYrIZK4E04/Rk0m9RXU9YI/AAAAAAAAAAM/UASmL_4MNgg/s72-c/NXTNumOut.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-1463097554408141399</id><published>2007-02-06T09:52:00.000-08:00</published><updated>2007-02-06T10:03:56.554-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><title type='text'>Latest 'Crossing Borders' is about Lisp</title><content type='html'>At &lt;a href="http://www-128.ibm.com/developerworks/java"&gt;IBM's Java page&lt;/a&gt;, Bruce Tate writes articles about other languages and the features that they have that other languages don't. His latest is on Lisp. The usual intro stuff, but he could have spent a &lt;span style="font-style: italic;"&gt;little&lt;/span&gt; more time on macros; his example is&lt;br /&gt;(defmacro times_two (x) (* 2 x))&lt;br /&gt;With not much more he could have shown an actual language extension. Hey Bruce, would a 'while' have killed you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-1463097554408141399?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/1463097554408141399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=1463097554408141399' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/1463097554408141399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/1463097554408141399'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2007/02/latest-crossing-borders-is-about-lisp.html' title='Latest &apos;Crossing Borders&apos; is about Lisp'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-116318618393342752</id><published>2006-11-10T10:53:00.000-08:00</published><updated>2006-11-10T11:16:23.973-08:00</updated><title type='text'>Practical Ocaml - And I had such high hopes</title><content type='html'>If you go &lt;a href="http://i-need-closures.blogspot.com/2005/05/what-brought-me-to-lisp.html"&gt;back&lt;/a&gt; to my first posting, you'll see that before Common Lisp the language I used for home programming was OCaml. I still prefer Lisp's uniform syntax and macros, but Ocaml has a soft spot in my heart.&lt;br /&gt;&lt;br /&gt;That's why I was looking forward to Apress' "Practical OCaml", which was going to be OCaml's answer to "Pratical Common Lisp", even doing some of the same projects - good for comparison. &lt;br /&gt;&lt;br /&gt;Well, reviews are coming in, and the short version is, except for the prose and the code, the book's just fine. For the sarcasm impaired, &lt;a href="http://www.amazon.com/Practical-OCaml-Joshua-B-Smith/dp/159059620X"&gt;the amazon reviews&lt;/a&gt; are all one star, and even the book's technical reviewer &lt;a href="http://blog.merjis.com/2006/11/08/practical-ocaml/"&gt;is not thrilled with it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Some reviewers are even concerned that this will discourage others from writing a good OCaml book or learning OCaml. Thank you, Peter, for doing such a good job on "Pracital Common Lisp".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-116318618393342752?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/116318618393342752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=116318618393342752' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/116318618393342752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/116318618393342752'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/11/practical-ocaml-and-i-had-such-high.html' title='Practical Ocaml - And I had such high hopes'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-115859177138231321</id><published>2006-09-18T07:58:00.000-07:00</published><updated>2006-09-18T08:02:51.423-07:00</updated><title type='text'>Parenscript out on its own</title><content type='html'>I see that &lt;a href="http://parenscript.org/"&gt;Parenscript&lt;/a&gt; has a home of its own. I'm glad it's out on its own - in the past I've tried to grab just what I needed out of UCW, or use KlammerScript, but the docs never quite matched the code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-115859177138231321?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/115859177138231321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=115859177138231321' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/115859177138231321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/115859177138231321'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/09/parenscript-out-on-its-own.html' title='Parenscript out on its own'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-114921416821867063</id><published>2006-06-01T18:59:00.000-07:00</published><updated>2006-06-01T19:10:19.250-07:00</updated><title type='text'>Stealing it back</title><content type='html'>At &lt;a href="http://www.artima.com"&gt;Artima&lt;/a&gt;, Topher Cyll wrote an article called &lt;a href="http://www.artima.com/rubycs/articles/patterns_sexp_dslsP.html"&gt;If It's Not Nailed Down, Steal It&lt;/a&gt; where he implements pattern matching, S-expressions and destructuring in Ruby, then uses this to implement a modified Logo interpreter (it uses "(" and ")" instead of "[" and "]"). The Logo interpreter outputs SVG files for rendering. &lt;br /&gt;&lt;br /&gt;The interpreter interested me, and hey, Lisp already has the stuff he's stealing, so I thought I'd have a go at implementing the interpreter. I wanted to stick to "vanilla Common Lisp" as much as possible, in other words not pull in big pattern matching libraries, just stick to CLOS multiple dispatch. &lt;br /&gt;&lt;br /&gt;Most of the "stealing back" is pretty straightforward, except for the "run" methods. It looks like the Ruby code can distinguish methods by variable arguments, where Lisp methods implementing a generic function must all have the same argument signature, even if the last argument is a &amp;rest. Fortunately, the Ruby methods just distinguish by the command argument, and the rest is destructuring, so once we're in the dispatched run method we can destructure afterwards.&lt;br /&gt;&lt;br /&gt;The next bump was chopping off the "command" argument from the remainder of the S-expression to call the next run, which left a single argument for the &amp;rest, the argument being a list of the remaining arguments, so that had to be car'ed, and you had to remember to do it everywhere, etc. It's messy. &lt;br /&gt;&lt;br /&gt;"apply" to the rescue. From the CLHS, "apply" uses a "spreadable argument list designator", which means it will turn (1 2 (3 4 5)) into (1 2 3 4 5) when it gets back to dispatching on the method. So&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(apply #'run lg '(right 90 forward 10))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;turns into&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(run lg right 90 forward 10)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;which will match on&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defmethod run ((lg logo) (command (eql 'right)) &amp;rest args)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and "args" will have (90 forward 10) in it, ready for destructuring.&lt;br /&gt;&lt;br /&gt;One feature of the Ruby version that I can't figure out how to duplicate is dispatching on nil, in other words when we're at the end of the program S-expression. It looks like the methods can catch it, but calling "run" or "apply #'run" won't throw it. What I came up with was inserting a special "stop" token at the end of the programs and stopping on it, or checking at the end of each method for an empty remainder before calling run again. I opted for the empty check. If there's a better solution I'd appreciate a comment to let me know.&lt;br /&gt;&lt;br /&gt;This gives me methods such as&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(defmethod run ((lg logo) (command (eql 'forward)) &amp;rest args)&lt;br /&gt;  (destructuring-bind (distance &amp;rest rest-args) args&lt;br /&gt;    (move lg distance)&lt;br /&gt;    (when rest-args (apply #'run lg rest-args))))&lt;br /&gt;&lt;br /&gt;(defmethod run ((lg logo) (command (eql 'pendown)) &amp;rest args)&lt;br /&gt;  (setf (pen lg) t)&lt;br /&gt;  (when args (apply #'run lg args)))&lt;br /&gt;&lt;br /&gt;(defmethod run ((lg logo) (command (eql 'repeat)) &amp;rest args)&lt;br /&gt;  (destructuring-bind (repeat-count code &amp;rest rest-args) args&lt;br /&gt;    (dotimes (i repeat-count) (apply #'run lg code))&lt;br /&gt;    (when rest-args (apply #'run lg rest-args))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This works, but looking at the code you can see a lot of boilerplate code. Like any Lisper, to me this code smelled like it needed a macro to make an internal DSL to help out with the external DSL. So with&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(defmacro defrun ((logo-var command-symbol vars) &amp;body body)&lt;br /&gt;  (let ((args (gensym))&lt;br /&gt;        (rest-args (gensym)))&lt;br /&gt;    `(defmethod run ((,logo-var logo) (command (eql ',command-symbol)) &amp;rest ,args)&lt;br /&gt;       (destructuring-bind (,@vars &amp;rest ,rest-args) ,args&lt;br /&gt;         ,@body&lt;br /&gt;       (when ,rest-args (apply #'run ,logo-var ,rest-args))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;the above methods turn into&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(defrun (lg forward (distance)) (move lg distance))&lt;br /&gt;(defrun (lg pendown ()) (setf (pen lg) t))&lt;br /&gt;(defrun (lg repeat (repeat-count code)) (dotimes (i repeat-count) (apply #'run lg code)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;which is closer to the Ruby DSL.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blubparadox.googlepages.com/logo-steal-when.lisp"&gt;logo-steal-when.lisp&lt;/a&gt; has the pre-macro version, and &lt;a href="http://blubparadox.googlepages.com/logo-steal-macro.lisp"&gt;logo-steal-macro.lisp&lt;/a&gt; has the defrun'ned version. Happy stealing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-114921416821867063?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/114921416821867063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=114921416821867063' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114921416821867063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114921416821867063'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/06/stealing-it-back.html' title='Stealing it back'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-114780212218206213</id><published>2006-05-16T10:51:00.000-07:00</published><updated>2006-05-16T10:55:22.200-07:00</updated><title type='text'>Am I supposed to like Smalltalk?</title><content type='html'>When people talk in general about "high level, extensible, dynamic" languages on their blogs, they usually mention Smalltalk and Lisp in the same breath. Smalltalk programmers talk about their language in the same glowing terms as Lisp programmers; this prompts me to read about Smalltalk, and this weekend I tried out Squeak.&lt;br /&gt;&lt;br /&gt;I think I'll stay with Lisp. I'm sure someone will say I didn't try it long enough, but there were a couple of issues I don't think will go away with extended use. &lt;br /&gt;&lt;br /&gt;First of all is the environment/IDE. With Lisp/Emacs/Slime, or for that matter Java/Netbeans, to write method after method, you can just type. What I saw in Squeak was a bad combination of mousing and typing. You have to click in the '--all--' window of methods, then mouse down to the editing pane, and replace text, then save, then do it again for the next method. I'm sure this is a YMMV thing, but these mini-interruptions sure wouldn't keep me in 'flow' as much as just typing.&lt;br /&gt;&lt;br /&gt;Second is the 'OOP all the way' flavor of the Smalltalk language. Sometimes a function is just a function, and doesn't need to be in a class. I prefer the options that Lisp provides, I use imperative, OO, and functional, depending on the problem.&lt;br /&gt;&lt;br /&gt;All this is without bringing up macros, which I don't use that much now, but will do so more in the future, which will only widen the gap.&lt;br /&gt;&lt;br /&gt;Have you tried Smalltalk, and why do you prefer Lisp?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-114780212218206213?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/114780212218206213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=114780212218206213' title='23 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114780212218206213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114780212218206213'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/05/am-i-supposed-to-like-smalltalk.html' title='Am I supposed to like Smalltalk?'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-114541697473009601</id><published>2006-04-18T20:20:00.000-07:00</published><updated>2006-04-18T20:22:54.743-07:00</updated><title type='text'>Herds of Lispers?</title><content type='html'>Ever VNC into a computer that has a VNC window open to the computer that you're on? That's how I feel when I link to a blog that's linked to mine.&lt;br /&gt;&lt;br /&gt;About twice a week I &lt;a href="http://www.technorati.com/search/lisp"&gt;search for 'lisp' on technorati&lt;/a&gt;, and it's still a little surprise for me when &lt;a href="http://www.bobcongdon.net/blog/2006/04/java-and-lisp.html"&gt;I see someone else writing about one of my articles&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Bob Congdon's entry is mainly a discussion about &lt;a href="http://i-need-closures.blogspot.com/2005/11/or.html"&gt;my entry about Java vs. Lisp language expansion&lt;/a&gt;, but at the end he talks about the likely number of Lisp programmers on one project - he himself worked on a project with five. I can't imagine much more than that, both because you wouldn't need that many and we seem to be so few and far between I'm not sure how you'd get that many together. &lt;br /&gt;&lt;br /&gt;What's the biggest number of Lisp programmers you've seen on a project?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-114541697473009601?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/114541697473009601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=114541697473009601' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114541697473009601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114541697473009601'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/04/herds-of-lispers.html' title='Herds of Lispers?'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-114122284237070350</id><published>2006-03-01T05:45:00.000-08:00</published><updated>2006-03-01T06:20:42.453-08:00</updated><title type='text'>Let's scream</title><content type='html'>I'd read about Screamer so by the time I'd heard of Sudoku I thought that this was something that just "screamed" for Screamer. Plus, when you tell your friends that you're working on a Lisp/AJAX RSS reader as a kind of laboratory for exploring ideas about natural language processing, you get a blank look. Tell them you're writing a Sudoku solver and they understand that.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cliki.net"&gt;Screamer&lt;/a&gt; has two parts. The first part is backtracking/search. You can write your program somewhat normally, but where your searching ends you put a "fail" call. Where your code doesn't "fail" is where your answers get collected. &lt;a href="http://briankuhn.com/?p=41"&gt;Brian Kuhn&lt;/a&gt; posted an "interview question" where you have a sequence of numbers, positive and negative, and you return the subsequence that would give the highest total. He had 100 lines of Java; with Screamer's help I had&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(screamer:define-screamer-package :maxsub &lt;br /&gt;  (:export :findmaxsub))&lt;br /&gt;&lt;br /&gt;(in-package :maxsub)&lt;br /&gt;&lt;br /&gt;(defun findmaxsub (numbers)&lt;br /&gt;  (let ((total -99999))&lt;br /&gt;    (car &lt;br /&gt;     (nreverse  &lt;br /&gt;      (all-values &lt;br /&gt; (let ((begin (an-integer-between 0 (1- (length numbers))))&lt;br /&gt;       (end (an-integer-between 1 (length numbers))))&lt;br /&gt;   (when (&gt;= begin end) (fail))&lt;br /&gt;   (let ((subtotal (apply #'+ (subseq numbers begin end))))&lt;br /&gt;     (if (&gt; total subtotal)&lt;br /&gt;  (fail)&lt;br /&gt;  (setf total subtotal)))&lt;br /&gt;   (subseq numbers begin end)))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Every time the subtotal is higher than the previous total there's a "success", and the sublist is collected by the "all-values" call. When it's done, the highest of them all is at the end of that list.&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;The other part is the "constraints" part, where you list the constraints on your variables, wind up Screamer, and let it go. The main problem I found with Screamer is that it doesn't handle arrays well, it does lists better, and individual variables best of all. This turned Sudoku into an exercise in typing. I had to list out 81 variables - mostly are "something between 1 and 9", some are the starting numbers - and 27 constraints, 9 row, 9 column and 9 box. &lt;br /&gt;&lt;p/&gt;&lt;br /&gt;You can see the code &lt;a href="http://blubparadox.googlepages.com/sudoku-screamer.lisp"&gt;here&lt;/a&gt;. If you have a Gmail account, you should get your Google page to host files if you don't want your own domain.&lt;br /&gt;&lt;br /&gt;I've also wanted to learn LTK, so I wrote a separate LTK front-end for Sudoku. It uses LTK as well as the LTK "mega-widgets" in ltk-mw.lisp. Inside it uses a Sudoku solver that takes a 2D array as input, 0's for blanks, and returns a 2D array. Code is &lt;a href="http://blubparadox.googlepages.com/sudoku-ltk.lisp"&gt;here&lt;/a&gt;. If you want to try this out as is you'll need to get Screamer loaded.&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;&lt;img src="http://static.flickr.com/43/106103197_6f748e41d4.jpg?v=0"/&gt;&lt;br /&gt;&lt;p/&gt;&lt;br /&gt;Something funny in the license for Screamer. Part of the conditions of its use is you have to send an e-mail telling them what version of Common Lisp you're using it with, so they can list it. I'll be adding OpenMCL 1.0 under Mac OSX and SBCL 0.9.0 under Linux. If you try this out then let them know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-114122284237070350?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/114122284237070350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=114122284237070350' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114122284237070350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/114122284237070350'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/03/lets-scream.html' title='Let&apos;s scream'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113924417566662530</id><published>2006-02-06T08:32:00.000-08:00</published><updated>2006-02-06T08:42:56.506-08:00</updated><title type='text'>Franz bustin' out all over</title><content type='html'>In my latest Dr. Dobb's Journal, Franz had a two-page ad talking about what's possible and fast with AllegroCache.&lt;br /&gt;&lt;br /&gt;Peter Coffee's latest column at eWeek, &lt;a href="http://www.eweek.com/article2/0,1759,1917191,00.asp?kc=EWRSS03119TX1K0000594"&gt;'Exotic' Programming Tools Go Mainstream&lt;/a&gt;, has this to say:&lt;br/&gt;&lt;br /&gt;&lt;code&gt;Allegro CL has had two major updates since the last time eWEEK Labs reviewed it. The 8.0 version reflects performance-enhancing improvements so startling that if it played baseball, we'd expect a congressional probe.&lt;/code&gt;&lt;br/&gt;&lt;br /&gt;Can't wait to get my hands on the upcoming Express Edition. I knew Lisp was what I wanted to learn so I was willing to get over the Emacs/Slime curve, but I understand people who'd want to explore with an IDE to see if Lisp is for them, and it would be good to be able to recommend a hassle-free Windows IDE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113924417566662530?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113924417566662530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113924417566662530' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113924417566662530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113924417566662530'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/02/franz-bustin-out-all-over.html' title='Franz bustin&apos; out all over'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113752590229695668</id><published>2006-01-17T11:19:00.000-08:00</published><updated>2006-01-17T11:25:02.313-08:00</updated><title type='text'>Ever closer to Greenspun's Tenth</title><content type='html'>Anyone who's glanced at &lt;a href="http://www.cliki.net/Lisp%20Markup%20Languages"&gt;LML's&lt;/a&gt; should find &lt;a href="http://redhanded.hobix.com/inspect/markabyForRails.html"&gt;Markup for Ruby&lt;/a&gt; familiar:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; html do&lt;br /&gt;   head do&lt;br /&gt;     title action_name&lt;br /&gt;     stylesheet_link_tag 'scaffold'&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   body do&lt;br /&gt;     p flash[:notice], :style =&gt; "color: green" &lt;br /&gt;     self &lt;&lt; @content_for_layout&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113752590229695668?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113752590229695668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113752590229695668' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113752590229695668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113752590229695668'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/01/ever-closer-to-greenspuns-tenth.html' title='Ever closer to Greenspun&apos;s Tenth'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113716592169196111</id><published>2006-01-13T07:00:00.000-08:00</published><updated>2006-01-13T07:25:21.763-08:00</updated><title type='text'>Fits like a glove</title><content type='html'>I've had a dry spell of coding at home, between the holidays and reading "Ajax in Action", but reading some of the long postings at Planet Lisp should be enough to guilt any slacker back into action.&lt;br /&gt;&lt;br /&gt;This has uncovered yet another advantage of Common Lisp, at least for me; how short a time it takes to get back up to speed with the language after being away from it. It takes me considerably less time to get back "in the groove" than with other languages, with less references to language manuals. I don't know how this is for others, but Lisp fits my brain.&lt;br /&gt;&lt;br /&gt;I think this is because of the lack of syntax. Instead of having to remember operator precedence, the operators themselves, strings of characters that look like Yosemite Sam swearing, it's just almost-English words and parentheses. The language is built on just a few core concepts that can be mixed and matched, instead of a bunch of rigid rules and details that have to be remembered.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113716592169196111?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113716592169196111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113716592169196111' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113716592169196111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113716592169196111'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2006/01/fits-like-glove.html' title='Fits like a glove'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113496156540870126</id><published>2005-12-18T19:03:00.000-08:00</published><updated>2005-12-18T19:06:05.426-08:00</updated><title type='text'>New Year's Resolution</title><content type='html'>Regular backups.&lt;br/&gt;Also, thank Apple for putting 'terminal' on the install disk.&lt;br/&gt;Thank you. That is all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113496156540870126?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113496156540870126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113496156540870126' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113496156540870126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113496156540870126'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/12/new-years-resolution.html' title='New Year&apos;s Resolution'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113406387178605540</id><published>2005-12-08T09:31:00.000-08:00</published><updated>2005-12-08T09:44:31.826-08:00</updated><title type='text'>Portable Allegroserve as a de facto standard?</title><content type='html'>The "Ruby as an acceptable Lisp" and Reddit discussions (I don't really need to supply links, do I?) brought back to the surface a question I ask myself often.&lt;br /&gt;&lt;br /&gt;It's true that Common Lisp doesn't have multithreading or network clients in the standard, and people want that, but what's wrong with Portable Allegroserve? The acl-compat component has those covered (if the underlying implementation has support) for Allegro, LispWorks, CMUCL, SBCL, OpenMCL, SCL, Corman, CLisp. It appears to be used a lot, and has decent documentation. &lt;br /&gt;&lt;br /&gt;Why not just use that and move on to the next problem? Is there something horrible about Portable Allegroserve I should know about?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113406387178605540?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113406387178605540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113406387178605540' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113406387178605540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113406387178605540'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/12/portable-allegroserve-as-de-facto.html' title='Portable Allegroserve as a de facto standard?'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113288610781746822</id><published>2005-11-24T18:22:00.000-08:00</published><updated>2005-11-24T18:35:07.843-08:00</updated><title type='text'>Or....</title><content type='html'>I received an email from JavaLobby, which had in it this &lt;a href="http://www.eclipsezone.com/eclipse/forums/t54318.html"&gt;article&lt;/a&gt; at EclipseZone, which talks about the plusses and minuses of adding features to Java. From the article:&lt;br/&gt;&lt;br /&gt;&lt;code&gt;Language guys love to tweak. I know, because I'm a language guy myself. I used to work on compilers, code generators, libraries, and debuggers. We were always adding new stuff, new commands, special keywords, etc. Did our users thank us for it? Maybe the one or two that wanted the new things, but the vast majority would just groan when a new release came out. What will this break now? Will I have to upgrade? Will I have to use somebody else's code that requires this new thing before I'm ready? Has it been ported to all the machines I need to run on? Boring, I know, but very practical and important issues. &lt;/code&gt;&lt;br/&gt;&lt;br /&gt;Or... you can work in a language where if you want the one or two new things, you can just add them, and let the other guy that wants one or two other things added to the language add what he wants.&lt;br/&gt;&lt;br /&gt;Or... I could just let Peter Siebel &lt;a href="http://www.gigamonkeys.com/book/macros-standard-control-constructs.html"&gt;say it better&lt;/a&gt;:&lt;br/&gt;&lt;br /&gt;&lt;code&gt;DOLIST is similar to Perl's foreach or Python's for. Java added a similar kind of loop construct with the "enhanced" for loop in Java 1.5, as part of JSR-201. Notice what a difference macros make. A Lisp programmer who notices a common pattern in their code can write a macro to give themselves a source-level abstraction of that pattern. A Java programmer who notices the same pattern has to convince Sun that this particular abstraction is worth adding to the language. Then Sun has to publish a JSR and convene an industry-wide "expert group" to hash everything out. That process--according to Sun--takes an average of 18 months. After that, the compiler writers all have to go upgrade their compilers to support the new feature. And even once the Java programmer's favorite compiler supports the new version of Java, they probably still can't use the new feature until they're allowed to break source compatibility with older versions of Java. So an annoyance that Common Lisp programmers can resolve for themselves within five minutes plagues Java programmers for years.&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113288610781746822?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113288610781746822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113288610781746822' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113288610781746822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113288610781746822'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/11/or.html' title='Or....'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113268638865281755</id><published>2005-11-22T11:00:00.000-08:00</published><updated>2005-11-22T11:11:18.156-08:00</updated><title type='text'>Lisp with a different syntax</title><content type='html'>I've been reading &lt;a href="http://www.amazon.com/gp/product/1932394613/104-8365138-3104767?v=glance&amp;n=283155&amp;n=507846&amp;s=books&amp;v=glance"&gt;Ajax in Action&lt;/a&gt;, and have been reminded of the quote "Javascript is Lisp with a different syntax". It's usually used to stress the &lt;a href="http://blog.codingforums.com/index.php/main/blogentry/pure_functional_programming_in_javascript/"&gt;functional&lt;/a&gt; and closure features of Javascript, but there's another part that's also very close - attaching arbritrary properties to an object, including functions.&lt;br/&gt;&lt;br /&gt;Compare&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;var x = new Object()&lt;br /&gt;&gt;x.one = 1&lt;br /&gt;1&lt;br /&gt;&gt;x.two = 2&lt;br /&gt;2&lt;br /&gt;&gt;x.doubler = function(n) { return n * 2; }&lt;br /&gt;function (n) { return n * 2; }&lt;br /&gt;&gt;x.two&lt;br /&gt;2&lt;br /&gt;&gt;x.doubler(3)&lt;br /&gt;6&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;with&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;CL-USER&gt; (setf (get 'x 'one) 1)&lt;br /&gt;1&lt;br /&gt;CL-USER&gt; (setf (get 'x 'two) 2)&lt;br /&gt;2&lt;br /&gt;CL-USER&gt; (setf (get 'x 'doubler) #'(lambda (x) (* x 2)))&lt;br /&gt;#&amp;lt;CLOSURE :LAMBDA (X) (* X 2)&amp;gt;&lt;br /&gt;CL-USER&gt; (get 'x 'two)&lt;br /&gt;2&lt;br /&gt;CL-USER&gt; (funcall (get 'x 'doubler) 3)&lt;br /&gt;6&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In old Lisp textbooks I've seen this referred to as "data driven programming", used before anyone was talking about object-oriented programming. Now, no one would do OO this way in Lisp, but the quote didn't say "Javascript is &lt;i&gt;Common&lt;/i&gt; Lisp with a different syntax".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113268638865281755?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113268638865281755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113268638865281755' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113268638865281755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113268638865281755'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/11/lisp-with-different-syntax.html' title='Lisp with a different syntax'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113224607888731372</id><published>2005-11-17T07:44:00.000-08:00</published><updated>2005-11-17T08:47:58.930-08:00</updated><title type='text'>Looking for Lisp/NLP starting points</title><content type='html'>I guess I'm having trouble with the correct incantations into Google. I'm trying to find information on natural language processing, preferably in Lisp but I'll look at anything, specifically towards taking in text and summarizing it.&lt;br /&gt;&lt;br /&gt;I'm thinking of doing an RSS reader where long-winded feeds can be automatically summarized down to "abstract" form, and including a link back to the original article that the user can decide to read or just move on to the next article.&lt;br /&gt;&lt;br /&gt;Any suggestions for starting points would be appreciated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113224607888731372?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113224607888731372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113224607888731372' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113224607888731372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113224607888731372'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/11/looking-for-lispnlp-starting-points.html' title='Looking for Lisp/NLP starting points'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113125030389344041</id><published>2005-11-05T20:11:00.000-08:00</published><updated>2005-11-05T20:37:32.570-08:00</updated><title type='text'>A Cocoa-Lisp-Google Maps Mashup</title><content type='html'>&lt;img src="http://static.flickr.com/27/60264697_3e0bdadad8.jpg?v=0" /&gt;&lt;br&gt;&lt;br /&gt;Just your run-of-the-mill Google Maps page, except for a couple of things; the server part is in Portable AllegroServe (no big deal), and the addresses came out of my Mac's Address Book via OpenMCL (a bigger deal).&lt;br /&gt;I got interested in this after hearing an O'Reilly "Distributing the Future" podcast where someone mentioned that not everyone will want all their information on the web and there will be applications where part of the data is on the web and part is kept in the user's local storage.&lt;br /&gt;The basic understanding of the Mac's AddressBook library came from &lt;a href="http://www.macdevcenter.com/pub/a/mac/2002/08/27/cocoa.html?page=1"&gt;this Mac Dev Center article&lt;/a&gt;, and help from Gary Byers got OpenMCL loading and searching the Address Book in OpenMCL. The rest is basic Portable AllegroServe. &lt;br /&gt;The geocoder I'm using is &lt;a href="http://www.ontok.com/geocode/restapi"&gt;Ontok&lt;/a&gt;, which has a REST api that takes up to 10 addresses at one time and returns CSVs that start with latitute and longitude co-ordinates. &lt;br /&gt;&lt;a href="http://wilshipley.com/blog/2005/05/whats-coolest-thing-in-tiger.html"&gt;Wil Shipley mentions&lt;/a&gt; that instead of using a database for storing customer orders he keeps them in XML files and uses Spotlight for searching. Something similar could be done with Address Book, just keep addresses in the built-in library instead of a database.&lt;br /&gt;Code is &lt;a href="http://paste.lisp.org/display/13249"&gt;here&lt;/a&gt; if you'd like to see.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113125030389344041?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113125030389344041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113125030389344041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113125030389344041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113125030389344041'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/11/cocoa-lisp-google-maps-mashup.html' title='A Cocoa-Lisp-Google Maps Mashup'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-113026118577492775</id><published>2005-10-25T10:17:00.000-07:00</published><updated>2005-10-25T10:26:25.790-07:00</updated><title type='text'>Joel is influential, we must assimilate him</title><content type='html'>&lt;a href="http://bc.tech.coop/blog/051024.html"&gt;Bill&lt;/a&gt; pointed out Joel Spolsky saying &lt;br/&gt;&lt;i&gt;"I had to install Lisp in a Box and start working through Seibel's new book on Common Lisp until my brain started functioning again."&lt;/i&gt;&lt;br/&gt;What I find interesting is that the number of links to Lisp In A Box on &lt;a href="http://del.icio.us/tag/lisp"&gt;Delicious' lisp tag&lt;/a&gt; has really shot up the past couple of days. Expect a newbie mini-flood on c.l.l.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-113026118577492775?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/113026118577492775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=113026118577492775' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113026118577492775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/113026118577492775'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/10/joel-is-influential-we-must-assimilate.html' title='Joel is influential, we must assimilate him'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112896191277454912</id><published>2005-10-10T05:00:00.000-07:00</published><updated>2010-06-07T10:28:47.450-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>Common Lisp and/or Scheme, and Y I should bother</title><content type='html'>First things first. If there's a Y pun, then you know I must be talking about the Y combinator. Understanding it is on the computer science part of the ol' "Things to do before I die" list. To that end, I got and read "The Little Schemer", and had the same reaction I usually get when reading about the Y combinator, or continuations (another on my "to understand" list). It starts out very simple (cons, car cdr), adds a baby step, another baby step, etc. then they're off on this bizarro explanation that makes no sense to me. Instead of steps A, B, C, D, E, F it's more like A, B, C, W, X, Y; there were some important steps in between that I somehow missed. Is this something I need to eventually conquer to achieve enlightenment, or are they happy, productive Lispers out there who don't understand this?&lt;br /&gt;&lt;br /&gt;A related question is Common Lisp and Scheme, specifically PLT Scheme. I've looked at both and prefer Common Lisp to get work done, using emacs and SLIME. Every now and then I look at PLT Scheme, mainly out of IDE envy, and it looks nice. Bill Clementson says it's &lt;a href="http://bc.tech.coop/blog/040111.html"&gt;the best Open Source Lisp&lt;/a&gt;. Common Lisp vs. PLT Scheme reminds me of the "even though Python is a better language, Java + IDE combos make you more productive" blog entries I see. &lt;br /&gt;&lt;br /&gt;Everyone says the best tool for the job, but for Lisp users I'm thinking that's usually either Common Lisp or Scheme, and other non-Lisp languages. Do Lisp users just stick with one dialect of Lisp, or are there people that use Common Lisp and Scheme for different tasks?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112896191277454912?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112896191277454912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112896191277454912' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112896191277454912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112896191277454912'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/10/common-lisp-andor-scheme-and-y-i.html' title='Common Lisp and/or Scheme, and Y I should bother'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112683711824876055</id><published>2005-09-15T18:51:00.000-07:00</published><updated>2005-09-15T19:18:38.300-07:00</updated><title type='text'>An analogy - Lisp as Graffiti</title><content type='html'>The Palm kind, that is.&lt;br /&gt;&lt;br /&gt;Whining about Lisp's syntax is a favorite sport on the blogs, especially among students that have a Lisp assignment in a class. I look at it the same way Jeff Hawkins looked at Grafitti when developing the Palm (from &lt;a href="http://www.fastcompany.com/magazine/15/smallthing.html"&gt;a Fast Company article&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"People are smarter than appliances," Hawkins told his colleagues. "They can learn.'' He recalled a lesson from his Berkeley days: "People like learning. People can learn to work with tools. Computers are tools. People like to learn how to use things that work."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;It's good to make things easy for the user, but there comes a point where if the user can compromise a little in one area they can gain a lot in others. For the original Palm, learning Graffiti meant the PDA could fit in your pocket, be cheap and run on two  AAA's since the software could be simplified enough to fit in the restrictions of the machine. For Lisp, making a small change, going to prefix notation and "all those parentheses" gains you code as data as code, macros that match the syntax of the language, and everything else you've been reading about.&lt;br /&gt;&lt;br /&gt;If you're a whiny student who doesn't want to believe me, try believing &lt;a href="http://en.wikipedia.org/wiki/Robert_Floyd"&gt;Robert Floyd&lt;/a&gt;, from his Turing Prize lecture (from &lt;a href="http://mago.blogsome.com/2005/08/11/lenguajes-de-programacion-y-su-sintaxis/"&gt;here&lt;/a&gt; via &lt;a href="http://justavo.blogsome.com/2005/08/11/sobre-lisp/"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;i&gt;“Contact with the programming written under alien conventions may help. Visiting MIT on sabbatical this year, I have seen numerous examples of the programming power which Lisp programmers obtain from having a single data structure, which is also used as a uniform syntactic structure for all the functions and operations which appear in programs, with the capability to manipulate programs as data. Although my own previous enthusiasm has been for syntactically rich languages like the Algol family, I see now clearly and concretely the force of Minsky’s 1970 Turing Lecture, in which he argued that Lisp’s uniformity of structure and power of self-reference gave the programmer capabilities whose content was well worth the sacrifice of visual form.”&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112683711824876055?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112683711824876055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112683711824876055' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112683711824876055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112683711824876055'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/09/analogy-lisp-as-graffiti.html' title='An analogy - Lisp as Graffiti'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112588036970157580</id><published>2005-09-04T17:18:00.000-07:00</published><updated>2005-09-04T17:32:49.706-07:00</updated><title type='text'>Fuzzy Queries on top of CLSQL</title><content type='html'>I originally planned to incorporate Fuzzy SQL more into CLSQL, but I don't think it's necessary for my purposes. With CLSQL's def-view-class extension of CLOS I can use generic methods, and it will look like the rest of the class. Later in the book I'm using, &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0121942759/qid=1122690167/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/102-4566640-7454518?v=glance&amp;s=books&amp;amp;n=507846"&gt;Fuzzy Modeling and Genetic Algorithms for Data Mining and Exploration&lt;/a&gt; there's a chapter on Genetic Tuning of Fuzzy Models, which I think will work better with external functions and methods as opposed to MOP or macro-based solutions inside CLSQL. Besides, I couldn't even get db-reader to work with my classes, so I'll just leave well enough alone.&lt;br /&gt;&lt;br /&gt;This will be based on my previous &lt;a href="http://i-need-closures.blogspot.com/2005/07/fuzzy-logic-and-fuzzy-sql-or-richards.html"&gt;big and tall entry&lt;/a&gt;. My data setup is&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;rrc=# select * from btprospects;&lt;br /&gt;   name   | height | weight | age &lt;br /&gt;----------+--------+--------+-----&lt;br /&gt; Saunders |     74 |    215 |  52&lt;br /&gt; Cassey   |     73 |    188 |  40&lt;br /&gt; Miller   |     71 |    157 |  25&lt;br /&gt; Freeman  |     70 |    202 |  34&lt;br /&gt; OMalley  |     65 |    163 |  48&lt;br /&gt; Jackson  |     63 |    170 |  38&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;and I have a corresponding CLSQL view-class&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;(clsql:def-view-class btprospects ()&lt;br /&gt;  ((name :db-kind :key&lt;br /&gt;         :type (string 20)&lt;br /&gt;         :initarg :name&lt;br /&gt;         :accessor name)&lt;br /&gt;   (height :type integer&lt;br /&gt;           :initarg :height&lt;br /&gt;           :accessor height)&lt;br /&gt;   (weight :type integer&lt;br /&gt;           :initarg :weight&lt;br /&gt;           :accessor weight)&lt;br /&gt;   (age :type integer&lt;br /&gt;        :initarg :age&lt;br /&gt;        :accessor age)))&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The key is each class will have a &lt;b&gt;qcix&lt;/b&gt; (query compatibility index) method that will be the overall membership function, doing some combination of individual membership functions of individual columns in the database. For our "big and tall" prospects we'll have a &lt;b&gt;tall&lt;/b&gt; method for membership based on height, and a &lt;b&gt;heavy&lt;/b&gt; method for membership based on weight. These functions will return a value from 0.0 to 1.0, with a linear scale from the 0 cutoff to the 1 cutoff. For overall membership we'll average the two other membership function.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;(defmethod tall ((prospect btprospects))&lt;br /&gt;  (let ((raw-height (slot-value prospect 'height)))&lt;br /&gt;    (cond ((&lt;= raw-height 54) 0.0)&lt;br /&gt;          ((&gt;= raw-height 72) 1.0)&lt;br /&gt;          (t (float (/ (- raw-height 54) (- 72 54)))))))&lt;br /&gt;&lt;br /&gt;(defmethod heavy ((prospect btprospects))&lt;br /&gt;  (let ((raw-weight (slot-value prospect 'weight)))&lt;br /&gt;    (cond ((&lt;= raw-weight 182) 0.0)&lt;br /&gt;          ((&gt;= raw-weight 220) 1.0)&lt;br /&gt;          (t (float (/ (- raw-weight 182) (- 220 182)))))))&lt;br /&gt;&lt;br /&gt;(defmethod qcix ((prospect btprospects))&lt;br /&gt;  (float (/ (+ (tall prospect) (heavy prospect)) 2)))&lt;br /&gt;&lt;br /&gt;CL-USER&gt; (clsql:map-query 'list #'tall [clsql:select 'btprospects])&lt;br /&gt;(1.0 1.0 0.9444444 0.8888889 0.6111111 0.5)&lt;br /&gt;CL-USER&gt; (clsql:map-query 'list #'heavy [clsql:select 'btprospects])&lt;br /&gt;(0.8684211 0.15789473 0.0 0.5263158 0.0 0.0)&lt;br /&gt;CL-USER&gt; (clsql:map-query 'list #'qcix [clsql:select 'btprospects])&lt;br /&gt;(0.93421054 0.57894737 0.4722222 0.7076024 0.30555555 0.25)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So far, so good. Now we want to select only some records that have a qcix over a particular threshold. We can use CLSQL's addition to loop:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;(defun fuzzy-select (class-name cutoff)&lt;br /&gt;  (loop for (rec) being the records in (clsql:select class-name)&lt;br /&gt;    when (&gt; (qcix rec) cutoff) collect rec))&lt;br /&gt;&lt;br /&gt;CL-USER&gt; (fuzzy-select 'btprospects 0.5)&lt;br /&gt;; Warning: database-query-result-set not implemented for database type POSTGRESQL-SOCKET.&lt;br /&gt;; While executing: #&lt;STANDARD-METHOD CLSQL-SYS:DATABASE-QUERY-RESULT-SET (T CLSQL-SYS:DATABASE)&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Oops! Perhaps another reason not to delve into the innards of CLSQL. Plan B:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;(defun fuzzy-select (class-name cutoff)&lt;br /&gt;  (let ((result '()))&lt;br /&gt;    (clsql:do-query ((rec) [clsql:select class-name])&lt;br /&gt;      (when (&gt;= (qcix rec) cutoff)&lt;br /&gt;        (push rec result)))&lt;br /&gt;    result))&lt;br /&gt;&lt;br /&gt;CL-USER&gt; (mapcar #'name (fuzzy-select 'btprospects .5))&lt;br /&gt;("Freeman" "Cassey" "Saunders")&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;So, starting with a CLSQL def-view-class we can externally add generic methods to support fuzzy queries.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112588036970157580?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112588036970157580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112588036970157580' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112588036970157580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112588036970157580'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/09/fuzzy-queries-on-top-of-clsql.html' title='Fuzzy Queries on top of CLSQL'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112559176038519258</id><published>2005-09-01T09:15:00.000-07:00</published><updated>2005-09-01T09:22:40.390-07:00</updated><title type='text'>This wasn't even funny the first time (search friendly languages)</title><content type='html'>Occaisionally I want to see what other bloggers are doing with Lisp, so I use &lt;a href="http://www.technorati.com/search/lisp"&gt;Technorati to search on Lisp&lt;/a&gt;. Every time, over the course of months now, I see at least once or twice a search page &lt;i&gt;"Whose idea was it to put an "S" in the word "lisp"? "&lt;/i&gt;. And of course each time they act like they were the first to hear of it. &lt;br /&gt;&lt;br /&gt;Never mind the AI Winter reasons, Lisp, Scheme and Arc need better names for searching purposes. This kind of thing never happens to Ocaml or Nemerle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112559176038519258?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112559176038519258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112559176038519258' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112559176038519258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112559176038519258'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/09/this-wasnt-even-funny-first-time.html' title='This wasn&apos;t even funny the first time (search friendly languages)'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112527843742340634</id><published>2005-08-28T18:17:00.000-07:00</published><updated>2005-08-28T18:20:37.426-07:00</updated><title type='text'>September British LinuxUser reviews LispWorks Personal</title><content type='html'>I had a look at it in the bookstore, didn't buy it. Overall favorable, although they didn't like CAPI built on just Motif, they mentioned it uses Aqua under Mac. Nothing the Planet Lispers don't already know; I just mention it because I think it's interesting that a Common Lisp environment is mentioned in a more "mainstream" computer magazine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112527843742340634?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112527843742340634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112527843742340634' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112527843742340634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112527843742340634'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/08/september-british-linuxuser-reviews.html' title='September British LinuxUser reviews LispWorks Personal'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112467754680838216</id><published>2005-08-21T19:25:00.000-07:00</published><updated>2005-08-21T19:36:53.236-07:00</updated><title type='text'>A Spotlight Lisp plugin in a day, or I never metadata I never liked</title><content type='html'>While planning my approach into CLSQL to add Fuzzy SQL, I found myself wanting to just search for keywords, Spotlight-style. Well, how hard can it be? Not that hard, as it turns out. I basically just want to throw the text of a file to Spotlight and have it index the contents. Even if you have no Objective C or Cocoa experience like me, copying and modifying code is pretty straightforward.&lt;br /&gt;&lt;br /&gt;I started with &lt;a href="http://www.macdevcenter.com/lpt/a/6048"&gt;this article on Creating Spotlight Plugins&lt;/a&gt;. In the info.plist, I substituted his type of "com.apple.stickies.aaa" with "com.lisp.lisp", and "lisp" as the file extension. In the schema.xml, I made a custom metata for lisp files called com_lisp_lisp_data. &lt;br /&gt;&lt;br /&gt;The XCode project makes a file called 'GetMetaDataForFile.c', which gets renamed to 'GetMetaDataForFile.m' since we use Objective C and Cocoa. The meat of this file is a callback function called 'GetMetaDataForFile'. All I do in this function is read the entire file into a NSString and add it to the 'mutable dictionary'.&lt;br /&gt;&lt;br /&gt;Here's the function:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Boolean GetMetadataForFile(&lt;br /&gt;         void* thisInterface, &lt;br /&gt;         CFMutableDictionaryRef attributes, &lt;br /&gt;         CFStringRef contentTypeUTI,&lt;br /&gt;         CFStringRef pathToFile)&lt;br /&gt;{&lt;br /&gt; Boolean success=NO;&lt;br /&gt;    NSAutoreleasePool *pool;&lt;br /&gt; &lt;br /&gt; // Don't assume that there is an autorelease pool &lt;br /&gt; //around the calling of this function.&lt;br /&gt;    pool = [[NSAutoreleasePool alloc] init];&lt;br /&gt; &lt;br /&gt;    /* Pull any available metadata from the file */&lt;br /&gt;&lt;br /&gt; NSString *fileText = [NSString stringWithContentsOfFile:pathToFile];&lt;br /&gt; &lt;br /&gt; [(NSMutableDictionary *)attributes setObject:fileText&lt;br /&gt;  forKey:@"com_lisp_lisp_data"];&lt;br /&gt; &lt;br /&gt; // return YES so that the attributes are imported and&lt;br /&gt; // add more resilient error handling at your own discretion&lt;br /&gt; success=YES;&lt;br /&gt; &lt;br /&gt; //memory management&lt;br /&gt; [pool release];&lt;br /&gt; &lt;br /&gt; return success;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Build this in XCode, then:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;My-Computer:~/LispImporter/build rrc$ sudo cp -r LispImporter.mdimporter /Library/Spotlight&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We start with a small lisp file:&lt;br /&gt;&lt;code&gt;My-Computer:~/LispImporter/build rrc$ cat ~/small.lisp&lt;br /&gt;;; A small lisp file&lt;br /&gt;(format t "This is a small lisp file")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Index this file:&lt;br /&gt;&lt;code&gt;My-Computer:~/LispImporter/build rrc$ mdimport -d1 ~/small.lisp&lt;br /&gt;2005-08-21 20:41:05.624 mdimport[630] Import '/Users/rrc/small.lisp' type 'com.lisp.lisp' using 'file://localhost/Library/Spotlight/LispImporter.mdimporter/'&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;See what Spotlight thinks about this file. Note the 'com_lisp_lisp_data' attribute:&lt;br /&gt;&lt;code&gt;My-Computer:~/LispImporter/build rrc$ mdls ~/small.lisp&lt;br /&gt;/Users/rrc/small.lisp -------------&lt;br /&gt;com_lisp_lisp_data             = ";; A small lisp file (format t "This is a small lisp file") "&lt;br /&gt;kMDItemAttributeChangeDate     = 2005-08-21 20:41:05 -0400&lt;br /&gt;kMDItemContentCreationDate     = 2005-08-21 20:37:33 -0400&lt;br /&gt;kMDItemContentModificationDate = 2005-08-21 20:37:33 -0400&lt;br /&gt;kMDItemContentType             = "com.lisp.lisp"&lt;br /&gt;kMDItemContentTypeTree         = ("com.lisp.lisp", "public.data", "public.item", "public.content")&lt;br /&gt;kMDItemDisplayName             = "small.lisp"&lt;br /&gt;kMDItemFSContentChangeDate     = 2005-08-21 20:37:33 -0400&lt;br /&gt;kMDItemFSCreationDate          = 2005-08-21 20:37:33 -0400&lt;br /&gt;kMDItemFSCreatorCode           = 0&lt;br /&gt;kMDItemFSFinderFlags           = 0&lt;br /&gt;kMDItemFSInvisible             = 0&lt;br /&gt;kMDItemFSLabel                 = 0&lt;br /&gt;kMDItemFSName                  = "small.lisp"&lt;br /&gt;kMDItemFSNodeCount             = 0&lt;br /&gt;kMDItemFSOwnerGroupID          = 501&lt;br /&gt;kMDItemFSOwnerUserID           = 501&lt;br /&gt;kMDItemFSSize                  = 60&lt;br /&gt;kMDItemFSTypeCode              = 0&lt;br /&gt;kMDItemID                      = 1604367&lt;br /&gt;kMDItemKind                    = "Document"&lt;br /&gt;kMDItemLastUsedDate            = 2005-08-21 20:37:33 -0400&lt;br /&gt;kMDItemUsedDates               = (2005-08-21 20:37:33 -0400)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Great! Now tell Spotlight to do all the lisp files:&lt;br /&gt;&lt;code&gt;My-Computer:~/LispImporter/build rrc$ mdimport -r /Library/Spotlight/LispImporter.mdimporter&lt;br /&gt;2005-08-21 20:43:47.750 mdimport[633] Asking server to reimport files with UTIs: ("dyn.ah62d4rv4gk8y2wnxna", "dyn.ah62d4rv4ge8024pxsa", "com.lisp.lisp")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Go away for a while...&lt;br /&gt;Then give it a try.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/50877487@N00/36053439/" title="photo sharing"&gt;&lt;img src="http://photos22.flickr.com/36053439_7e06850c66.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112467754680838216?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112467754680838216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112467754680838216' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112467754680838216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112467754680838216'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/08/spotlight-lisp-plugin-in-day-or-i.html' title='A Spotlight Lisp plugin in a day, or I never metadata I never liked'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112407418145233505</id><published>2005-08-14T19:22:00.000-07:00</published><updated>2005-08-14T19:49:41.476-07:00</updated><title type='text'>Refresh, renew, refill the Kool-Aid</title><content type='html'>My wife and I went on a vacation to the mountains of Highlands, NC. The place had no Internet access, so I thought I'd take along "Hackers and Painters" to reread and get re-inspired. I have drunk the Paul Graham Kool-Aid; I got a Mac to have an easy-to-use Unix to work on Lisps, I suggest his essays to friends, yada yada. &lt;br /&gt;&lt;br /&gt;What Paul probably got real right - page 56, where he starts talking about web apps taking over most of software. This was before Google showing us the AJAX way.&lt;br /&gt;&lt;br /&gt;What Paul may have gotten wrong - page 164, "parallelism will be something that is available if you ask for it explicitly, but ordinarily not used". Lately we've been hearing that we're hitting the limits on a particular core, mulitcore chips are going to be more common and we'll have to write our software for it.&lt;br /&gt;&lt;br /&gt;The big open question I came away with was Paul talking about "Good design comes in chunks". He compares 15th century Florence (mentions 10 famous artists from there and then) vs 15th century Milan (mentions 0). &lt;br /&gt;&lt;br /&gt;"Nothing is more powerful than a community of talented people working on related problems". Can virtual communities serve this purpose today? I can't move to this era's "15th century Florence", even if I could find it. But would I need to? Do I just need to keep up with Planet Lisp or comp.lang.lisp or common-lisp.net? Is is something broader, like Ruby On Rails/Trails/Lisp on Lines communities? It would be pretty damn cool if anyone could just surf to "a community of talented people working on related problems". All we need to do is find it, or define it ourselves.&lt;br /&gt;&lt;br /&gt;P.S. Paul - If you're reading this, RELEASE ARC ALREADY. Thank you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112407418145233505?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112407418145233505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112407418145233505' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112407418145233505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112407418145233505'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/08/refresh-renew-refill-kool-aid.html' title='Refresh, renew, refill the Kool-Aid'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112347049957338797</id><published>2005-08-07T20:08:00.000-07:00</published><updated>2005-08-07T20:26:18.163-07:00</updated><title type='text'>Holy Crap! or, I didn't know you could do that</title><content type='html'>As a lower priority project I've been looking for a "universal UI" for any Lisp projects I may do. I've been restricting it to Web clients backed by Lisp on the server, no unusual installs, etc. I also want to keep it to something that would work with most browsers and OS's today (ruling out Safari's canvas tag, SVG, etc.) but that would allow some graphics, probably charts.&lt;br /&gt;&lt;br /&gt;I was originally thinking of Laszlo, which with version 3.0 you can take your Laszlo client and compile it into Flash. The standalone Flash app can send requests back to the server, get data in the form of XML and use XPath strings to get to the data.&lt;br /&gt;&lt;br /&gt;Then I found &lt;a href="http://www.davidbetz.net/graphics"&gt;this article on JavaScript Graphics&lt;/a&gt;. &lt;br/&gt;&lt;a href="http://www.flickr.com/photos/50877487@N00/32146774/" title="photo sharing"&gt;&lt;img src="http://photos22.flickr.com/32146774_d2dac4f455_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br/&gt;This is just browser, no Flash, Java or plugins. Basically, you can use pure JavaScript, DOM and CSS to make graphcs in browsers. All the tricks work with standards compliant browsers, and some work with IE. I've tried them with Safari and Firefox. &lt;br /&gt;&lt;br /&gt;I was going to go Laszlo, but I won't mind going back to the drawing board for this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112347049957338797?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112347049957338797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112347049957338797' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112347049957338797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112347049957338797'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/08/holy-crap-or-i-didnt-know-you-could-do.html' title='Holy Crap! or, I didn&apos;t know you could do that'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112269524360459131</id><published>2005-07-29T20:44:00.000-07:00</published><updated>2005-07-29T20:49:29.280-07:00</updated><title type='text'>Fuzzy Logic and Fuzzy SQL, or Richard's Big &amp; Tall Shop</title><content type='html'>These explanations are based on my readings so far in Earl Cox's &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0121942759/qid=1122690167/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/102-4566640-7454518?v=glance&amp;s=books&amp;amp;n=507846"&gt;Fuzzy Modeling and Genetic Algorithms for Data Mining and Exploration&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fuzzy Logic, or Are you tall?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A more complete explanation can be found &lt;a href="http://en.wikipedia.org/wiki/Fuzzy_Logic"&gt;here&lt;/a&gt;, but here's a short version. Fuzzy Logic is a superset of Boolean Logic. In Boolean Logic, you're either in a set or not, and this can be represented by a membership function that returns either 0 or 1. In Fuzzy Logic, an item's membership in a set is measured in a continuous number from 0 to 1, determined by a membership function.&lt;br /&gt;&lt;br /&gt;As an example, let's talk about "tall". A boolean membership function would be something like "if you're six feet or over, you're tall, else you're not". 0 or 1. A fuzzy membership function could be "if you're 5 feet or under, your tallness is 0. If you're 6 feet or over, your tallness is 1. From 5 feet to 6 feet it's a continuous slope". So, if someone is 5'9" their membership in the "tallness" set is .75.&lt;br /&gt;&lt;br /&gt;In this logic system, a fuzzy AND of two numbers is the minimum of the numbers, a fuzzy OR is the maximum of the numbers, and a fuzzy NOT is 1 - a number. If you think of booleans as either 0 or 1, these operators are the same. Fuzzy is a superset of boolean.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fuzzy SQL, or are you Tall and Heavy?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's say I'm opening a new chain of Big &amp; Tall stores, and let's say I bought a database or broke into some insurer and have a huge list of names, addresses, heights and weights. I want to determine who in the database it would be worth my while to send a direct mailing. In regular SQL a query would look something like&lt;br /&gt;&lt;br /&gt;select name, address from prospects where height =&gt; 74 and weight =&gt; 210;&lt;br /&gt;&lt;br /&gt;That would give me a subset to work with, but what about someone who's 72 inches and 240? He's probably a pretty good prospect, but my boolean filtering would miss him. I could play with the cutoffs, but there would always be someone just outside, and if I move them too far I increase my chances of adding people who wouldn't be interested, and exclude the tall but not too heavy or heavy but not too tall.&lt;br /&gt;&lt;br /&gt;Fuzzy SQL is a way of managing this problem. A Fuzzy SQL statement that we would use would look like&lt;br /&gt;&lt;br /&gt;select name, address from prospects where height is tall and weight is heavy;&lt;br /&gt;&lt;br /&gt;Looks kind of meaningless. What's "tall and heavy"? Well, first you start by computing individual membership numbers for the "tall" set and the "heavy" set using membership functions I wrote about above. Then with these individual numbers you compute what Cox calls a "Query Compatibility Index" (QCIX), which are different ways of combining the individual numbers. One way is the classic fuzzy AND, the minimum of the numbers. Another way is to average the numbers, perhaps with a weighted average, if for example I thought heavy was more important than tall. The Fuzzy SQL query should also return extra columns, such as the QCIX and perhaps the individual membership numbers calculated by the membership functions.&lt;br /&gt;&lt;br /&gt;Sticking with a regular average would be OK for my direct mailing purposes. Tall and heavy would give a high QCIX, but also would very tall but not that heavy, and vice versa. So, the query is run and the rows sorted according to the QCIX, and we give a cutoff value for the QCIX below which rows are not returned. Print them envelopes, throw in a coupon and we're good to go.&lt;br /&gt;&lt;br /&gt;The source code in the book is in Visual Basic, but what's the fun in that? What we really need is language that can add extra keywords such as the "is" and make it look like the rest of the language, that can take symbols like "tall" and "heavy" and associate them with membership functions....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112269524360459131?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112269524360459131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112269524360459131' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112269524360459131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112269524360459131'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/fuzzy-logic-and-fuzzy-sql-or-richards.html' title='Fuzzy Logic and Fuzzy SQL, or Richard&apos;s Big &amp; Tall Shop'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112234697158953179</id><published>2005-07-25T20:01:00.000-07:00</published><updated>2005-07-25T20:02:51.596-07:00</updated><title type='text'>It's OK if you want to do this one</title><content type='html'>I've been working with &lt;a href="http://activemq.com"&gt;ActiveMQ&lt;/a&gt; at work. In addition to being the Java Messaging System in Apache's Geronimo, it's also going to have open-source C libraries, and support from the financial community (&lt;a href="http://www.eweek.com/article2/0,1759,1761537,00.asp"&gt;See Here&lt;/a&gt;). What inspired me to write it that is also has &lt;a href="http://activemq.org/REST"&gt;REST API&lt;/a&gt;. This means that a fairly simple Lisp library could be whipped up to communicate with J2EE app servers, C applications, etc. I may get around to this eventually, but if someone else wants to have a crack at this that's OK with me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112234697158953179?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112234697158953179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112234697158953179' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112234697158953179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112234697158953179'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/its-ok-if-you-want-to-do-this-one.html' title='It&apos;s OK if you want to do this one'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112200313475853210</id><published>2005-07-21T20:32:00.000-07:00</published><updated>2005-07-21T20:35:12.396-07:00</updated><title type='text'>CLHS &amp; CLTL in Compiled Help format</title><content type='html'>&lt;a href="http://www.flickr.com/photos/50877487@N00/27466899/" title="photo sharing"&gt;&lt;img src="http://photos21.flickr.com/27466899_e4bf841584_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;&lt;a href="http://www.flickr.com/photos/50877487@N00/27466899/"&gt;clhs-win&lt;/a&gt; &lt;br /&gt;Originally uploaded by &lt;a href="http://www.flickr.com/people/50877487@N00/"&gt;ralphrichardcook&lt;/a&gt;.&lt;/span&gt;&lt;br clear="all" /&gt;&lt;p&gt;I've found where someone has put the CLHS and CLTL in WIndows Compiled Help format. What's so nice about this, at least on Windows, it that's much easier to search than navigating the links in a browser. It works great in Windows, pictured here, but the mac viewer doesn't do indexes or searches. I'll look for an X viewer and see if I can compile it on the mac.&lt;br /&gt;The CHM files can be found  &lt;a href="http://xarch.tu-graz.ac.at/autocad/lisp/cormanlisp/src/README.txt"&gt;here&lt;/a&gt;, scroll to the bottom for URL's.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112200313475853210?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112200313475853210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112200313475853210' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112200313475853210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112200313475853210'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/clhs-cltl-in-compiled-help-format.html' title='CLHS &amp; CLTL in Compiled Help format'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112174243968839717</id><published>2005-07-18T19:01:00.000-07:00</published><updated>2005-07-18T20:07:19.703-07:00</updated><title type='text'>Smug Lisp Weenies unite...or at least talk to each other</title><content type='html'>For a while I've been hearing about Ruby on Rails, and how Ruby's metaprogramming makes it possible to do it with so few lines of code. Well, we all know that Lisp invented metaprogramming, so I was thinking of working on a Lisp version of Rails. Then I see &lt;a href="http://bc.tech.coop/blog/050717.html"&gt;this&lt;/a&gt;. Someone who's worked on it for months, come up with a better version than I could, and is giving demos on it.&lt;br /&gt;&lt;br /&gt;Time for Plan B.&lt;br /&gt;&lt;br /&gt;I'm reading Earl Cox's "Fuzzy Modeling and Genetic Algorithms for Data Mining and Exploration". Upcoming chapters use something he calls "Fuzzy SQL" to model fuzzy sets, and genetic algorithms for tuning. I'm thinking of modifying or extending CLSQL to incorporate the Fuzzy SQL concepts, and look at John Koza's genetic programming for tuning in Lisp.&lt;br /&gt;&lt;br /&gt;So, I'm asking, IS ANYONE ELSE DOING THIS? Am I going to start working on this, only to find a blog entry one day where someone's been working on this for months, come up with a better version than I could, and is giving demos on it?&lt;br /&gt;&lt;br /&gt;If so, I'd appreciate it if you'd drop a comment here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112174243968839717?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112174243968839717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112174243968839717' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112174243968839717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112174243968839717'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/smug-lisp-weenies-uniteor-at-least.html' title='Smug Lisp Weenies unite...or at least talk to each other'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112173825013822181</id><published>2005-07-18T18:52:00.000-07:00</published><updated>2005-07-18T18:57:30.140-07:00</updated><title type='text'>I think Pesty is a Lisp programmer</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/7878/1123/1600/pesty-lisp-programmer.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/7878/1123/320/pesty-lisp-programmer.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112173825013822181?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112173825013822181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112173825013822181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112173825013822181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112173825013822181'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/i-think-pesty-is-lisp-programmer.html' title='I think Pesty is a Lisp programmer'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-112173790751406534</id><published>2005-07-18T18:48:00.000-07:00</published><updated>2005-07-18T18:51:47.520-07:00</updated><title type='text'>Optimization conundrums</title><content type='html'>I've been programming professionally for 20 years, and programming Java professionally for about five. Something I think I have in Java is a good feel for optimization and performance, at least on the micro level. What code is going to cause a lot of object creation, what choice of libraries is the best for a certain set of circumstances, etc. &lt;br /&gt;&lt;br /&gt;Let's say I don't have that in Lisp yet. I worked on a benchmark for the &lt;a href="http://shootout.alioth.debian.org/"&gt;Computer Language Shootout&lt;/a&gt;, and my best optimizations with declarations weren't doing so well. I asked for help on Usenet, Nicolas Neuss had a look, and, well, I'll just show you.&lt;br /&gt;&lt;br /&gt;Here's my code (testrrc package) and Nicolas' (testnn package) combined for one of the routines.&lt;br /&gt;&lt;br /&gt;This is compiled and run in CMUCL on my 1 Ghz iBook.&lt;br /&gt;&lt;br /&gt;(proclaim '(optimize (speed 3) (safety 0) (debug 0) (compilation-speed 0) (space 0)))&lt;br /&gt;&lt;br /&gt;(defpackage :testrrc)&lt;br /&gt;(in-package :testrrc)&lt;br /&gt;&lt;br /&gt;(defconstant IM     139968)&lt;br /&gt;(defconstant IA       3877)&lt;br /&gt;(defconstant IC     29573)&lt;br /&gt;&lt;br /&gt;(defparameter THE_LAST 42)&lt;br /&gt;(declaim (inline gen_random))&lt;br /&gt;&lt;br /&gt;(declaim (inline gen_random))&lt;br /&gt;(defun gen_random (max)&lt;br /&gt;  (declare (type (signed-byte 32) IM IA IC THE_LAST))&lt;br /&gt;  (declare (double-float max))&lt;br /&gt;  (setq THE_LAST (mod (+ (* THE_LAST IA) IC) IM))&lt;br /&gt;  (/ (* max THE_LAST) IM))&lt;br /&gt;&lt;br /&gt;(defpackage :testnn)&lt;br /&gt;(in-package :testnn)&lt;br /&gt;&lt;br /&gt;(defconstant IM     139968)&lt;br /&gt;(defconstant IA       3877)&lt;br /&gt;(defconstant IC     29573)&lt;br /&gt;&lt;br /&gt;(defparameter THE_LAST 42)&lt;br /&gt;(declaim (inline gen_random))&lt;br /&gt;&lt;br /&gt;(defun gen_random (max)&lt;br /&gt;  (declare (type (unsigned-byte 30) IM IA IC THE_LAST))&lt;br /&gt;  (declare (double-float max))&lt;br /&gt;  (setq THE_LAST (mod&lt;br /&gt;                  (+ (the (unsigned-byte 31) (* THE_LAST IA)) IC) IM))&lt;br /&gt;  (/ (* max THE_LAST) IM))&lt;br /&gt;&lt;br /&gt;(in-package :common-lisp-user)&lt;br /&gt;&lt;br /&gt;(defun main ()&lt;br /&gt;  (time (dotimes (i 7500000) (testrrc::gen_random 1.0d0)))&lt;br /&gt;  (Time (dotimes (i 7500000) (testnn::gen_random 1.0d0))))&lt;br /&gt;&lt;br /&gt;And here's the results.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;; Evaluation took:&lt;br /&gt;;   1.45 seconds of real time&lt;br /&gt;;   1.142364 seconds of user run time&lt;br /&gt;;   0.025509 seconds of system run time&lt;br /&gt;;   1,529,475,015 CPU cycles&lt;br /&gt;;   0 page faults and&lt;br /&gt;;   5,127,264 bytes consed.&lt;br /&gt;; &lt;br /&gt;&lt;br /&gt;; Evaluation took:&lt;br /&gt;;   0.28 seconds of real time&lt;br /&gt;;   0.133931 seconds of user run time&lt;br /&gt;;   6.7e-4 seconds of system run time&lt;br /&gt;;   294,265,464 CPU cycles&lt;br /&gt;;   0 page faults and&lt;br /&gt;;   0 bytes consed.&lt;br /&gt;&lt;br /&gt;Not only does that small change make it 5 times faster, but I have no idea why my version needs to cons 5 MEGS of bytes, and Nicolas' conses ZERO bytes. Anyone care to explain that one to me?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-112173790751406534?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/112173790751406534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=112173790751406534' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112173790751406534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/112173790751406534'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/07/optimization-conundrums.html' title='Optimization conundrums'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-111655939331123715</id><published>2005-05-19T20:19:00.000-07:00</published><updated>2005-05-19T20:23:13.313-07:00</updated><title type='text'>I wish I'd said that.</title><content type='html'>From &lt;a href="http://adamconnor.org/?m=200505"&gt;Marginilia&lt;/a&gt;, a quote that sums up my feelings pretty well.&lt;br /&gt;&lt;br /&gt;There are still things to learn about Java, too, and I’m sure there are many smart people working on it, but here is the difference: studying Lisp is like peeking behind the curtain and mastering the secrets of the universe, whereas studying Java is like learning how fix your old truck — lots of particulars but not much theory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-111655939331123715?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/111655939331123715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=111655939331123715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111655939331123715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111655939331123715'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/05/i-wish-id-said-that.html' title='I wish I&apos;d said that.'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-111655916580160150</id><published>2005-05-19T20:12:00.000-07:00</published><updated>2005-05-19T20:19:25.803-07:00</updated><title type='text'>So what is a closure?</title><content type='html'>For the Java and other imperative language users, &lt;a href="http://today.java.net/pub/a/today/2005/05/19/fences.html"&gt;here&lt;/a&gt; is a good explanation of what closures are. Read the sections titled "&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;We're no longer in Kansas" and "Does a Fence Keep things in or out?".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-111655916580160150?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/111655916580160150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=111655916580160150' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111655916580160150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111655916580160150'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/05/so-what-is-closure.html' title='So what is a closure?'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12983281.post-111638207876304410</id><published>2005-05-17T22:07:00.000-07:00</published><updated>2005-05-17T19:07:58.766-07:00</updated><title type='text'>What brought me to Lisp</title><content type='html'>Since the main emphasis of my writings will be about my explorations in and around Lisp, I thought I'd start with how I came to Lisp. This is an abreviated version of what's &lt;a href="http://http://lisp.tech.coop/Ralph%20Richard%20Cook"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A few years back I started looking into functional programming, and started with &lt;a href="http://www.haskell.org"&gt;Haskell&lt;/a&gt;, a pure functional language. This is fine for learning the basic concepts of functional programming, but imperative is better for some things, mainly I/O. Haskell's monads made my head hurt. Sometimes you just want to print something out or access a database without getting a PhD.&lt;br /&gt;&lt;br /&gt;This led to &lt;a href="http://www.ocaml.org"&gt;OCaml&lt;/a&gt;, which seemed to have most of what I wanted. Functional, but not obsessively so (you can printf when you want to). Good execution speed. Support for objects. I read a lot of literature about functional programming vs. object-oriented programming and came to the conclusion that both have their uses so I wanted a language that had both. I started writing some simple OCaml programs as I was learning the language and I liked the way they came out, no having to declare variable types, first-class functions, etc. Then I got farther along in my studies, learning more about how objects and classes are used in OCaml. I started looking at how they handled the FP vs. OOP tension, namely adding functions to a existing class/module vs. adding classes and subclasses, and they started talking about parameterized classes and abstract modules and the syntax started getting more and more complicated.&lt;br /&gt;&lt;br /&gt;In Common Lisp, the FP/OOP tension is handled with multimethods - much simpler. Metaprogramming in Common Lisp is done with defmacro, backquote and comma and is done in place, where in OCaml you need a separate preprocessor and a syntax that's rather different than the syntax of the language itself.&lt;br /&gt;&lt;br /&gt;I would say that OCaml and Lisp give you much the same power to do things, but my experience is that while doing the simple stuff may be simpler in OCaml than in Lisp, doing the complicated stuff is simpler in Lisp than in OCaml, and I plan on doing a lot more of the complicated stuff than the simple stuff.&lt;br /&gt;&lt;br /&gt;I don't want to expend my brainpower wrestling with my programming language, I want to expend it solving problems, and with Lisp I don't wrestle the language. Although some say Common Lisp is a 'big' language, it's basically just parentheses and keywords.&lt;br /&gt;&lt;br /&gt;If you think the prefix arithmetic is hard, well it can be, but how often do you put the Pythagorean theorem in your code, vs. just making a function call with parameters? Is foo(bar) that much easier than (foo bar)?&lt;br /&gt;&lt;br /&gt;Oh, and about the parentheses? Get a parenthesis-matching editor, and get over it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12983281-111638207876304410?l=i-need-closures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://i-need-closures.blogspot.com/feeds/111638207876304410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12983281&amp;postID=111638207876304410' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111638207876304410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12983281/posts/default/111638207876304410'/><link rel='alternate' type='text/html' href='http://i-need-closures.blogspot.com/2005/05/what-brought-me-to-lisp.html' title='What brought me to Lisp'/><author><name>Richard Cook</name><uri>http://www.blogger.com/profile/11838741004941594394</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
