<?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-4334522554803190021</id><updated>2011-04-21T13:35:57.355-07:00</updated><category term='ruby'/><category term='proga'/><category term='asdf'/><category term='hunchentoot'/><category term='web'/><category term='mudballs'/><category term='asdf-install'/><category term='google group'/><category term='programming'/><category term='arc'/><category term='windows'/><category term='rep'/><category term='lisp'/><category term='openmcl'/><category term='ccl'/><category term='common lisp'/><category term='case'/><category term='CLOS'/><title type='text'>On Code</title><subtitle type='html'>My ramblings on Lisp, Ruby and Coding.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4334522554803190021.post-2817682259145176251</id><published>2009-03-29T01:35:00.000-07:00</published><updated>2009-03-29T02:45:03.418-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ccl'/><category scheme='http://www.blogger.com/atom/ns#' term='hunchentoot'/><category scheme='http://www.blogger.com/atom/ns#' term='openmcl'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Hunchentoot and CCL on Windows. Take 2.</title><content type='html'>&lt;div&gt;I &lt;a href="http://sean-ross.blogspot.com/2009/03/hunchentoot-ccl-and-windows.html"&gt;recently posted a brief workaround&lt;/a&gt; for a bug in &lt;a href="http://ccl.clozure.com/"&gt;CCL&lt;/a&gt; on MS Windows which prevented &lt;a href="http://weitz.de/hunchentoot/"&gt;Hunchentoot&lt;/a&gt; from responding to HTTP requests. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Shortly after posting this I, and everyone else on the &lt;a href="http://clozure.com/mailman/listinfo/openmcl-devel"&gt;openmcl-devel&lt;/a&gt; mailing list, received an &lt;a href="http://clozure.com/pipermail/openmcl-devel/2009-March/009037.html"&gt;email from R. Matthew Emerson&lt;/a&gt; who has informed us that this issue was resolved in their SVN repository over a week ago and that CCL no longer needs the workaround I posted.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So for all those CCL+Windows users, you can now &lt;pre&gt;svn update&lt;/pre&gt; and &lt;pre&gt;(rebuild-ccl :clean t)&lt;/pre&gt; and ignore my previous post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-2817682259145176251?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/2817682259145176251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=2817682259145176251' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/2817682259145176251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/2817682259145176251'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2009/03/hunchentoot-and-ccl-on-windows-take-2.html' title='Hunchentoot and CCL on Windows. Take 2.'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-5494127773263096051</id><published>2009-03-27T13:33:00.001-07:00</published><updated>2009-03-27T14:31:20.558-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ccl'/><category scheme='http://www.blogger.com/atom/ns#' term='hunchentoot'/><category scheme='http://www.blogger.com/atom/ns#' term='openmcl'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><title type='text'>Hunchentoot, CCL and Windows</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's been a couple of months now and I've been warming to &lt;a href="http://trac.clozure.com/openmcl"&gt;CCL&lt;/a&gt;, so much so in fact, that it has replaced SBCL as my `other` CL implementation. If you've never used it, it is an Open Source Common Lisp which runs on a number of platforms, including Windows, Mac OS X and Linux in both 32 and 64 bit modes and supports threading on all 3 of these platforms.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is however a &lt;a href="http://clozure.com/pipermail/openmcl-devel/2009-March/009008.html"&gt;small issue when running Hunchentoot with CCL on Windows&lt;/a&gt;; you will notice when connecting to a CCL+Hunchentoot server that it never responds with any content but hangs indefinitely. This is caused by a bug in the CCL Windows timeout handling which requires a small workaround by the user.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fortunately the workaround is straightforward; simply start up &lt;a href="http://weitz.de/hunchentoot/"&gt;Hunchentoot&lt;/a&gt; with the following extra parameters:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&gt; (hunchentoot:start (make-instance 'hunchentoot:acceptor :port 8080 &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;:read-timeout nil :write-timeout nil&lt;/span&gt;&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And you are on your way.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-5494127773263096051?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/5494127773263096051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=5494127773263096051' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5494127773263096051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5494127773263096051'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2009/03/hunchentoot-ccl-and-windows.html' title='Hunchentoot, CCL and Windows'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-8016878160726087876</id><published>2009-03-17T10:41:00.000-07:00</published><updated>2009-03-21T10:27:07.484-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mudballs'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><title type='text'>Mudballs 3</title><content type='html'>&lt;div&gt;&lt;blockquote&gt;&lt;/blockquote&gt;Well, I've finally pushed Mudballs 3 out the door and, while it contains a large number of changes and many improvements, this post isn't only about the work that has been done in the past few months but will also touch on where Mudballs will be going in the months to come.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The bad news is that, once again and for the very last time,  Mudballs users will be required to reinstall the mudballs distribution as various internals have been moved around, I'm terribly sorry about this and I've done my best to ensure that this is the last time that it will happen. Please note that nothing will break if you do not upgrade but the old repository will no longer be updated.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always Mudballs is available from &lt;a href="http://mudballs.com/#installing"&gt;http://mudballs.com/#installing&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;Lets first look at the changes that have made their way into the repository.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;ASDF Support:&lt;/span&gt; This is a big one, Mudballs now includes a sysdef.asdf system which provides an ASDF package (or more precisely, a SYSDEF.ASDF package with the nickname ASDF) to provide ASDF support. To be more precise defsystem, operate and  the various component and action classes are exported and provide the same service you would normally expect from ASDF. The biggest drawback that it has at the moment is that when specializing methods on operate invoking `call-next-method` will have undefined consequences (read that as `Don't call call-next-method`).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold; "&gt;Single File Systems:&lt;/span&gt; Mudballs can now be used to load single files on your computer. Mudballs will now search on the list &lt;tt&gt;*search-paths*&lt;/tt&gt;   for systems when a relative portable pathname is supplied.  As an example, given a &lt;tt&gt;*search-paths*&lt;/tt&gt; of &lt;tt&gt;'("~/Lisp/")&lt;/tt&gt; and a file named #P"~/Lisp/workfiles/cc-validate.lisp" I can compile and load this file using the following form.  &lt;pre&gt;(mb:load ";workfiles;cc-validate")&lt;/pre&gt; Internally a component is created in mudballs and is operated upon and can be looked up using &lt;tt&gt;&lt;a href="http://mudballs.com/documentation/mb.sysdef/find-system-generic-function.html"&gt;find-system&lt;/a&gt;&lt;/tt&gt;.   The component which is created can be customized by adding a &lt;tt&gt;(mb:component . options)&lt;/tt&gt; form to the top of the file.  As an example, a small file which needs &lt;tt&gt;:cl-ppcre&lt;/tt&gt; can be customized by adding the following form to the top of the file.  &lt;pre&gt;#+mudballs (mb:component (:needs :cl-ppcre))&lt;/pre&gt; It is worth noting that &lt;tt&gt;&lt;a href="http://mudballs.com/documentation/mb.sysdef/single-file-system-class.html"&gt;SINGLE-FILE-SYSTEM&lt;/a&gt;&lt;/tt&gt; is not, in fact, a subclass of &lt;tt&gt;SYSTEM&lt;/tt&gt; but rather a subclass of &lt;tt&gt;LISP-SOURCE-FILE&lt;/tt&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Multiple parent classes:&lt;/span&gt; DEFINE-SYSTEM now accepts any number of parent classes. This will create an anonymous class which extends the provided classes. eg.&lt;pre&gt;(define-system :my-system (core-system-mixin system)  .....)&lt;/pre&gt; Will create a new system which extends both core-system-mixin and system.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;FOR Option:&lt;/span&gt;  In an attempt to remove the need for #+ and #- reader macros in system definitions (which do not behave well with automating releases) a :FOR option has been added to components and to the syntax for defining dependencies which can be used to achieve that same goal as read time conditionalization. As an example, consider Edi Weitz's excellent &lt;a href="http://weitz.de/drakma/"&gt;:DRAKMA&lt;/a&gt; system which has a dependency on :USOCKET for all implementation other than Lispworks. Previously the needs form would have looked something like the following. &lt;pre&gt; (:NEEDS #-lispworks :USOCKET)&lt;/pre&gt;    Using :FOR (which is now the preferred approach) the :NEEDS form will now look like this. &lt;pre&gt; (:NEEDS (:USOCKET (:FOR (:NOT :LISPWORKS)))) &lt;/pre&gt;Granted this is somewhat more verbose (although somewhat less so when replacing a #+ conditionalization) it does mean that the system dependencies are now portably inspectable. This option is applicable to ALL instances of components, including modules and files. It is also worth noting the value for the FOR option can be anything which is suitable to sysdef::featurep.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;NAMED-MODULE:&lt;/span&gt; The named-module is a new subclass of module which provides a way to specify the directory of the module per implementation,  this is designed to provide a more introspectable alternative to the reader conditionalization macros. As an example, CLOSER-MOP has the following NAMED-MODULE in it's COMPONENTS list. &lt;br /&gt;&lt;pre&gt;(COMPAT NAMED-MODULE  &lt;br /&gt;  (:NAMES :ALLEGRO :CLISP :LISPWORKS&lt;br /&gt;          ((:OR :MCL :OPENMCL) "mcl")  &lt;br /&gt;          ((:OR :CMU :SBCL) "pcl"))  &lt;br /&gt;  (:COMPONENTS "closer-mop-packages" "closer-mop"))&lt;/pre&gt;Each entry in the :NAMES option is expected to be either a symbol which, when matched using featurep, will use the string-downcase'd  version of the symbol as the directory name. When a list is provided then the first element in the list is the argument which will be tested using featurep and the second is the name to use if it matches.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;REQUIRES Option:&lt;/span&gt; The requires option has gone through a number of changes and has now been resurrected from a deprecated nickname  for :NEEDS to portable way to `CL:REQUIRE` implementation specific libraries which you have a dependency on. Previously this was only handled for SBCL by defining SBCL systems in a system-definition file. This file has now been dropped and the :REQUIRES option is now the preferred  way to load implementation specific requirements.  As an example usocket has a dependency on SB-BSD-SOCKETS which used to be handled by having a &lt;pre&gt;(:NEEDS #+sbcl :SB-BSD-SOCKETS)&lt;/pre&gt; option. This is now replaced by &lt;pre&gt;(:REQUIRES (:SB-BSD-SOCKETS (:FOR :SBCL)))&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;CONDUIT-SYSTEM's:&lt;/span&gt; A new subclass of System is now exported; this class, which performs the same task as asdf-system-connections,  provides a means to define a system which is loaded automatically when all of it's dependencies are loaded. A conduit system can be defined either by specifying &lt;a href="http://mudballs.com/documentation/mb.sysdef/conduit-system-class.html"&gt;CONDUIT-SYSTEM&lt;/a&gt; in the superclass list of &lt;a href="http://mudballs.com/documentation/mb.sysdef/define-system-macro.html"&gt;define-system&lt;/a&gt; or by defining your system using &lt;a href="http://mudballs.com/documentation/mb.sysdef/define-conduit-system-macro.html"&gt;DEFINE-CONDUIT-SYSTEM&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Portable Pathname Specifiers:&lt;/span&gt; Mudballs now provides a portable way of specifying pathnames when passing pathnames to the :config-file and :preferences-file options. In this naming scheme directory names are seperated by #\;'s (a semicolon) and mudballs will ensure that any path starting with #\~ (tilde) will have the result of (user-homedir-pathname) merged with the remaining namestring. Example. &lt;tt&gt;"~;mudballs;test.lisp"&lt;/tt&gt; is a portable yet shorter way of specifying &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(merge-pathnames (make-pathname :directory '(:relative "mudballs")&lt;br /&gt;                                :name "test" :type "lisp") &lt;br /&gt;                 (user-homedir-pathname))&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;tt&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Other Features and Change&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;FEATURE: system definitions files now are automatically compiled when mudballs changes. (this includes files added using wildcard-searcher)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;FEATURE: You no longer need to run sysdef:register-sysdefs when you add new systems. It is automatically run before find-system (some attempt has been made to ensure that it doesn't impact performance too heavily)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;BUG FIX: (:needs (:cl-ppcre :version "1.3")) is once again valid.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UPDATE: The no-installed-component condition has been removed as it is a conceptual duplicate.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;UPDATE: redefining a system no longer creates a new instance of a SYSTEM but will reset and update the currently defined one if one exists.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;BUG FIX: redefining a system will not cause the system to be considered un-operated upon.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;NEWS: Mudballs now waits until the last possible moment before loading system definitions, this now results in faster startup times.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;And many other small changes and fixes.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span"  style="font-size:x-large;"&gt;The Future&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now that we've gotten the past and present out of the way lets look to the future. Mudballs, while having had a large portion of work dedicated to operating upon systems, does &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;NOT&lt;/span&gt; have&lt;span class="Apple-style-span" style="font-style: italic;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;'&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;operating on systems'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; as it's primary goal. Mudballs is primarily about Distribution and distributing Common Lisp systems in particular, which is &lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;It's biggest difference to ASDF and &lt;br /&gt;&lt;/li&gt;&lt;li&gt;a far more useful problem that needs solving.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what does this mean? It means that mudballs users can expect, in the near future, a portion of mudballs.com dedicated to the creation of projects and the uploading of new versions of systems which will automatically provide new definition files and downloadable mudballs on mudballs.com.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This will allow any writer of Common Lisp code to upload their system and make it available (with correct version information) to the rest of the world, complete with automatically generated documentation and links to the various releases. This, not so small, feature should go along way to providing Common Lispers with something which is at least converging on CPAN.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is all being done with one thing in mind: Repeatability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is currently the biggest shortcoming of the ASDF family, in that the installation of an arbitrary set of systems cannot be reliably reproduced, which makes troubleshooting library combination issues incredibly difficult; and of course the more systems you have installed the more likely it becomes that what you have will differ from a maintainer which makes having dependencies on systems an inherently risky affair.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I know I'm not the only person who's had a particular system fail only to be told by the maintainer that `It works for me` followed by a list of the versions he is using. This is typically followed by the `Vain attempt to find these exact versions` dance [1] which is all too often followed by the `I give up, hands in the air` shuffle. As it stands, ASDF and friends just do not help here and &lt;span class="Apple-style-span" style="font-style: italic;"&gt;this&lt;/span&gt; is the situation Mudballs is intended to solve.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Mudballs primary purpose is not System Definition but Repeatable System Distribution.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always comments and investments of time are welcome and you can reach myself and other Mudballs users at the &lt;a href="http://groups.google.com/group/mudballs/"&gt;Mudballs Google Group&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enjoy,&lt;/div&gt;&lt;div&gt; Sean.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Don't even get me started about systems whose primary form of distribution is `Fresh checkout from VC tool of choice`.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/tt&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-8016878160726087876?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/8016878160726087876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=8016878160726087876' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8016878160726087876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8016878160726087876'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2009/03/mudballs-3.html' title='Mudballs 3'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-5973919184252612505</id><published>2009-02-12T07:44:00.000-08:00</published><updated>2009-02-12T14:19:17.100-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mudballs'/><category scheme='http://www.blogger.com/atom/ns#' term='google group'/><title type='text'>Mudballs Google Group</title><content type='html'>&lt;div&gt;Not a full update I'm afraid, although one will be coming shortly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;In the interests of promoting discussion about Mudballs I have created a mudballs google group.&lt;div&gt;This can be found by pointing your browser at &lt;a href="http://groups.google.com/group/mudballs/"&gt;http://groups.google.com/group/mudballs/&lt;/a&gt;  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope to see you there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;sean.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-5973919184252612505?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/5973919184252612505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=5973919184252612505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5973919184252612505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5973919184252612505'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2009/02/mudballs-google-group.html' title='Mudballs Google Group'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-7576317353047655676</id><published>2009-01-08T14:03:00.000-08:00</published><updated>2009-01-08T14:03:19.683-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mudballs'/><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><title type='text'>A Mudballs Update</title><content type='html'>&lt;span class="Apple-style-span"   style="  ;font-family:Helvetica;font-size:12px;"&gt;&lt;div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "&gt;Yes, I know it's late but better late than never right.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, I have just uploaded the 'Christmas Cheer' release of mudballs which, unfortunately, will require a fresh install of mudballs for existing users as there was a rather egregious oversight regarding the updating of systems.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Noteworthy Features&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;A publicly editable wiki has now been made available at &lt;a href="http://redmine.mudballs.com/wiki/mudballs/"&gt;http://redmine.mudballs.com/wiki/mudballs/&lt;/a&gt;   New pages can be created by opening the appropriate URL. For example, &lt;a href="http://redmine.mudballs.com/wiki/mudballs/hunchentoot"&gt;http://redmine.mudballs.com/wiki/mudballs/hunchentoot&lt;/a&gt; will  show an option for creating a new page. &lt;/li&gt;&lt;li&gt;The start of a mudballs FAQ can be found on it's wiki page: &lt;a href="http://redmine.mudballs.com/wiki/mudballs/FAQ"&gt;http://redmine.mudballs.com/wiki/mudballs/FAQ&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;down-casing of pathnames has been fixed. Down-casing will now only happen for components named with symbols.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;New versions of all systems, including core systems such as :cl-ppcre, can now be updated without having to reinstall mudballs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;(mb:install :cl-ppcre :file "/path/to/file") now works.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The output path of component is now calculated correctly (including honoring the :fasl-output-root preference).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Uninstalled systems are no longer considered  for an operation if there is an installed version of the system present unless explicitly requested using the :version keyword.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The fasl-path of system definition files is no longer the same as components of a system as this was conflicting with the output of compiling components.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;And other small fixes&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always mudballs is available for download from the &lt;a href="http://mudballs.com/releases/"&gt;releases&lt;/a&gt; directory and instructions can be found &lt;a href="http://redmine.mudballs.com/wiki/mudballs/Install"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Please let &lt;a href="mailto:sross@mudballs.com"&gt;me&lt;/a&gt; know if any server on mudballs.com is not responding as my hosting provider is being a little flaky of late.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thanks to the following people for reports and ideas.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- Magnus Malm&lt;/div&gt;&lt;div&gt;- Luke Renn&lt;/div&gt;&lt;div&gt;- Leigh Smith&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-7576317353047655676?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/7576317353047655676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=7576317353047655676' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7576317353047655676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7576317353047655676'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2009/01/mudballs-update.html' title='A Mudballs Update'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-8552976849898440834</id><published>2008-12-02T11:21:00.000-08:00</published><updated>2008-12-03T01:37:58.528-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mudballs'/><category scheme='http://www.blogger.com/atom/ns#' term='hunchentoot'/><category scheme='http://www.blogger.com/atom/ns#' term='asdf'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Announcing Mudballs</title><content type='html'>&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; This post is to announce the release of &lt;/span&gt;&lt;a href="http://mudballs.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Mudballs&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;, a collection of Common Lisp code for managing systems.  It is currently in an early stage of development and still has a long way to go but is currently able to compile,  load, document, download and install systems across Windows, Linux and Mac OSX. Mudballs supports the following implementations &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;Lispworks on Mac OSX, Linux and Windows.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;SBCL on Mac OSX and Linux.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;CMUCL on Mac OSX and Linux.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;CLISP on Linux and Windows (Mac OSX as well provided  you have FFI).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;ClozureCL/OpenMCL on Mac OSX, Linux and Windows.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;AllegroCL on Mac OSX, Linux and Windows.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; As it currently stands it is not ASDF compatible (not ideal, I know) but ASDF support is planned for the future. It is available from &lt;/span&gt;&lt;a href="http://mudballs.com/"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;http://mudballs.com&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;  which contains enough information to get the intrepid lisper on his or  her way.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt; As a small taste, the following is now possible from a freshly installed Lisp with Mudballs loaded.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;pre&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&gt; (mb:install :hunchentoot)&lt;br /&gt;&gt; (hunchentoot:start-server :port 8080)&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;P.S.  Prizes for anyone that can come up with a logo which doesn't look like a pile of excrement.&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-8552976849898440834?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/8552976849898440834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=8552976849898440834' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8552976849898440834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8552976849898440834'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2008/12/announcing-mudballs.html' title='Announcing Mudballs'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4334522554803190021.post-7224584681033905783</id><published>2008-05-08T07:33:00.000-07:00</published><updated>2008-05-08T07:34:24.757-07:00</updated><title type='text'>Renaming files in Common Lisp.</title><content type='html'>&lt;p&gt;So I ran across &lt;a href="http://reddit.com/r/programming/info/5z1fl/comments/c02b4wa"&gt;this&lt;/a&gt; while going through my morning catchup routine  and thought it could do with some clearing up. &lt;/p&gt;&lt;p&gt;The part of the post I'm actually interested is this.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;When Haskell can compete on those types of problems, it'll be easier to induce people to learn it. (Same with CL, my fav language....)&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;blah, blah=""&gt;&lt;/blah,&gt;&lt;/p&gt;&lt;p&gt;Now, bonus points for proclaiming CL as being his favorite language, but minus 10 billion for continuing the meme&lt;meme&gt; that CL is somehow unsuited for writing[1] these kinds of simple software (for whatever definition of simple you have).&lt;br /&gt;&lt;/meme&gt;&lt;/p&gt;&lt;p&gt;One of the examples given is  "I have a bunch of files, and I want to rename them all according to some pattern." and as it so happens translate-pathname[2] makes this wonderfully simple.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;(defun rename-files (from to)&lt;br /&gt; (dolist (file (directory from))&lt;br /&gt;   (rename-file file (translate-pathname file from to))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And thats it, 3 lines of code, or for our simple testing purposes&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun show-rename-files (from to)&lt;br /&gt; (dolist (file (directory from))&lt;br /&gt;   (format t "Renaming ~A to ~A~%" file&lt;br /&gt;           (translate-pathname file from to))))&lt;br /&gt;&lt;br /&gt;(show-rename-files "/usr/share/pixmaps/*.xpm" "/usr/share/pixmaps/backup-*.xpm")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The funny thing is that this isn't secret knowledge but is pulled straight from the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_tr_pn.htm"&gt;Hyperspec&lt;/a&gt; (see the examples).&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;[1]: Please note, I said 'writing' them, not 'creating a 2k binary' of them, please people CL /= Unix.&lt;br /&gt;[2]: Granted, the behavior of translate-pathname isn't specified in detail by the spec but that doesn't mean we cannot use it.&lt;br /&gt;&lt;br /&gt;This post brought to you by Lispworks 5.1, clisp 2.41 and SBCL 1.0.12&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-7224584681033905783?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/7224584681033905783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=7224584681033905783' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7224584681033905783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7224584681033905783'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2008/05/renaming-files-in-common-lisp.html' title='Renaming files in Common Lisp.'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-3771908341406498671</id><published>2008-02-10T19:00:00.000-08:00</published><updated>2008-02-10T14:44:01.726-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='case'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><title type='text'>Case Conversion Considered Useful</title><content type='html'>One of the stranger[1] features of Common Lisp is that the CL reader, by default, will convert symbols to uppercase[2] which can be a little surprising to newcomers, and inevitably leads misconceptions regarding case (in)sensitivity.&lt;br /&gt;&lt;br /&gt;One of the advantages of this automatic case conversion is that it allows us to use case as syntactic markers.&lt;br /&gt;&lt;br /&gt;Here's a simple example (ignore the non idiomatic use of CL).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun filter (test list)&lt;br /&gt; (let ((result ()))&lt;br /&gt;   (dolist (elt list result)&lt;br /&gt;     (when (funcall test elt)&lt;br /&gt;       (push elt result)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Did you notice the return form?&lt;br /&gt;This happens to be one of those constructs that is quite easy to overlook when reading through code, it doesn't happen often but it does happen[3].&lt;br /&gt;&lt;br /&gt;However, if we change it to this.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defun filter (test list)&lt;br /&gt; (let ((result ()))&lt;br /&gt;   (dolist (elt list RESULT)&lt;br /&gt;     (when (funcall test elt)&lt;br /&gt;       (push elt result)))))&lt;br /&gt;&lt;/pre&gt;the result form 'leaps' out of the page which makes it very difficult to miss.&lt;br /&gt;&lt;br /&gt;It's the code equivalent of wearing a silly hat.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;p&gt;1: Stranger, as in, 'This isn't like C/Java/Python/Ruby'.&lt;br /&gt;2: This is only the default and can be changed using &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_rdtabl.htm"&gt;readtable-case&lt;/a&gt;&lt;br /&gt;3: Well it happens to me, ok.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-3771908341406498671?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/3771908341406498671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=3771908341406498671' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3771908341406498671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3771908341406498671'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2008/02/case-conversion-considered-useful.html' title='Case Conversion Considered Useful'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-3357625226370370755</id><published>2008-02-05T10:27:00.000-08:00</published><updated>2008-02-05T11:19:51.224-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='rep'/><category scheme='http://www.blogger.com/atom/ns#' term='arc'/><title type='text'>The 'pre Arc' Arc</title><content type='html'>Seeing that arc is the word on everyones lips I thought I'd take a quick peek.&lt;br /&gt;&lt;br /&gt;In Summary.&lt;br /&gt;- data in the functional position is interesting.&lt;br /&gt;- [] function syntax is neat (and almost as nice as the #L syntax in iterate)&lt;br /&gt;- foo:bar for function composition reads quite nicely (once you get out of the CL mindset)&lt;br /&gt;&lt;br /&gt;The rest is kind of 'meh' and then i realized, wait a second,  a Lisp1 with more Lisp than Scheme and unhygienic macros,  I've seen that before and I had, it is called &lt;a href="http://librep.sourceforge.net/librep-manual.html"&gt;rep&lt;/a&gt;.  This is the Lisp that powers sawfish which (and someone correct me if I'm wrong) was the default window manager for GNOME for quite some time.&lt;p&gt;This was actually the Lisp that I cut my teeth on way back in 2001 (Grief, I can't believe it was that long ago)  and looking back on it brings back some fond memories and reminds me how full featured it was (especially for something at version 0.17), to list some of them:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Profiler&lt;/li&gt;&lt;li&gt;Module system (modelled on Scheme48)&lt;/li&gt;&lt;li&gt;Tail call elimination&lt;/li&gt;&lt;li&gt;Byte Compiled&lt;/li&gt;&lt;li&gt;First class Continuations&lt;/li&gt;&lt;li&gt;Regexes&lt;/li&gt;&lt;li&gt;Threading&lt;/li&gt;&lt;li&gt;Good access to OS &lt;/li&gt;&lt;li&gt;Ability to load .so files&lt;/li&gt;&lt;li&gt;Bindings to mysql&lt;/li&gt;&lt;li&gt;Built in documentation via the ,desc operator&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;and&lt;strong&gt; Most&lt;/strong&gt; importantly it has apropos, god knows why arc is missing this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-3357625226370370755?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/3357625226370370755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=3357625226370370755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3357625226370370755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3357625226370370755'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2008/02/pre-arc-arc.html' title='The &apos;pre Arc&apos; Arc'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-6893785966780286198</id><published>2007-10-26T10:04:00.000-07:00</published><updated>2007-10-26T02:10:29.927-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='proga'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><title type='text'>Ruby Quiz 144 (in CL)</title><content type='html'>There was a small posting on c.l.l asking if anyone felt like completing Ruby quiz 144 in CL and after &lt;a href="http://www.lispcast.com/index.php/2007/10/time-window-matcher/"&gt;eric's&lt;/a&gt; solution I thought I'd give it a go.&lt;br /&gt;&lt;br /&gt;This needs :cl-ppcre and :alexandria (and :lisp-unit to run the tests)&lt;br /&gt;Apologies for formatting screwiness.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;(defpackage :time-window (:use :cl :cl-ppcre :alexandria)&lt;br /&gt;  (:export #:in-window-p))&lt;br /&gt;&lt;br /&gt;(in-package :time-window)&lt;br /&gt;&lt;br /&gt;;(defparameter *window* "Sat-Mon; Mon Wed 0700-0900; Thu 0700-0900 1000-1200")&lt;br /&gt;&lt;br /&gt;;; This works by converting a spec (like the one above) into it's seperate components (split by ;)&lt;br /&gt;;; and converting each spec into distinct time and day parts (expanding day ranges as we go)&lt;br /&gt;;; so the above would be converted into the following&lt;br /&gt;;; ((nil                       ("Sat" "Sun" "Mon"))&lt;br /&gt;;;  (("0700-0900")             ("Mon" "Wed"))&lt;br /&gt;;;  (("0700-0900" "1000-1200") ("Thu")))&lt;br /&gt;;; We can then walk through each converted spec ensuring that the time specified falls into&lt;br /&gt;;; the time/day specified.&lt;br /&gt;&lt;br /&gt;(defun in-window-p (time window)&lt;br /&gt;  (some (lambda (spec)&lt;br /&gt;          (every (lambda (part)&lt;br /&gt;                   (if (null part)&lt;br /&gt;                       t ;; since (some (constantly t) ()) is nil&lt;br /&gt;                       (some (curry 'time-within time) part)))&lt;br /&gt;                 spec))&lt;br /&gt;        (mapcar (lambda (split)&lt;br /&gt;                  (group-by-type (split " " (string-trim " " split))))&lt;br /&gt;                (split ";" window))))&lt;br /&gt;&lt;br /&gt;(defun group-by-type (list)&lt;br /&gt;  (loop for spec in list&lt;br /&gt;        :when (time-range-p spec) :collect spec :into times&lt;br /&gt;        :when (single-day-p spec) :collect spec :into days&lt;br /&gt;        :when (day-range-p spec) :append (days-of spec) :into days&lt;br /&gt;        :finally (return (list times days))))&lt;br /&gt;&lt;br /&gt;(defparameter *days*&lt;br /&gt;  '(("Mon" . 0) ("Tue" . 1) ("Wed" . 2) ("Thu" . 3) ("Fri" . 4) ("Sat" . 5) ("Sun" . 6)))&lt;br /&gt;&lt;br /&gt;(defparameter *day-ring* (let ((list (copy-list *days*)))&lt;br /&gt;                           (setf (cdr (last list)) list)&lt;br /&gt;                           list))&lt;br /&gt;&lt;br /&gt;(defun single-day-p (spec)&lt;br /&gt;  (assoc spec *days* :test 'string=))&lt;br /&gt;&lt;br /&gt;(defun day&lt;-spec (spec)&lt;br /&gt;  (cdr (single-day-p spec)))&lt;br /&gt;&lt;br /&gt;(defun day-range-p (spec)&lt;br /&gt;  (and (= (count #\- spec) 1)&lt;br /&gt;       (every 'single-day-p (split "-" spec))))&lt;br /&gt;&lt;br /&gt;(defun days-of (spec)&lt;br /&gt;  (assert (day-range-p spec))&lt;br /&gt;  (destructuring-bind (start stop) (split "-" spec)&lt;br /&gt;    (loop :for (day . nil) :in (member start *day-ring* :key 'first :test 'string=)&lt;br /&gt;          :collect day&lt;br /&gt;          :until (string= day stop))))&lt;br /&gt;&lt;br /&gt;(defun single-time-p (spec)&lt;br /&gt;  (every 'digit-char-p spec))&lt;br /&gt;&lt;br /&gt;(defun time-range-p (spec)&lt;br /&gt;  (and (= 1 (count #\- spec))&lt;br /&gt;       (every 'single-time-p (split "-" spec))))&lt;br /&gt;&lt;br /&gt;(defun time-in-range (hour minute start stop)&lt;br /&gt;  (flet ((to-mins (x) (+ (* 60 (parse-integer (subseq x 0 2)))&lt;br /&gt;                         (parse-integer (subseq x 2 4)))))&lt;br /&gt;    (&lt;= (to-mins start) (+ (* 60 hour) minute) (1- (to-mins stop)))))&lt;br /&gt;&lt;br /&gt;(defun time-within (time spec)&lt;br /&gt;  (multiple-value-bind (sec minute hour date month year day)&lt;br /&gt;      (decode-universal-time time 0)&lt;br /&gt;    (declare (ignore sec date month year))&lt;br /&gt;    (cond ((single-day-p spec) (= day (day&lt;-spec spec)))&lt;br /&gt;          ((time-range-p spec)&lt;br /&gt;           (apply #'time-in-range hour minute (split "-" spec))))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;;;; and a small test package&lt;br /&gt;(defpackage :time-window.tests (:use :time-window :lisp-unit :cl))&lt;br /&gt;(in-package :time-window.tests)&lt;br /&gt;&lt;br /&gt;;; Tests&lt;br /&gt;(define-test window-tests&lt;br /&gt;  (let ((window "Sat-Sun; Mon Wed 0700-0900; Thu 0700-0900 1000-1200"))&lt;br /&gt;    (flet ((in (sec hour date month year)&lt;br /&gt;             (in-window-p (encode-universal-time 0 sec hour date month year 0) window)))&lt;br /&gt;    (assert-false (in 0 8 25 9 2007))&lt;br /&gt;    (assert-true  (in 0 8 26 9 2007))&lt;br /&gt;    (assert-false (in 0 11 26 9 2007))&lt;br /&gt;    (assert-false (in 59 6 27 9 2007))&lt;br /&gt;    (assert-true (in 0 7 27 9 2007))&lt;br /&gt;    (assert-true (in 59 8 27 9 2007))&lt;br /&gt;    (assert-false (in 0 9 27 9 2007))&lt;br /&gt;    (assert-true (in 0 11 27 9 2007))&lt;br /&gt;    (assert-true (in 0 11 29 9 2007))&lt;br /&gt;    (assert-true (in 0 0 29 9 2007))&lt;br /&gt;    (assert-true (in 59 23 29 9 2007))&lt;br /&gt;    )))&lt;br /&gt;&lt;br /&gt;(define-test window-tests2&lt;br /&gt;  (let ((window "Fri-Mon"))&lt;br /&gt;    (flet ((in (date month year)&lt;br /&gt;             (in-window-p (encode-universal-time 0 0 0 date month year 0) window)))&lt;br /&gt;      (assert-false (in 27 9 2007))&lt;br /&gt;      (assert-true (in 28 9 2007))&lt;br /&gt;      (assert-true (in 29 9 2007))&lt;br /&gt;      (assert-true (in 30 9 2007))&lt;br /&gt;      (assert-true (in 1 10 2007))&lt;br /&gt;      (assert-false (in 2 10 2007)))))&lt;br /&gt;&lt;br /&gt;(run-tests)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nothing flashy but it does remind me how useful circular lists can be.&lt;br /&gt;Comments, as always, are welcomed.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;This post brought to you by Lispworks 5.0.2&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-6893785966780286198?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/6893785966780286198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=6893785966780286198' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6893785966780286198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6893785966780286198'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/10/ruby-quiz-144-in-cl.html' title='Ruby Quiz 144 (in CL)'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-324938598755394301</id><published>2007-07-21T18:00:00.000-07:00</published><updated>2007-07-21T10:05:54.835-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='CLOS'/><title type='text'>Closures + Lambda &lt; CLOS</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;There's&lt;/span&gt; a blog post floating around the web[1] on how Closures + Lambda make up all the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;OO&lt;/span&gt; programming tools you'll ever want or need.  Now this is a long running theme[2] in the Lisp family and really is a testament to how flexible Common Lisp (or any other language which shares these traits) is&lt;br /&gt;&lt;br /&gt;.... however ....&lt;br /&gt;&lt;br /&gt;the majority of these are for pedagogical purposes[3] and should never be seriously&lt;br /&gt;compared with a fully fledged object system. It's seems to be in vogue to consider&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;CLOS&lt;/span&gt; elephantine[4] and complex but the truth is that at the surface &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;CLOS&lt;/span&gt; is wonderfully simple.&lt;br /&gt;&lt;br /&gt;We have classes with slots (read instance variables) created with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;defclass&lt;/span&gt;, we create&lt;br /&gt;instances of these classes with make-instance. We access (and change) the slots of these&lt;br /&gt;instances using slot-value and create methods for the classes using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;defmethod&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Simple, yes? Not complex or elephantine, Yes?&lt;br /&gt;&lt;br /&gt;You can read more of course (all in the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;CLHS&lt;/span&gt;) and discover the object initialization protocol&lt;br /&gt;and how the classes of objects can be changed on the fly, you can find out how to customize&lt;br /&gt;the initialization of your classes and add &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;accessors&lt;/span&gt; to your slots.&lt;br /&gt;You can dig deeper and you'll discover the MOP and discover how to change the behaviour of&lt;br /&gt;slot access and class definition.&lt;br /&gt;&lt;br /&gt;But remember that you do not need to understand any of this in order to&lt;br /&gt;define classes, create instances, access slots and define methods!&lt;br /&gt;&lt;br /&gt;So next time you are rolling your own Object System because someone considers &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;CLOS&lt;/span&gt; too slow,&lt;br /&gt;or too large, stop and give &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;CLOS&lt;/span&gt; a try, you may just like it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--------------------&lt;br /&gt;[1] : See &lt;a href="http://lispy.wordpress.com/2007/07/18/closures-lambda-the-key-to-oop-in-lisp/"&gt;here&lt;/a&gt; and &lt;a href="http://lispy.wordpress.com/2007/07/09/closures-hash-tables-as-much-oop-as-youll-ever-need/"&gt;here&lt;/a&gt; .&lt;br /&gt;[2] : And is implemented in &lt;a href="http://norvig.com/paip.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;PAIP&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt;  among others.&lt;br /&gt;[3] : For a full &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;OO&lt;/span&gt; implementation in CL see &lt;a href="http://www.cliki.net/KR"&gt;KR&lt;/a&gt;  which is a prototype based object system with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;valuepropogation&lt;/span&gt;.  &lt;br /&gt;[4] : Or big, slow[5] or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;klunky&lt;/span&gt;&lt;br /&gt;[5] : This myth has officially been debunked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-324938598755394301?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/324938598755394301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=324938598755394301' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/324938598755394301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/324938598755394301'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/07/closures-lambda-clos.html' title='Closures + Lambda &lt; CLOS'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-3241702824010819156</id><published>2007-07-18T17:30:00.000-07:00</published><updated>2007-07-18T14:05:25.989-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Lisp in Lisp</title><content type='html'>One of the fantastic things about Common Lisp is discovering how you can write parts of the language in the language itself and I'm not talking about implementing number parsing or some library function but rather a languages control structures. A nice and relatively simple one, is implementing handler-case[1] in portable Common Lisp[2].&lt;br /&gt;  &lt;pre class="htmlize"&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defvar"&gt;defvar&lt;/a&gt; &lt;span class="variable-name"&gt;*handlers*&lt;/span&gt; () &lt;span class="string"&gt;"Alist of condition name to handler"&lt;/span&gt;)&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defvar"&gt;defvar&lt;/a&gt; &lt;span class="variable-name"&gt;*old-handlers*&lt;/span&gt; () &lt;span class="string"&gt;"Var to save the bindings of *handlers*"&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defclass"&gt;defclass&lt;/a&gt; root-error () &lt;br /&gt;  ((message &lt;span class="builtin"&gt;:initarg&lt;/span&gt; &lt;span class="builtin"&gt;:message&lt;/span&gt; &lt;span class="builtin"&gt;:accessor&lt;/span&gt; message-of &lt;span class="builtin"&gt;:initform&lt;/span&gt; &lt;span class="string"&gt;"Unknown"&lt;/span&gt;))&lt;br /&gt;  (&lt;span class="builtin"&gt;:documentation&lt;/span&gt; &lt;span class="string"&gt;"Our base error class."&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defun"&gt;defun&lt;/a&gt; &lt;span class="function-name"&gt;raise&lt;/span&gt; (class text)&lt;br /&gt;  &lt;span class="string"&gt;"signals an error of class CLASS with message TEXT."&lt;/span&gt;&lt;br /&gt;  (&lt;a href="http://lispdoc.com/?q=let"&gt;let&lt;/a&gt; ((handler (get-handler class)))&lt;br /&gt;    (&lt;a href="http://lispdoc.com/?q=if"&gt;if&lt;/a&gt; handler&lt;br /&gt;        (invoke-handler handler (&lt;a href="http://lispdoc.com/?q=make-instance"&gt;make-instance&lt;/a&gt; class &lt;span class="builtin"&gt;:message&lt;/span&gt; text))&lt;br /&gt;        &lt;span class="comment"&gt;;; This is our 'we crash now'&lt;/span&gt;&lt;br /&gt;        (&lt;a href="http://lispdoc.com/?q=error"&gt;error&lt;/a&gt; text))))&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;; We implement our handlers as functions.&lt;/span&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defun"&gt;defun&lt;/a&gt; &lt;span class="function-name"&gt;invoke-handler&lt;/span&gt; (handler class)&lt;br /&gt;  (&lt;a href="http://lispdoc.com/?q=funcall"&gt;funcall&lt;/a&gt; handler class))&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defun"&gt;defun&lt;/a&gt; &lt;span class="function-name"&gt;get-handler&lt;/span&gt; (class)&lt;br /&gt;  &lt;span class="string"&gt;"Finds the first handler on *handlers* which is registered with a class&lt;br /&gt;which CLASS is a subtype of."&lt;/span&gt;&lt;br /&gt;  (&lt;a href="http://lispdoc.com/?q=cdr"&gt;cdr&lt;/a&gt; (&lt;a href="http://lispdoc.com/?q=find-if"&gt;find-if&lt;/a&gt; (&lt;a href="http://lispdoc.com/?q=lambda"&gt;lambda&lt;/a&gt; (handler) (&lt;a href="http://lispdoc.com/?q=subtypep"&gt;subtypep&lt;/a&gt; class handler))&lt;br /&gt;                &lt;span class="variable-name"&gt;*handlers*&lt;/span&gt; &lt;span class="builtin"&gt;:key&lt;/span&gt; 'car)))&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defun"&gt;defun&lt;/a&gt; &lt;span class="function-name"&gt;add-handlers&lt;/span&gt; (&amp;amp;rest handlers)&lt;br /&gt;  &lt;span class="string"&gt;"Takes a list of (class . handler) forms and creates a new&lt;br /&gt;list which can be used as *handlers*"&lt;/span&gt;&lt;br /&gt;  (&lt;a href="http://lispdoc.com/?q=append"&gt;append&lt;/a&gt; handlers &lt;span class="variable-name"&gt;*handlers*&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;;; And all that is left now is to implement trycatch&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defmacro"&gt;defmacro&lt;/a&gt; trycatch (form &amp;amp;body error-bindings)&lt;br /&gt;  (&lt;a href="http://lispdoc.com/?q=let*"&gt;let*&lt;/a&gt; ((block (gensym &lt;span class="string"&gt;"BLOCK"&lt;/span&gt;))&lt;br /&gt;         &lt;span class="comment"&gt;;; turns each handler into a list of (tmpvar classname handler-fn)&lt;/span&gt;&lt;br /&gt;         &lt;span class="comment"&gt;;; its important that we save the state of *handlers* to prevent&lt;/span&gt;&lt;br /&gt;         &lt;span class="comment"&gt;;; using the handler bindings we are a part of  if we signal an error &lt;/span&gt;&lt;br /&gt;         &lt;span class="comment"&gt;;; from within a handler.&lt;/span&gt;&lt;br /&gt;         (binds (loop for (name args . body) in error-bindings&lt;br /&gt;                      collect (list (gensym) name `(lambda ,args&lt;br /&gt;                                                     (let ((&lt;span class="variable-name"&gt;*handlers*&lt;/span&gt; &lt;span class="variable-name"&gt;*old-handlers*&lt;/span&gt;))&lt;br /&gt;                                                       (return-from ,block (progn ,@body))))))))&lt;br /&gt;    `(&lt;a href="http://lispdoc.com/?q=block"&gt;block&lt;/a&gt; ,block&lt;br /&gt;       (&lt;a href="http://lispdoc.com/?q=let*"&gt;let*&lt;/a&gt; ((&lt;span class="variable-name"&gt;*old-handlers*&lt;/span&gt; &lt;span class="variable-name"&gt;*handlers*&lt;/span&gt;)&lt;br /&gt;              &lt;span class="comment"&gt;;; binds our tmpvar to the handler-function&lt;/span&gt;&lt;br /&gt;              ,@(mapcar (lambda (bind) (list (first bind) (third bind)))&lt;br /&gt;                        binds))&lt;br /&gt;         &lt;span class="comment"&gt;;; and add (classname . handler-fn) to *handlers*&lt;/span&gt;&lt;br /&gt;         (&lt;a href="http://lispdoc.com/?q=let"&gt;let&lt;/a&gt; ((&lt;span class="variable-name"&gt;*handlers*&lt;/span&gt; (add-handlers ,@(mapcar (lambda (bind)&lt;br /&gt;                                                     `(cons ',(second bind) ,(first bind)))&lt;br /&gt;                                                   binds))))&lt;br /&gt;           ,form)))))&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;and we now raise and catch errors&lt;/span&gt;&lt;br /&gt;(trycatch (raise 'root-error &lt;span class="string"&gt;"foo"&lt;/span&gt;)&lt;br /&gt;  (root-error (c) (&lt;a href="http://lispdoc.com/?q=format"&gt;format&lt;/a&gt; t  &lt;span class="string"&gt;"WE GOT AN ERROR ~A"&lt;/span&gt; c)))&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defclass"&gt;defclass&lt;/a&gt; my-error (root-error) ())&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://lispdoc.com/?q=defun"&gt;defun&lt;/a&gt; &lt;span class="function-name"&gt;test-my-error&lt;/span&gt; () (raise 'my-error &lt;span class="string"&gt;"Whoops!~%"&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;(trycatch (test-my-error)&lt;br /&gt;  (my-error (c) (&lt;a href="http://lispdoc.com/?q=format"&gt;format&lt;/a&gt; t &lt;span class="string"&gt;"Great it works!~%"&lt;/span&gt;)))&lt;br /&gt;&lt;br /&gt;(trycatch (test-my-error)&lt;br /&gt;  (root-error (c) (&lt;a href="http://lispdoc.com/?q=format"&gt;format&lt;/a&gt; t &lt;span class="string"&gt;"And subtyping works too~%"&lt;/span&gt;)))&lt;br /&gt;&lt;br /&gt;(trycatch (trycatch (test-my-error)&lt;br /&gt;            (root-error (c) (raise 'my-error &lt;span class="string"&gt;"new-error"&lt;/span&gt;))&lt;br /&gt;            (my-error (c) &lt;span class="string"&gt;"INNER MY-ERROR HANDLER"&lt;/span&gt;))&lt;br /&gt;  (my-error (c) &lt;span class="string"&gt;"OUTER MY-ERROR HANDLER"&lt;/span&gt;))&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;;; should return "OUTER MY-ERROR HANDLER"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;Next step handler-bind[3].&lt;br /&gt;&lt;br /&gt;-------------------------------&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;[1] : http://www.lispworks.com/documentation/HyperSpec/Body/m_hand_1.htm&lt;br /&gt;  Slow and renamed to trycatch for namespace reasons.&lt;br /&gt;[2] : hmmmm, is this the start of recursive Greenspunning?&lt;br /&gt;[3] : http://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm&lt;br /&gt;&lt;br /&gt;-----&lt;br /&gt;This post is courtesy of lispworks(5.0.2), emacs22 and lispdoc&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-3241702824010819156?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/3241702824010819156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=3241702824010819156' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3241702824010819156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3241702824010819156'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/07/one-of-fantastic-things-about-common.html' title='Lisp in Lisp'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-3712572592693080811</id><published>2007-06-22T07:35:00.000-07:00</published><updated>2007-06-22T08:05:41.169-07:00</updated><title type='text'>Advertising is good</title><content type='html'>Lifted from Akita's &lt;a href="http://www.akitaonrails.com/pages/olabini"&gt;interview&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; I think that Ruby have almost all the power I'm used to from Common Lisp. [sic]&lt;br /&gt; - Ola Bini&lt;br /&gt;&lt;br /&gt;Unsolicited advertising from a well respected individual, 'nuff said.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-3712572592693080811?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/3712572592693080811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=3712572592693080811' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3712572592693080811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/3712572592693080811'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/06/advertising-is-good.html' title='Advertising is good'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-6217094172797234718</id><published>2007-05-29T07:22:00.001-07:00</published><updated>2007-05-30T08:13:02.379-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hunchentoot'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>Hunchentoot and packages</title><content type='html'>Over the past couple of years I've been experimenting with a number of CL&lt;br /&gt;http  servers and have recently turned to &lt;a href="http://weitz.de/hunchentoot"&gt;hunchentoot&lt;/a&gt;  as my platform of choice&lt;br /&gt;which, like the rest of Edi's packages, has found it's way into my heart.&lt;br /&gt;&lt;br /&gt;One of the things I've often found rather annoying however (not with&lt;br /&gt;Hunchentoot specifically, this is present in all of the CL web servers&lt;br /&gt;I've experimented with) is that publishing a URL is a twofold process:&lt;br /&gt;&lt;br /&gt;a) define your handler function (or something similar) and&lt;br /&gt;b) register that handler with a particular URL.&lt;br /&gt;&lt;br /&gt;Now all this becomes a little repetitive so here is a new publisher function&lt;br /&gt;which allows you to publish your package on a particular URL so that any&lt;br /&gt;requests to URL's   'below' that one will be resolved to a function in your package.&lt;br /&gt;&lt;br /&gt;We play on one of the less remarked upon CL features (or lack of restrictions)&lt;br /&gt;which allows symbols to start with a #\/ (a forward slash,  to those not used to&lt;br /&gt;the CL character macro reader) so we can publish our package on /test define a&lt;br /&gt;function named /foo and automagically have requests to /test/foo mapped&lt;br /&gt;to our /foo handler.&lt;br /&gt;&lt;br /&gt;(modified 30/5/2007 16:00)&lt;br /&gt;eg.&lt;br /&gt;&lt;pre style="font-size: small;"&gt;&lt;br /&gt;(asdf:oos 'asdf:load-op :hunchentoot)&lt;br /&gt;(asdf:oos 'asdf:load-op :cl-who)&lt;br /&gt;&lt;br /&gt;(defpackage :pack-test (:use :cl :hunchentoot :cl-who))&lt;br /&gt;(in-package :pack-test)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(defun index ()&lt;br /&gt;  #'(lambda ()&lt;br /&gt;      (with-html-output-to-string (x)&lt;br /&gt;        (:html "The index page"))))&lt;br /&gt;&lt;br /&gt;(defun seq-last (seq)&lt;br /&gt;  (aref seq (1- (length seq))))&lt;br /&gt;&lt;br /&gt;(defun string-&gt;handler (string package)&lt;br /&gt;  (when (string= string "/") (return-from string-&gt;handler (index)))&lt;br /&gt;  (multiple-value-bind (sym type) (find-symbol string package)&lt;br /&gt;    (when (and (not (eql type :inherited))&lt;br /&gt;               (fboundp sym))&lt;br /&gt;      (symbol-function sym))))&lt;br /&gt;                                  &lt;br /&gt;(defun create-package-dispatcher (prefix)&lt;br /&gt;  (check-type prefix string)&lt;br /&gt;  (assert (eql (seq-last prefix) #\/) (prefix) "Prefix must end in a / (forward slash)")&lt;br /&gt;  #'(lambda (request)&lt;br /&gt;      (let* ((function (script-name request))&lt;br /&gt;             (mismatch (mismatch (script-name request) prefix&lt;br /&gt;                                 :test #'char=)))&lt;br /&gt;        (when (or (null mismatch)&lt;br /&gt;                  (&gt;= mismatch (length prefix)))&lt;br /&gt;          (string-&gt;handler (string-upcase (subseq function (1- (length prefix))))&lt;br /&gt;                           *package*)))))&lt;br /&gt;&lt;br /&gt;(push (create-package-dispatcher "/test/") *dispatch-table*)&lt;br /&gt;&lt;br /&gt;(defun /index ()&lt;br /&gt;  (with-html-output-to-string (out)&lt;br /&gt;    (:html (:head (:title "Welcome"))&lt;br /&gt;           (:body (:h2 "This is my welcome page")))))&lt;br /&gt;&lt;br /&gt;(defvar *server* (start-server :port 8080))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and now browsing to &lt;a href="http://localhost:8080/test/index"&gt;http://localhost:8080/test/index&lt;/a&gt;  should give you  a&lt;br /&gt;nice new welcome page and adding a new URL is a simple 1 step process.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;This post is courtesy of lispworks(5.0.2),  hunchentoot(0.9.2) and cl-who (0.4.4)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-6217094172797234718?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/6217094172797234718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=6217094172797234718' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6217094172797234718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6217094172797234718'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/05/hunchentoot-and-packages.html' title='Hunchentoot and packages'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4334522554803190021.post-7134984833569786334</id><published>2007-05-01T02:11:00.000-07:00</published><updated>2007-05-01T05:29:19.825-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asdf-install'/><category scheme='http://www.blogger.com/atom/ns#' term='asdf'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><title type='text'>asdf-install &amp; Windows</title><content type='html'>Thanks to Nate's latest release of  &lt;a href="http://www.method-combination.net/blog/archives/2007/04/30/new-archive-release.html"&gt;archive&lt;/a&gt; we can now use asdf-install on Windows&lt;br /&gt;without resorting to cygwin or gnu-tar. Just add the following to your .asdf-install.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(asdf:oos 'asdf:load-op :gzip-stream)&lt;br /&gt;(asdf:oos 'asdf:load-op :archive :version "0.6")&lt;br /&gt;&lt;br /&gt;(defun asdf-install-extractor (to-dir tarball)&lt;br /&gt;(let ((name nil))&lt;br /&gt;  (gzip-stream:with-open-gzip-file (ins tarball)&lt;br /&gt;    (archive:with-open-archive (archive ins)&lt;br /&gt;      (let ((*default-pathname-defaults* (pathname to-dir)))&lt;br /&gt;        (archive:do-archive-entries (entry archive name)&lt;br /&gt;          (archive:extract-entry archive entry)&lt;br /&gt;          (unless name (setf name (archive:name entry)))))))&lt;br /&gt;  ;; we use string instead of namestring because&lt;br /&gt;  ;; asdf-install searches for /'s and not \'s&lt;br /&gt;  ;; which will break on windows&lt;br /&gt;  (string name)))&lt;br /&gt;&lt;br /&gt;(push 'asdf-install-extractor asdf-install:*tar-extractors*)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You will still get an error along the lines of&lt;br /&gt;"'gpg' is not recognized as an internal or external command,"&lt;br /&gt;but select the continue restart and all should be fine and dandy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;This post is courtesy of lispworks(5.0.2), gzip-stream(0.1),  asdf-install(0.5.5) and archive(0.6).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-7134984833569786334?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/7134984833569786334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=7134984833569786334' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7134984833569786334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/7134984833569786334'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/05/asdf-install-windows.html' title='asdf-install &amp; Windows'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-5201529320272820465</id><published>2007-04-19T08:00:00.000-07:00</published><updated>2007-04-19T08:03:56.093-07:00</updated><title type='text'>Feisty Friday</title><content type='html'>OK so it's not Friday, but &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu Feisty Fawn&lt;/a&gt; has been released.&lt;br /&gt;&lt;br /&gt;I've been constantly impressed with each release of Ubuntu and&lt;br /&gt;can heartily recommend it to anyone who wants to see what Linux&lt;br /&gt;is like.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-5201529320272820465?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/5201529320272820465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=5201529320272820465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5201529320272820465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/5201529320272820465'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/04/feisty-friday.html' title='Feisty Friday'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-2850331193133825744</id><published>2007-03-22T07:46:00.000-07:00</published><updated>2007-04-12T05:36:44.784-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>ORF and values</title><content type='html'>As it turns out my previous &lt;a href="http://sean-ross.blogspot.com/2007/02/orf-common-lisp-version-of.html"&gt;post&lt;/a&gt; does not allow a &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_values.htm"&gt;values&lt;/a&gt; form as a place (the macro expands into invalid code).&lt;br /&gt;&lt;br /&gt;So here is an updated version which behaves as follows.&lt;br /&gt;When provided with a values form then for each place n, if n is nil&lt;br /&gt;then n will be set to the nth value returned by the values-form.&lt;br /&gt;&lt;br /&gt;eg.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(let ((a 1)&lt;br /&gt;     b&lt;br /&gt;     (c 3))&lt;br /&gt; (orf (values a b c) (values 4 2 5))&lt;br /&gt; (values a b c))&lt;br /&gt;&lt;br /&gt;=&gt; 1,2,3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here it is in all it's glory.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defmacro orf (place value-form &amp;amp;environment env)&lt;br /&gt; (multiple-value-bind (vars vals store-vars writer reader)&lt;br /&gt;     (get-setf-expansion place env)&lt;br /&gt;   (let ((tmp-var (loop repeat (length store-vars) collect (gensym))))&lt;br /&gt;     `(let* (,@(mapcar 'list vars vals))&lt;br /&gt;        (multiple-value-bind ,store-vars ,reader&lt;br /&gt;          (multiple-value-bind ,tmp-var ,value-form&lt;br /&gt;            ,@(loop for store in store-vars for val in tmp-var&lt;br /&gt;                    collect `(unless  ,store (setf ,store ,val)))&lt;br /&gt;            ,writer))))))&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-2850331193133825744?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/2850331193133825744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=2850331193133825744' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/2850331193133825744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/2850331193133825744'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/03/orf-and-values.html' title='ORF and values'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-6146036205014163236</id><published>2007-02-07T09:30:00.001-08:00</published><updated>2007-03-29T03:10:19.648-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>orf (a Common Lisp version of ||=)</title><content type='html'>I've recently been programming in ruby and one of  the handy operators I've&lt;br /&gt;been using has been ||= .&lt;br /&gt;&lt;br /&gt;If you haven't seen it before think of it in terms of += .&lt;br /&gt;So x ||= 3 is equivalent to x = x || 3.&lt;br /&gt;&lt;br /&gt;I've found this pretty useful in a couple of cases and decided to write a&lt;br /&gt;CL implementation of it.  I give you ORF.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;pre&gt;&lt;br /&gt;(defmacro orf (place value &amp;amp;environment env)&lt;br /&gt; (multiple-value-bind (vars vals store-vars writer reader)&lt;br /&gt;   (get-setf-expansion place env)&lt;br /&gt; `(let* (,@(mapcar 'list vars vals)&lt;br /&gt;         (,@store-vars (or ,reader ,value)))&lt;br /&gt;    ,writer)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now (orf x 3) === (setf x (or x 3))&lt;br /&gt;&lt;br /&gt;with the minor caveat that x will only being evaluated once.&lt;br /&gt;&lt;br /&gt;Truly, Lisp is the Borg of programming languages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-6146036205014163236?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/6146036205014163236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=6146036205014163236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6146036205014163236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/6146036205014163236'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/02/orf-common-lisp-version-of.html' title='orf (a Common Lisp version of ||=)'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-1913790685185008665</id><published>2007-01-29T07:31:00.000-08:00</published><updated>2007-04-11T02:15:17.359-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='common lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Format</title><content type='html'>Format is one of those features in Common Lisp that people seem to have a love/hate relationship with, the other being loop. Both have their own mini languages that are not especially lispy. I'm still not too sure where I stand in this debate but being able  to say things like this is still pretty incredible.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow: auto; font-size: 11px;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;(defun print-diamond (str x &amp;optional c a (max (1+ x)) (star "*"))&lt;br /&gt;  (format str "~&amp;~[~:;~:*~vT~v@{~A ~:*~}~3@*~v,v/print-diamond/~:*~v[~:;~@*~vT~v@{~A ~:*~}~%~]~]"&lt;br /&gt;          x (- max x) star max star (1- x)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now for an explanation of that format string.&lt;br /&gt;Bear with me this is hairy.&lt;br /&gt;&lt;div style="font-size: 12px;"&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;~&amp; : Conditional newline (insert newline if we aren't at the start of a line)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~[ : Process the nth clause (seperated by ~:). ~:; specifies a default clause. This consumes the argument x. This directive causes print-diamond to stop processing when x is zero.&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;~:* : Backup 1 argument (unconsumes the argument x)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~vT : Insert arg number of spaces (this reconsumes the first argument ie. x)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~v@{ : Iterate v times, v is (- max x).&lt;/li&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;~A : Print 1 element&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~:* : Backup 1 element (The effects of the last 3 directives is to print star (- max x) times)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;~} : End loop&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~3@ : Move to the 3rd argument (star)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~v,v/print-diamond/ : The recursive call. invoke print-diamond again with max, star and (1- x), This is equivalent to calling (print-diamond stream (1- x) nil nil max star)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~:* : Backup 1 argument (unconsumes (1- x))&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~v[ : Conditional processing based (1- x).&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;~@* : Go to the start of the argument list.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~vT : Insert arg number of spaces (this consumes the first argument again)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~v@{ : Iterate v times, v is (- max x).&lt;ul&gt;&lt;br /&gt;&lt;li&gt;~A : Print 1 element&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~:* : Backup 1 element (The effects of the last 3 directives is to print star (- max x) times)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;~} : End loop&lt;/li&gt;&lt;br /&gt;&lt;li&gt;~% : Insert a new line&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;~] : End conditional processing&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;~] End conditional processing&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Whew, brain freeze.&lt;br /&gt;&lt;br /&gt;now we can do &lt;code&gt;(print-diamond t 10)&lt;/code&gt;&lt;br /&gt;&lt;pre style="font-size: 10px;"&gt;&lt;br /&gt;         *&lt;br /&gt;        * *&lt;br /&gt;       * * *&lt;br /&gt;      * * * *&lt;br /&gt;     * * * * *&lt;br /&gt;    * * * * * *&lt;br /&gt;   * * * * * * *&lt;br /&gt;  * * * * * * * *&lt;br /&gt; * * * * * * * * *&lt;br /&gt;* * * * * * * * * *&lt;br /&gt; * * * * * * * * *&lt;br /&gt;  * * * * * * * *&lt;br /&gt;   * * * * * * *&lt;br /&gt;    * * * * * *&lt;br /&gt;     * * * * *&lt;br /&gt;      * * * *&lt;br /&gt;       * * *&lt;br /&gt;        * *&lt;br /&gt;         *&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-1913790685185008665?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/1913790685185008665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=1913790685185008665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/1913790685185008665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/1913790685185008665'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/01/format.html' title='Format'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-8252640909651785592</id><published>2007-01-29T05:20:00.000-08:00</published><updated>2007-01-29T07:26:56.140-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>darjeeling</title><content type='html'>&lt;a href="http://technomancy.us/blog/post/72"&gt;This&lt;/a&gt; looks as if it could be quite interesting.&lt;br /&gt;&lt;br /&gt;The ability to convert Ruby to Common Lisp (or ideally just load ruby files) should put paid to complaints about the lack of libraries in CL.&lt;br /&gt;&lt;br /&gt;Of course it could turn out to be absolutely nothing but I'm going to keep an eye on it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-8252640909651785592?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/8252640909651785592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=8252640909651785592' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8252640909651785592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/8252640909651785592'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/01/darjeeling.html' title='darjeeling'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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-4334522554803190021.post-849549912555126831</id><published>2007-01-11T04:00:00.000-08:00</published><updated>2007-01-16T07:43:32.637-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Lispworks 5.1 Personal Edition</title><content type='html'>At last, Lispworks Ltd has announced the release of Lispworks 5.1 Personal Edition!&lt;br /&gt;&lt;br /&gt;New features&lt;br /&gt;- Threading now uses pthread on Linux&lt;br /&gt;- FreeBSD port&lt;br /&gt;- Support for Intel Mac's&lt;br /&gt;&lt;br /&gt;More &lt;a href="http://www.lispworks.com/news/index.html#501personalrelease"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4334522554803190021-849549912555126831?l=sean-ross.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sean-ross.blogspot.com/feeds/849549912555126831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4334522554803190021&amp;postID=849549912555126831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/849549912555126831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4334522554803190021/posts/default/849549912555126831'/><link rel='alternate' type='text/html' href='http://sean-ross.blogspot.com/2007/01/lispworks-51-personal-edition.html' title='Lispworks 5.1 Personal Edition'/><author><name>Sean Ross</name><uri>http://www.blogger.com/profile/07630823416408764714</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></feed>
