<?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-5966353302263378647</id><updated>2012-01-27T20:11:24.866-08:00</updated><category term='mistake'/><category term='array-operations'/><category term='debugging'/><category term='latex-table'/><category term='let-plus'/><category term='cl-rmath'/><category term='latex'/><category term='light'/><category term='github'/><category term='graphs'/><category term='llgpl'/><category term='api'/><category term='numerical methods'/><category term='linkedin'/><category term='library'/><category term='cl-num-utils'/><category term='interface'/><category term='numerical'/><category term='git'/><category term='bicycle'/><category term='debian'/><category term='flashlight'/><category term='e-books DRM Kindle indie'/><category term='cl-cairo2'/><category term='cl-colors'/><category term='linux'/><category term='scripting'/><category term='table'/><category term='emacs'/><category term='product review'/><category term='filk'/><category term='social network sites'/><category term='sparse matrix'/><category term='asdf-install'/><category term='arrays'/><category term='foreign arrays'/><category term='rootfinding'/><category term='graphics'/><category term='cffi'/><category term='sparse linear system'/><category term='parody'/><category term='lla'/><category term='migration'/><category term='music'/><category term='lisp'/><category term='syntax highlighting'/><category term='xarray'/><category term='cl-2d'/><category term='implementations'/><category term='ffa'/><category term='license change'/><category term='cl-numlib'/><category term='ecl'/><category term='cl-random'/><category term='array indexing'/><category term='library configuration'/><category term='book review'/><category term='optimization'/><category term='cl-sparsematrix'/><category term='led'/><category term='job market'/><category term='ubuntu'/><category term='cairo'/><category term='blogging'/><category term='org-mode'/><title type='text'>Tamas K Papp's blog</title><subtitle type='html'>Blog about random things, mostly technical stuff, software announcements, Lisp code.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-5478554361857492091</id><published>2012-01-26T01:12:00.000-08:00</published><updated>2012-01-26T01:17:32.645-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>cl-cairo2: new maintainer, new license</title><content type='html'>&lt;p&gt;&lt;a href="http://www.cliki.net/cl-cairo2"&gt;cl-cairo2&lt;/a&gt; was one of the first Common Lisp libraries I wrote, but I haven't been using it much for the last year or so (currently I am experimenting with &lt;a href="http://www.cliki.net/CL-PDF"&gt;cl-pdf&lt;/a&gt; as a backend for my new plotting library, which will be released soon).  I have been pretty busy with research, so I didn't have time to merge (and test) patches, also, I didn't even contemplate updating the library to make use of the latest version of &lt;a href="http://cairographics.org/"&gt;cairo&lt;/a&gt;.  So when &lt;a href="https://github.com/rpav"&gt;Ryan Pavlik&lt;/a&gt; contacted me about adding compatibility with &lt;a href="https://github.com/rpav/cl-freetype2"&gt;cl-freetype2&lt;/a&gt;, I asked him whether he wants to take over as a maintaner.  He kindly agreed, so I have transferred the &lt;a href="https://github.com/rpav/cl-cairo2"&gt;repository&lt;/a&gt; to him, and he already merged a lot of patches.
&lt;/p&gt;
&lt;p&gt;
One last thing that I wanted to fix before handing the repository over is the license.  Originally, the library was licensed under the GPL &amp;mdash; in retrospect, I think that
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I was very naive about software licenses, and didn't really understand what GPL means in the context if Common Lisp (I still don't claim that I do :-P), and
&lt;/li&gt;
&lt;li&gt;I didn't realize that there are a lot of commercial applications in the Common Lisp world, whose authors are wary of depending on GPL'ed libraries.
&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
Consequently, I received many complaints about the license of the library, and decided to change it.  I picked the &lt;a href="http://www.boost.org/users/license.html"&gt;Boost Software License&lt;/a&gt;, and contacted all who contributed to the library for permission.  All contributors approved the change, so now the library has &lt;a href="http://www.gnu.org/licenses/license-list.html#boost"&gt;a simple, permissive non-copyleft free software license&lt;/a&gt;.  However, it is always possible that I missed someone, so &lt;b&gt;if you contributed to cl-cairo2 in the past but didn't hear from me regarding the license change, please get in touch&lt;/b&gt; (eg via the Github &lt;a href="https://github.com/rpav/cl-cairo2/issues"&gt;issue tracker&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;
I would like to thank (in alphabetical order) Ala'a Mohammad Alawi, Jay Bromley, Pau Fernández, Johann Korndoerfer, Peter Mikula, and especially Kei Suzuki (who did the last major reorganization) for their contributions to the library (again, I apologize if I missed anyone).  I would also like to thank Ryan for taking over &amp;mdash; I am convinced that the library is in good hands.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5478554361857492091?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5478554361857492091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2012/01/cl-cairo2-new-maintainer-new-license.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5478554361857492091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5478554361857492091'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2012/01/cl-cairo2-new-maintainer-new-license.html' title='cl-cairo2: new maintainer, new license'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-2638247227965602911</id><published>2011-11-01T01:23:00.000-07:00</published><updated>2011-11-01T01:26:11.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Color schemes to prevent eye fatigue</title><content type='html'>&lt;p&gt;I have been sitting in front of the computer quite a bit in the past few weeks, and I noticed that my eyes get very tired by the end of the day (I used to get back pain too, but &lt;a href="http://shelterpub.com/_fitness/_stretching_in_the_office/sto_book.html"&gt;stretching&lt;/a&gt; helped a lot).  After a bit of reading I learned that the maximum-contrast white-on-black-based color scheme I was using is in fact extremely stressful for the eyes, and I started looking for something designed for the specific purpose of reducing eye fatigue.  After checking out &lt;a href="http://slinky.imukuppi.org/zenburn/"&gt;Zenburn&lt;/a&gt; for a few days, I started using &lt;a href="http://ethanschoonover.com/solarized"&gt;Solarized&lt;/a&gt; by Ethan Schoonover.  I find it really nice and relaxing, here is a screenshot of Emacs editing Common Lisp code:
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-nrSo8FhKFSU/Tq-s3TSThMI/AAAAAAAAAEM/3u7JXqvuDa8/s1600/solarized.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 369px;" src="http://2.bp.blogspot.com/-nrSo8FhKFSU/Tq-s3TSThMI/AAAAAAAAAEM/3u7JXqvuDa8/s400/solarized.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5669940521952576706" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-2638247227965602911?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/2638247227965602911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/11/color-schemes-to-prevent-eye-fatigue.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2638247227965602911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2638247227965602911'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/11/color-schemes-to-prevent-eye-fatigue.html' title='Color schemes to prevent eye fatigue'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-nrSo8FhKFSU/Tq-s3TSThMI/AAAAAAAAAEM/3u7JXqvuDa8/s72-c/solarized.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-1908459524903022981</id><published>2011-11-01T00:59:00.000-07:00</published><updated>2011-11-01T01:10:35.472-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-2d'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-random'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-num-utils'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-rmath'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><title type='text'>New and updated libraries</title><content type='html'>&lt;p&gt;Lately I have been trying to be more organized about updates to my libraries: I always try to keep the master branch on Github in a consistent state for all of them, and merge the development branches for all libraries at the same time.  I have been doing that yesterday, here is a brief summary of the changes.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/tpapp/cl-num-utils"&gt;cl-num-utils&lt;/a&gt; mostly received minor fixes: I cleaned up the accumulator code a bit, and added a few minor convenience functions.  The package now exports &lt;code&gt;median&lt;/code&gt;, which causes a symbol conflict with &lt;a href="http://common-lisp.net/project/alexandria/draft/alexandria.html#Numbers"&gt;alexandria:median&lt;/a&gt; so you need to shadow if you are using both.  Maybe I should ask the developers of Alexandria to make &lt;code&gt;mean&lt;/code&gt;, &lt;code&gt;variance&lt;/code&gt; and &lt;code&gt;median&lt;/code&gt; generic.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/tpapp/lla"&gt;LLA&lt;/a&gt; underwent a medium-scale rewrite: I sanitized the type system (internal types are no longer exposed), cleaned up object creation functions (&lt;code&gt;CLO&lt;/code&gt; replaced with &lt;code&gt;HERMITIAN&lt;/code&gt;, &lt;code&gt;LOWER&lt;/code&gt;, etc), and wrote specialized routines for array sharing which are about 30 times faster than they used to be &amp;mdash; this of course doesn't mean that LLA is now 30x faster, just that they overhead for sharing arrays got a lot smaller.  Since many operations are \(O(n^\alpha), \alpha \geq 2\), this is mostly noticeable for small arrays.  Note that this is still generic CFFI-based code, preliminary tests indicate that implementation-specific tricks could yield array copying code that is 2-5x faster, but currently I have neither the time nor the inclination to write this, because I would rather wait for other parts of LLA to settle down before I micro-optimize.  However, if you find that array copying overhead is critical for you, please let me know and I will see what I can do &amp;mdash; this rewrite was prompted by the benchmarks sent by Robert Brown.
&lt;/p&gt;
&lt;p&gt;
Realizing that implementing special functions in Common Lisp is perhaps not the best use of my time, I decided to use a foreign library for this purpose in &lt;a href="https://github.com/tpapp/cl-random"&gt;cl-random&lt;/a&gt;.  I chose R's standalone math library, with an &lt;a href="http://www.swig.org/"&gt;SWIG&lt;/a&gt;-generated wrapper (it took about 30 minutes to have this library running, SWIG is amazing).  I made the result available as a small standalone library called &lt;a href="https://github.com/tpapp/cl-rmath"&gt;cl-rmath&lt;/a&gt; in case anyone else wants to use it.  I really appreciate that the R developers made this available as a standalone library, it makes my life much easier.  Besides these changes, I only made small changes to cl-random, for example, the univariate normal now has the syntax &lt;code&gt;(r-normal mean variance)&lt;/code&gt; instead of the standard deviation, to be more consistent with the multivariate case.
&lt;/p&gt;
&lt;p&gt;
Finally, it looks like &lt;a href="https://github.com/tpapp/cl-2d"&gt;cl-2d&lt;/a&gt; refuses to &lt;a href="http://tkpapp.blogspot.com/2011/09/is-anyone-using-cl-2d.html"&gt;die&lt;/a&gt;, so I fixed some of the minor bugs that were the result of other libraries moving on.  I am working on a replacement library, but I will probably keep cl-2d updated until the new library is ready.  It amazes me how many people are using cl-2d: I get questions and bug reports all the time.  It is not a bad library, but I wrote it when I was a CL newbie and I hope that I can write a much better one &amp;mdash; we shall see.  In any case, if you are &lt;b&gt;not&lt;/b&gt; using cl-2d, I would recommend that you don't start now.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-1908459524903022981?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/1908459524903022981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/11/new-and-updated-libraries.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1908459524903022981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1908459524903022981'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/11/new-and-updated-libraries.html' title='New and updated libraries'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-7859341138114730579</id><published>2011-09-06T23:36:00.000-07:00</published><updated>2011-09-06T23:37:24.316-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-2d'/><title type='text'>Is anyone using cl-2d?</title><content type='html'>&lt;p&gt;I wrote a Common Lisp plotting library called &lt;a href="https://github.com/tpapp/cl-2d"&gt;cl-2d&lt;/a&gt; in 2009, and I have been using it for my own graphs ever since.  I am currently working on a library that implements the same functionality but with a much more friently interface and a different engine, using &lt;a href="http://www.latex-project.org/"&gt;LaTeX&lt;/a&gt; and &lt;a href="http://pgf.sourceforge.net/"&gt;pgf&lt;/a&gt; to generate the plots instead of &lt;a href="http://cairographics.org/"&gt;cairo&lt;/a&gt;.  This gives me a lot of useful features out of the box, including very nicely formatted formulas if I want to use them in annotations, and it is reasonably fast for my purposes.
&lt;/p&gt;
&lt;p&gt;
I plan to remove the existing cl-2d repository from Github, put up a new one (it is a complete rewrite from scratch, there isn't much sense in carrying around the old source), and recycle the name (for both the package and the library).
&lt;/p&gt;
&lt;p&gt;
I don't think that there is anyone out there using the current version of this library, but in case you are, please let me know soon.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-7859341138114730579?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/7859341138114730579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/09/is-anyone-using-cl-2d.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7859341138114730579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7859341138114730579'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/09/is-anyone-using-cl-2d.html' title='Is anyone using cl-2d?'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-4991094217125153818</id><published>2011-09-02T04:54:00.001-07:00</published><updated>2011-09-05T05:51:22.936-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><title type='text'>Persistent misconceptions about Lisp</title><content type='html'>
&lt;p&gt;I am in the process of implementing (yet another) graphing library Common Lisp, one that would conform to my requirements better (I will blog about it later on).  In order to understand some issues better, I decided to read &lt;a href="http://www.cs.uic.edu/~wilkinson/TheGrammarOfGraphics/GOG.html"&gt;The Grammar of Graphics&lt;/a&gt; by Leland Wilkinson.  The book is very well written and clearly organized, and I think it will turn out to be very useful for what I am doing.  However, I encountered a couple of misconceptions about Lisp in the Introduction.  On page 4, the author claims that
&lt;/p&gt;
&lt;blockquote&gt;

&lt;p&gt;Some languages, like Simula, Smalltalk, and Java, make it easy to implement objects and difficult to implement procedures.  Others, like C++, enable development of both objects and procedures.  And others, like C, Pascal, Ada, BASIC, Algol, Lisp, APL, and FORTRAN, make it difficult (but not impossible) to develop objects.
&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;
&lt;a href="http://www.gigamonkeys.com/book/object-reorientation-classes.html"&gt;O RLY?&lt;/a&gt;  Most users of CLOS find both objects and &lt;a href="http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html"&gt;"procedures"&lt;/a&gt; very easy to use, and at least on par with other OO languages.  Moreover, I don't understand how Lisp ended up in the company of C, which doesn't have any OO whatsoever.
&lt;/p&gt;
&lt;p&gt;
On page 5, we are told that
&lt;/p&gt;
&lt;blockquote&gt;

&lt;p&gt;Lisp is ideal for manipulating lists of words and symbols because it is a list processing language.
&lt;/p&gt;
&lt;/blockquote&gt;


&lt;p&gt;
Strictly speaking, this is true, but Lisp is much more than a list processing language: it is also used to tackle &lt;a href="http://www.cliki.net/Mathematics"&gt;numerical problems&lt;/a&gt; and usually does a very good job.  Compiled code can be very fast, especially with implementations like &lt;a href="http://www.sbcl.org"&gt;SBCL&lt;/a&gt;, and Lisp has a very nice &lt;a href="http://common-lisp.net/project/cffi/"&gt;foreign function interface&lt;/a&gt; library.
&lt;/p&gt;
&lt;p&gt;
That said, from what I have read so far, the book appears to be excellent, and the author is clearly an expert on the topic.  Statements about programming languages are tangential to the book in any case, so I don't understand why the author found it necessary to talk about a language that he is not so familiar with.
&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-4991094217125153818?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/4991094217125153818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/09/persistent-misconceptions-about-lisp.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4991094217125153818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4991094217125153818'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/09/persistent-misconceptions-about-lisp.html' title='Persistent misconceptions about Lisp'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-179837126353698700</id><published>2011-07-21T05:30:00.001-07:00</published><updated>2011-07-21T05:30:37.245-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='library configuration'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><title type='text'>Library configuration in Common Lisp: an example</title><content type='html'>&lt;p&gt;I have been dodging the issue of configuration for &lt;a href="https://github.com/tpapp/lla"&gt;LL&lt;/a&gt;A for a while, but eventually I had to come up with a solution for the &lt;a href="http://tkpapp.blogspot.com/2011/07/lla-reorganization-almost-finished-new.html"&gt;revised version&lt;/a&gt; that I pushed to Github yesterday.
&lt;/p&gt;
&lt;p&gt;
LLA users may need to configure two things: the location and name of libraries that they want to use, and whether LLA should use 64-bit integers to interface with BLAS/LAPACK (this is rarely needed, even on 64-bit platforms, as many implementations still use 32-bit integers).  In the previous versions of LLA, I tried to do this with read-time conditionals (based on &lt;a href="http://www.cliki.net/trivial-features"&gt;trivial-features&lt;/a&gt;) but this was not satisfactory as it is impossible to figure out the list of libraries from nothing but the platform information &amp;mdash; for example, a Linux user could use &lt;a href="http://math-atlas.sourceforge.net/"&gt;ATLAS&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/Math_Kernel_Library"&gt;MKL&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
I read &lt;a href="http://jcsu.jesus.cam.ac.uk/~csr21/papers/features.pdf"&gt;Maintaining Portable Lisp Programs&lt;/a&gt; by Christophe Rhodes and also asked on cl-pro, where I got a lot of good suggestions and decided to follow the &lt;a href="http://article.gmane.org/gmane.lisp.cl-pro/470"&gt;advice&lt;/a&gt; of Pascal Costanza.  This is how configuration works at the moment for LLA:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
The user may define a variable &lt;code&gt;*lla-configuration*&lt;/code&gt; in the &lt;code&gt;CL-USER&lt;/code&gt; package.  The variable should contain a plist of configuration options, eg
&lt;code&gt;:libraries&lt;/code&gt;.  The variable does not need to be bound, and it can be NIL or incomplete: the user only needs to deal with configuration when he wants to override the defaults of the library.  LLA makes an effort to come up with sensible platform-specific defaults.

&lt;/li&gt;
&lt;li&gt;
When loaded/compiled, LLA checks whether &lt;code&gt;cl-user::*lla-configuration*&lt;/code&gt; is bound, and if it is, it uses the corresponding values.  If the variable is not bound or doesn't contain the desired property, a default value is used instead.
&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;
Internally, some features are implemented by pushing symbols like &lt;code&gt;lla::int64&lt;/code&gt; to &lt;code&gt;*features*&lt;/code&gt;.  I have do admit that I didn't even consider the possibility of package qualifiers in read-time conditionals before I read the &lt;a href="file:////usr/share/doc/hyperspec/Issues/iss318_w.htm"&gt;appropriate sections&lt;/a&gt; of the Hyperspec, but in retrospect it makes perfect sense as it helps to avoid name clashes.  LLA also removes its own symbols from &lt;code&gt;*features*&lt;/code&gt; if they don't belong there: this means that you can reload the library with a different configuration without restating your CL image.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-179837126353698700?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/179837126353698700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/07/library-configuration-in-common-lisp.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/179837126353698700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/179837126353698700'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/07/library-configuration-in-common-lisp.html' title='Library configuration in Common Lisp: an example'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-1614938393655533355</id><published>2011-07-20T04:43:00.000-07:00</published><updated>2011-07-20T04:51:01.690-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><title type='text'>LLA reorganization almost finished, new version on Github</title><content type='html'>&lt;p&gt;I have almost completed the reorganization of LLA and merged it to the &lt;a href="https://github.com/tpapp/lla"&gt;main branch&lt;/a&gt; on Github (sorry, no installation via &lt;a href="http://www.quicklisp.org/"&gt;Quicklisp&lt;/a&gt; until the library is fully stable, for the moment you have to check it out from Github).  Make sure that you get the latest dependencies, most importantly &lt;a href="https://github.com/tpapp/cl-num-utils"&gt;cl-num-utils&lt;/a&gt; and &lt;a href="https://github.com/tpapp/let-plus"&gt;let-plus&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This version of LLA boasts a reorganized interface: most importantly, now it works with plain vanilla Common Lisp arrays:
&lt;/p&gt;


&lt;pre class="example"&gt;LLA&amp;gt; (defparameter *a* #2A((1 2) (3 4)))
*A*
LLA&amp;gt; (mm t *a*) ; same as A^T A, but LLA recognizes that the result is Hermitian
#&amp;lt;HERMITIAN-MATRIX 
  10.00000        *
  14.00000 20.00000&amp;gt;
LLA&amp;gt; (elements *)  ; Lisp arrays inside all special matrices
#2A((10.0d0 0.0d0) (14.0d0 20.0d0))
LLA&amp;gt; (svd *a* :thin)
#S(SVD
   :U #2A((-0.40455358483375703d0 0.9145142956773045d0)
          (-0.9145142956773045d0 -0.40455358483375703d0))
   :D #&amp;lt;DIAGONAL 
  5.46499       .
        . 0.36597&amp;gt;
   :VT #2A((-0.5760484367663207d0 -0.817415560470363d0)
           (-0.817415560470363d0 0.5760484367663208d0)))
LLA&amp;gt; (elements (svd-d *)) ; Lisp arrays again
#(5.464985704219043d0 0.3659661906262576d0)
&lt;/pre&gt;


&lt;p&gt;
LLA uses clever tricks to avoid transposing when it can.  Row-major and column-major representations are transposes of each other, and instead of calculating an SVD as
$$A=UDV^T$$
LLA justs calculates
$$A^T={V^T}^T D^T U^T$$
and returns \(U\) as \(V^T\) and vice versa.  Of course transposing cannot be avoided all the time, but it is not needed often and should not impose a large performance penalty.  So LLA can work with row-major Common Lisp arrays natively &amp;mdash; in fact, that's the only array representation it supports.
&lt;/p&gt;
&lt;p&gt;
This version of LLA has a reorganized DSL for BLAS/LAPACK calls which makes it really easy to wrap Fortran functions in general, not just LAPACK/BLAS functions for which it has extensions.  For example, this is how Cholesky factorization is implemented:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(&lt;span style="color: #00ffff;"&gt;defmethod&lt;/span&gt; &lt;span style="color: #87cefa;"&gt;cholesky&lt;/span&gt; ((a hermitian-matrix))
  (let+ ((a (elements a))
         ((a0 a1) (array-dimensions a)))
    (&lt;span style="color: #ffc0cb; font-weight: bold;"&gt;assert&lt;/span&gt; (= a0 a1))
    (lapack-call (&lt;span style="color: #ffa07a;"&gt;"potrf"&lt;/span&gt; (common-float-type a)
                          (make-instance 'cholesky &lt;span style="color: #b0c4de;"&gt;:left-square-root&lt;/span&gt; 
                                         (make-lower-triangular-matrix l)))
                 #\U (&lt;span style="color: #98fb98;"&gt;&amp;amp;integer&lt;/span&gt; a0) (&lt;span style="color: #98fb98;"&gt;&amp;amp;array&lt;/span&gt; a &lt;span style="color: #b0c4de;"&gt;:output&lt;/span&gt; l) (&lt;span style="color: #98fb98;"&gt;&amp;amp;integer&lt;/span&gt; a0) &lt;span style="color: #98fb98;"&gt;&amp;amp;info&lt;/span&gt;)))
&lt;/pre&gt;


&lt;p&gt;
The first two lines are just bookkeeping: the array &lt;code&gt;A&lt;/code&gt; containing the elements of the hermitian (symmetric) matrix (in the lower triangle) is extracted, and its dimensions are examined.  &lt;code&gt;LAPACK-CALL&lt;/code&gt; figures out whether to use &lt;code&gt;SPOTRF&lt;/code&gt;, &lt;code&gt;DPOTRF&lt;/code&gt;, &lt;code&gt;CPOTRF&lt;/code&gt;, &lt;code&gt;ZPOTRF&lt;/code&gt; from the element type of the matrix, allocates memory for atoms (recall that Fortran takes pointers) using the macros, and automatically examines the &lt;code&gt;INFO&lt;/code&gt; parameter at &lt;code&gt;&amp;amp;info&lt;/code&gt; to catch exceptions.  The &lt;code&gt;#\U&lt;/code&gt; in the code suggests that storage is upper-triangular, even though in CL we store elements of the hermitian matrix in the lower triangle: this is because we avoid transposing.  I find that it is really easy to write wrappers to Fortran code using this macro family (there is also a &lt;code&gt;BLAS-CALL&lt;/code&gt; and a &lt;code&gt;LAPACK-CALL-W/QUERY&lt;/code&gt; that queries workspace sizes), and it should be easy to write a &lt;code&gt;FORTRAN-CALL&lt;/code&gt; for general Fortran code, or even a wrapper for C functions that handle arrays.  Let me know if you are interested in any of these, I would be happy to add them or even factor out this part of LLA into another library.
&lt;/p&gt;
&lt;p&gt;
By the way, contrary to what my &lt;a href="http://tkpapp.blogspot.com/2011/06/lla-reorganization-almost-done.html"&gt;previous post on LLA&lt;/a&gt; said, you no longer need the C wrappers in MKL or CLAPACK, so ATLAS or something similar is just fine.  The README has instructions on how to set up these libraries (unless you want to compile your own, a single &lt;code&gt;apt-get install&lt;/code&gt; or similar is enough to satisfy LLA's dependencies) and configure custom library locations.
&lt;/p&gt;
&lt;p&gt;
Even though LLA is now perfectly usable and all the unit tests work just fine, there are still some things left to do:
&lt;/p&gt;&lt;dl&gt;
&lt;dt&gt;Write the array implementation-specific sharing macros.&lt;/dt&gt;&lt;dd&gt;
LLA uses a few macros to make arrays available for foreign functions, and all the wrappers are built around these.  The idea is to avoid copying &lt;a href="http://tkpapp.blogspot.com/2010/05/upgraded-array-element-types-and-pinned.html"&gt;if the implementation supports it&lt;/a&gt;, and otherwise fall back to copying.  I decided to focus my efforts on getting LLA to work again first, and this means that currently all operations fall back to copying, which should entail a slight performance penalty.  I will of course remedy this at some point, first for SBCL and ECL and then for the other distributions, but I am waiting for the rest of LLA to stabilize before I start fiddling with low-level optimizations.
&lt;/dd&gt;
&lt;dt&gt;Eigenvalues/eigenvectors are not yet implemented.&lt;/dt&gt;&lt;dd&gt;
LAPACK's handling of eigenvalues and especially eigenvectors is a mess, and I need to dust off the code that picks out paired eigenvectors.  It should be fairly easy, but I prefer not to add functionality without thorough testing, so currently I am postponing this until someone needs it (just drop me a line).
&lt;/dd&gt;
&lt;/dl&gt;


&lt;p&gt;
Also, even though I wrote a lot of unit tests, it is of course possible (and probable) that LLA has bugs.  Please report them on Github.
&lt;/p&gt;
&lt;p&gt;
I would like to thank all users of LLA for helpful suggestions and for the gentle nudging I received during LLA's reorganization.  I believe that LLA fills an important niche, and I will continue to work on it.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-1614938393655533355?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/1614938393655533355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/07/lla-reorganization-almost-finished-new.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1614938393655533355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1614938393655533355'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/07/lla-reorganization-almost-finished-new.html' title='LLA reorganization almost finished, new version on Github'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-3370467043183144846</id><published>2011-07-14T08:16:00.000-07:00</published><updated>2011-07-14T08:16:23.853-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='e-books DRM Kindle indie'/><title type='text'>Why I only buy e-books from indie publishers</title><content type='html'>&lt;p&gt;Nikodemus Siivola blogged about the &lt;a href="http://random-state.net/log/3519640145.html"&gt;$2 surcharge&lt;/a&gt; Amazon extracts from Kindle customers outside the US.  I use my Kindle every day, and I buy e-books to read on a regular basis, spending around $10-30 a month (depending on how much time I have for reading).  I have owned a Kindle for almost a year now, but I didn't know about this surcharge: I guess the reason for this is that none of the money I spent on e-books went to Amazon.
&lt;/p&gt;
&lt;p&gt;
There are two reasons for this: their &lt;i&gt;non-competitive pricing&lt;/i&gt; and &lt;i&gt;DRM&lt;/i&gt;.  First, I am reluctant to pay more for an e-book than I would for a paperback, yet I frequently saw e-books on Amazon that cost more than their paperback versions.  I understand that Amazon is trying to extract economic rents using its strong position in this market, but I would feel like an idiot if I participated in this scheme.
&lt;/p&gt;
&lt;p&gt;
Regarding DRM: I like my Kindle very much, but I think that in the long run e-book readers will become even more of a commodity (like laptops or cell phones), and I don't wish my e-book collection to be tied to Amazon.  Call me old-fashioned, but I do want to own the content I pay for, especially if I paid almost as much as I would pay for a hardcopy.  So I only buy DRM-free books.
&lt;/p&gt;
&lt;p&gt;
I mostly read literature on my Kindle.  I buy quite a bit of sci-fi from &lt;a href="http://www.webscription.net/"&gt;Baen books&lt;/a&gt; &amp;mdash; they also have a lot of books available for free, knowing full well that good sci-fi is addictive for some people anyway, but they don't exploit this: most of their books sell for $5-6.  I haven't head a chance to check out &lt;a href="http://drmfree.calibre-ebook.com"&gt;Calibre's DRM-free book store&lt;/a&gt;, but it looks very promising.
&lt;/p&gt;
&lt;p&gt;
I think that unless Amazon changes its pricing policy and considers offering DRM-free content, there is very little chance that I will buy anything from them.  If you know some indie authors or publishers who sell reasonably priced DRM-free e-books, I would be interested in hearing about them.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-3370467043183144846?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/3370467043183144846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/07/why-i-only-buy-e-books-from-indie.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3370467043183144846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3370467043183144846'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/07/why-i-only-buy-e-books-from-indie.html' title='Why I only buy e-books from indie publishers'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-5656459728374317540</id><published>2011-07-12T03:59:00.000-07:00</published><updated>2011-07-12T03:59:42.262-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='social network sites'/><category scheme='http://www.blogger.com/atom/ns#' term='linkedin'/><title type='text'>LinkedIn: an obnoxious spam engine</title><content type='html'>&lt;p&gt;I have to admit that I don't see the point of so-called social networking sites, but I recognize the possibility that some people may find them useful, and I am just not one of them.  Nevertheless, I still fail to see why random people I have never met want to add me as a contact.  I get invitations from these people on LinkedIn almost daily, and to make it worse, LinkedIn then sends me &lt;i&gt;reminders&lt;/i&gt; about them.  Note that &lt;b&gt;I am not even registered on their damn site&lt;/b&gt;.  I don't have a profile, and I have no intention of creating one.
&lt;/p&gt;
&lt;p&gt;
Which presents another problem: I couldn't find a way of opting out from these invitations &lt;i&gt;without creating a profile&lt;/i&gt;.  Clever, isn't it?  They send you spam, and then they are trying to sucker people into registering to stop spam.  I could just start marking these messages spam, but I think that my spam filter would take a while to learn this, and in any case, I don't want to add noise to the Bayesian model just to create false positives for relevant e-mail.  The cleanest solution I found is putting the whole linkedin.com domain on my blacklist.
&lt;/p&gt;
&lt;p&gt;
I want to emphasize that this is a rare distinction: with spam filters getting so clever (thank you, Gmail!), I haven't had to manually blacklist a sender in years.  Congratulations are in order: dear LinkedIn, you are a really obnoxious engine for spam!  I sincerely hope that you vanish to oblivion soon.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5656459728374317540?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5656459728374317540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/07/linkedin-obnoxious-spam-engine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5656459728374317540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5656459728374317540'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/07/linkedin-obnoxious-spam-engine.html' title='LinkedIn: an obnoxious spam engine'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-4542006191792489949</id><published>2011-07-11T08:21:00.000-07:00</published><updated>2011-07-11T08:21:42.685-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Goodbye Ubuntu, hello Debian</title><content type='html'>&lt;div id="outline-container-1" class="outline-3"&gt;
&lt;h3 id="sec-1"&gt;My road to Ubuntu&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-1"&gt;


&lt;p&gt;
I have started using Linux around 1998.  I remember that I wanted to try out several distributions before settling on the one the "best" one, but I had a dial-up connection (28kbps, if I remember correctly) and downloading all of them seemed infeasible, so I mail-ordered a set of CDs that contained &lt;a href="http://www.redhat.com/"&gt;Red Hat&lt;/a&gt;, &lt;a href="http://www.slackware.com/"&gt;Slackware&lt;/a&gt; and &lt;a href="http://www.debian.org"&gt;Debian&lt;/a&gt;.  I think I decided on Debian because I liked the clean and transparent package management system, especially &lt;a href="http://en.wikipedia.org/wiki/Advanced_Packaging_Tool"&gt;APT&lt;/a&gt; which seemed way ahead of other distributions at that time.  Linux became my primary OS within a few months: even though it didn't have a fraction of the tools that are available today, it had everything I needed.
&lt;/p&gt;
&lt;p&gt;
A lot happened in the Linux world since then.  I don't know when (if?) Linux "conquered" the desktop, but in 2003 it became mature enough that I installed Linux (Debian, of course) on my parent's desktop.  Neither of my parents are very computer-savvy, but they also found Linux much nicer than Windows.  I think what mattered the most to them is its stability: I would update the software once in a while, test that everything was working (and fix it when it didn't), but in the meantime, the system was rock-solid.  This was important as I no longer lived in the same city, so I couldn't just drop by to fix computer problems on a short notice, which I had to do with Windows.
&lt;/p&gt;
&lt;p&gt;
When they got another computer (I think it was around 2005), I replaced Debian with Ubuntu, figuring that it would provide a more polished user experience, and I was pleased with the result.  I installed Ubuntu on all computers that family members asked me to help with, and in 2009, I installed Ubuntu on a new laptop I got.  It &lt;b&gt;was&lt;/b&gt; a bit more polished than Debian, especially when it came to setup things like printers and network drives.  I knew how to do those things via the relevant config files, but I appreciated the GUI.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-3"&gt;
&lt;h3 id="sec-2"&gt;Why I moved back to Debian&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2"&gt;


&lt;p&gt;
I think that I like Linux because it allows me to concentrate on my work: I came to accept that sometimes setting things up required a bit of tweaking, but &lt;i&gt;once I configured something, it would work exactly the way I liked it&lt;/i&gt;.  I welcome changes if they make sense (eg a feature extension), but I don't see the point of gratuitous ones.  In retrospect, I should have considered the &lt;a href="http://lifehacker.com/5500577/move-ubuntus-window-buttons-back-to-the-right"&gt;moving of window buttons&lt;/a&gt; a warning sign, especially when Mark Shuttleworth &lt;a href="https://bugs.launchpad.net/ubuntu/+source/light-themes/+bug/532633/comments/564"&gt;refused to move them back&lt;/a&gt; despite popular demand.  The fix was easy, but the whole move was totally unnecessary and resulted in a lot of confusion: until I fixed it (I really &lt;i&gt;did&lt;/i&gt; give it a try for a few days), my desktop just felt like a car with the gas and brake pedals interchanged.
&lt;/p&gt;
&lt;p&gt;
The &lt;a href="http://www.pcworld.com/businesscenter/article/226940/natty_narwhal_the_first_linux_for_newbies.html"&gt;controversy surrounding Unity&lt;/a&gt; was the real eye-opener for me.  I  dist-upgraded Ubuntu on my parents current computer (a perfectly good desktop for office work, around 2 years old) and was informed that the system doesn't have the resources to run the damn thing.  I tried it out on my laptop briefly, and realized that all that glitz and glitter is unnecessary and a waste of resources (most importantly battery power), and Ubuntu was trying to force yet another gratuitous UI change on its users.  I backed up my data, wiped my HD, and within an hour, I was back to good old Debian.  Which still rocks.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-3"&gt;
&lt;h3 id="sec-3"&gt;Why Debian is perfect for me&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-3"&gt;


&lt;p&gt;
In order to answer that question, here is a sample of the desktop software that I use (of course I use a lot of other programs, eg &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; or &lt;a href="http://www.sbcl.org"&gt;SBCL&lt;/a&gt;, but there is no purpose in enumerating all of them):
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;desktop environment&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://www.xfce.org/"&gt;XFCE&lt;/a&gt; (with some Gnome applets in the panel)
&lt;/dd&gt;
&lt;dt&gt;e-mail&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://www.mutt.org/"&gt;mutt&lt;/a&gt;, &lt;a href="http://offlineimap.org/"&gt;offlineimap&lt;/a&gt;, &lt;a href="http://msmtp.sourceforge.net/"&gt;msmtp&lt;/a&gt;
&lt;/dd&gt;
&lt;dt&gt;shell&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://zsh.sourceforge.net/"&gt;zsh&lt;/a&gt;, running under &lt;a href="http://www.gnu.org/s/screen/"&gt;screen&lt;/a&gt; in &lt;a href="http://extragear.kde.org/apps/yakuake/"&gt;yakuake&lt;/a&gt; (with the &lt;a href="http://kde-look.org/content/show.php/Tango+for+Konsole+Yakuake+(KDE4)?content=83498"&gt;Tango color scheme&lt;/a&gt; &amp;mdash; I got used to that from Gnome)
&lt;/dd&gt;
&lt;dt&gt;editing&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://www.gnu.org/software/emacs/"&gt;emacs&lt;/a&gt;, &lt;a href="http://www.tug.org/texlive/"&gt;TeX Live&lt;/a&gt;, &lt;a href="http://www.gnu.org/software/auctex/"&gt;AUCTeX&lt;/a&gt;, &lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt;, &amp;hellip;
&lt;/dd&gt;
&lt;dt&gt;browser&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://www.google.com/chrome/"&gt;chrome&lt;/a&gt;
&lt;/dd&gt;
&lt;dt&gt;password manager&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://oss.codepoet.no/revelation/wiki/Home"&gt;Revelation&lt;/a&gt;
&lt;/dd&gt;
&lt;dt&gt;newsfeeds&lt;/dt&gt;&lt;dd&gt;
&lt;a href="http://liferea.sourceforge.net/"&gt;Liferea&lt;/a&gt;
&lt;/dd&gt;
&lt;/dl&gt;


&lt;p&gt;
This is a pretty eclectic mix with no overall GUI concept &amp;mdash; for example, it has programs from Gnome and KDE &amp;mdash; but I have come to like each of these programs and they work very well for me.  &lt;a href="http://www.debian.org/releases/testing/"&gt;Debian testing&lt;/a&gt; has pretty recent releases for all of them, and more importantly, the idea of Debian developers forcing any particular choice on how &lt;i&gt;I&lt;/i&gt; set up my desktop never even comes up at any point.  They provide excellent software, take care of packaging new releases and fixing bugs, but I doubt that any of them would even entertain the idea of pushing some wacky &lt;i&gt;desktop du jour&lt;/i&gt; concept on their users.  I think that they have better things to do with their time, including maintaining the best Linux distro out there, and that's the way I like it.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-4" class="outline-3"&gt;
&lt;h3 id="sec-4"&gt;The icing on the cake&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-4"&gt;


&lt;p&gt;
Compared to my previous desktop (which was plain vanilla Gnome, &lt;a href="https://wiki.ubuntu.com/MaverickMeerkat"&gt;Ubuntu/Maverick&lt;/a&gt;), the above setup appears to be much less resource intensive.  I have plenty of RAM and CPU power, but I noticed that my laptop gives me about 20% more battery time than it used to.  I cannot help but love Debian.  It is good to be back!
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-4542006191792489949?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/4542006191792489949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/07/goodbye-ubuntu-hello-debian.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4542006191792489949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4542006191792489949'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/07/goodbye-ubuntu-hello-debian.html' title='Goodbye Ubuntu, hello Debian'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-6094676138765494351</id><published>2011-06-27T06:30:00.000-07:00</published><updated>2011-06-27T06:30:55.468-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><title type='text'>LLA reorganization almost done</title><content type='html'>&lt;div id="content"&gt;

&lt;p&gt;As many of you have noticed, the &lt;a href="http://github.com/tpapp/lla"&gt;Lisp Linear Algebra&lt;/a&gt; library is currently undergoing a major reorganization.  The &lt;a href="https://github.com/tpapp/lla/tree/rewriting"&gt;new branch&lt;/a&gt; is incomplete, but what is there is perfectly is usable and passes all unit tests.  The purpose of this post is to give a preview of changes and invite LLA users to experiment with the new version before it is "released".
&lt;/p&gt;

&lt;div id="outline-container-1" class="outline-3"&gt;
&lt;h3 id="sec-1"&gt;Why the new version? &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-1"&gt;


&lt;p&gt;
Also relying on &lt;a href="http://www.netlib.org/lapack/"&gt;LAPACK&lt;/a&gt;, the previous version of LLA used a column-major representation.  This meant that even though matrices were represented using Common Lisp arrays (in particular, vectors) under the hood, they had to be wrapped to indicate that they were column-major.  However, less then a year ago the LAPACK Team finally standardized the &lt;a href="http://www.netlib.org/lapack/#_standard_c_language_apis_for_lapack"&gt;C interface&lt;/a&gt; for the library, which now provides row-major matrices.  This means that you can use Common Lisp arrays in LLA:
&lt;/p&gt;


&lt;pre class="example"&gt;(let ((a #2A((1 2)
             (3 4)))
      (b #(5 7)))
  (solve a b))
&lt;/pre&gt;


&lt;p&gt;
which computes \(A^{-1}b\), evaluating to
&lt;/p&gt;


&lt;pre class="example"&gt;#(-3.0d0 4.0d0)
&lt;/pre&gt;


&lt;p&gt;
Note that the result contains double floats instead of integers: in fact, in implementations that support it, the element type of the array will be double-float.
&lt;/p&gt;
&lt;p&gt;
This is because most LLA operations work like this:
&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Determine the narrowest common element type of each argument.  Unless the element type of the array is something specific that LLA can recognize (eg single and double floats and their complex versions), LLA needs to traverse the array, which costs a bit in terms of speed.  Use arrays with specialized element types to avoid this cost.  Integers and rationals are converted to floats (you can control which, double is the default).
&lt;/li&gt;
&lt;li&gt;Determine the narrowest common element type of the pertinent arguments.  For example, in the code above, LLA decided to use double floats, which also determines the element type.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
The use of Common Lisp arrays made LLA much more transparent without any noticable overhead, especially if you use arrays that have the appropriate element types (instead of &lt;code&gt;T&lt;/code&gt;).  Even if you don't, LLA functions will return arrays that have specialized element types, so if you chain LLA operations, your code should be efficient without any particular effort.
&lt;/p&gt;
&lt;p&gt;
Hermitian and triangular matrices are now wrappers around simple two-dimensional arrays.  You should use &lt;code&gt;as-array&lt;/code&gt; to convert to a dense matrix.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-3"&gt;
&lt;h3 id="sec-2"&gt;Required libraries &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2"&gt;


&lt;p&gt;
You need an implementation of LAPACK that provides the C interface.  Currently, the two available choices are &lt;a href="http://www.netlib.org/lapack/lapacke.tgz"&gt;LAPACKE&lt;/a&gt; and Intel's &lt;a href="http://software.intel.com/en-us/articles/intel-mkl/"&gt;MKL&lt;/a&gt;.  I have been using the latter to develop the new version of LLA, so I don't have instructions on how to compile and set up LAPACKE with other libraries.  If you figure it out, please write it up and I will post it in the README file of LLA.
&lt;/p&gt;
&lt;p&gt;
If you install MKL on Linux, all you have to do is tell the linker where the libraries are: for example, all I had to do was create the file &lt;code&gt;/etc/ld.so.conf.d/mkl.conf&lt;/code&gt; with contents
&lt;/p&gt;


&lt;pre class="example"&gt;/opt/intel/mkl/lib/intel64
/opt/intel/composerxe/lib/intel64
&lt;/pre&gt;


&lt;p&gt;
and run &lt;code&gt;ldconfig&lt;/code&gt;.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-3"&gt;
&lt;h3 id="sec-3"&gt;Portability &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-3"&gt;


&lt;p&gt;
LLA uses CFFI, and should be perfectly portable.  However, implementations that don't support arrays with element types &lt;code&gt;single-float&lt;/code&gt;, &lt;code&gt;double-float&lt;/code&gt;, &lt;code&gt;(complex single-float)&lt;/code&gt; and &lt;code&gt;(complex double-float)&lt;/code&gt; will suffer a performance penalty because LLA has to check the array elements to determine the narrowest type.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-4" class="outline-3"&gt;
&lt;h3 id="sec-4"&gt;State of the new version &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-4"&gt;


&lt;p&gt;
Everything works except eigenvalues and singular value decompositions.  Drop me a line if you are using the new version and need either one of those, I am happy to implement them &amp;mdash; it should be relatively easy, but I have kept features to the minimum while the library is in flux.
&lt;/p&gt;
&lt;p&gt;
In principle, LLA should be clever enough to avoid copying of arrays when possible (ie no type conversion is necessary and the implementation supports foreign arrays &amp;mdash; most of them &lt;a href="http://tkpapp.blogspot.com/2010/05/upgraded-array-element-types-and-pinned.html"&gt;should&lt;/a&gt;), but currently I am using the CFFI backend for testing.
&lt;/p&gt;
&lt;p&gt;
As always, feedback, bug reports and suggestions are very welcome.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="postamble"&gt;
&lt;a href="http://validator.w3.org/check?uri=referer"&gt;Validate XHTML 1.0&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-6094676138765494351?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/6094676138765494351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/06/lla-reorganization-almost-done.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6094676138765494351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6094676138765494351'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/06/lla-reorganization-almost-done.html' title='LLA reorganization almost done'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-8407038028804388726</id><published>2011-05-23T22:48:00.000-07:00</published><updated>2011-05-23T22:48:57.723-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='let-plus'/><title type='text'>Introducing LET+, a destructuring extension of LET*</title><content type='html'>&lt;div id="content"&gt;

&lt;div id="outline-container-1" class="outline-2"&gt;
&lt;h2 id="sec-1"&gt;Why &lt;b&gt;another&lt;/b&gt; destructuring library? &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;


&lt;p&gt;
This Common Lisp library extends the syntax of &lt;code&gt;let*&lt;/code&gt;.  In that
respect it is pretty similar to other destructuring libraries, most
importantly Gary King's excellent &lt;a href="http://common-lisp.net/project/metabang-bind/"&gt;metabang-bind&lt;/a&gt;.  I have been using
the latter for years now, but at some point I decided to write a
library of my own, aiming for a cleaner syntax, more concise
implementation and a more consistent interface (whether I have
succeeded is of course a matter of judgement &amp;mdash; try &lt;a href="http://common-lisp.net/project/metabang-bind/"&gt;metabang-bind&lt;/a&gt; to
see if you like it better).
&lt;/p&gt;
&lt;p&gt;
This library differs from &lt;a href="http://common-lisp.net/project/metabang-bind/"&gt;metabang-bind&lt;/a&gt; in the following ways:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Placeholder macros like &lt;code&gt;&amp;amp;slots&lt;/code&gt;, mainly for providing editor hints
(completion, eg syntax reminders in the Emacs status bar with
SLIME, displaying of arguments, etc).

&lt;/li&gt;
&lt;li&gt;
More consistent naming of destructuring forms.  In particular, when
both read-write and read-only forms are available the latter always
have the &lt;code&gt;-r/o&lt;/code&gt; suffix

&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;flet&lt;/code&gt; and &lt;code&gt;&amp;amp;labels&lt;/code&gt; resemble the Common Lisp syntax more closely.

&lt;/li&gt;
&lt;li&gt;
The code is extremely simple (&amp;lt; 300 loc, not counting unit tests),
and the library should be easier to extend.
&lt;/li&gt;
&lt;/ol&gt;


&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-2"&gt;
&lt;h2 id="sec-2"&gt;Examples &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;


&lt;p&gt;
Lists are destructured unless recognized as something else (values
mapping to &lt;code&gt;NIL&lt;/code&gt; are ignored):
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(let+ (((a (b &lt;span style="color: #98fb98;"&gt;&amp;amp;optional&lt;/span&gt; (c 3)) nil &lt;span style="color: #98fb98;"&gt;&amp;amp;key&lt;/span&gt; (d 1 d?)) '(1 (2) 7 &lt;span style="color: #b0c4de;"&gt;:d&lt;/span&gt; 4)))
  (list a b c d d?))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 2 3 4 T)
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
Slots and accessors have a syntax similar to &lt;code&gt;with-slots&lt;/code&gt;:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(&lt;span style="color: #00ffff;"&gt;defclass&lt;/span&gt; &lt;span style="color: #98fb98;"&gt;foo-class&lt;/span&gt; ()
  ((a &lt;span style="color: #b0c4de;"&gt;:accessor&lt;/span&gt; a &lt;span style="color: #b0c4de;"&gt;:initarg&lt;/span&gt; &lt;span style="color: #b0c4de;"&gt;:a&lt;/span&gt;)
   (b &lt;span style="color: #b0c4de;"&gt;:accessor&lt;/span&gt; b-accessor &lt;span style="color: #b0c4de;"&gt;:initarg&lt;/span&gt; &lt;span style="color: #b0c4de;"&gt;:b&lt;/span&gt;)))

(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;slots&lt;/span&gt; a (my-b b)) (make-instance 'foo-class &lt;span style="color: #b0c4de;"&gt;:a&lt;/span&gt; 1 &lt;span style="color: #b0c4de;"&gt;:b&lt;/span&gt; 2)))
  (list a my-b))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 2)
&lt;/span&gt;
(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;accessors&lt;/span&gt; a (b b-accessor)) (make-instance 'foo-class &lt;span style="color: #b0c4de;"&gt;:a&lt;/span&gt; 1 &lt;span style="color: #b0c4de;"&gt;:b&lt;/span&gt; 2)))
  (list a b))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 2)
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
Slots in structures can be accessed by giving the &lt;code&gt;conc-name&lt;/code&gt;:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(&lt;span style="color: #00ffff;"&gt;defstruct&lt;/span&gt; &lt;span style="color: #98fb98;"&gt;foo-struct&lt;/span&gt; c d)
(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;structure&lt;/span&gt; foo-struct- c (my-d d)) (make-foo-struct &lt;span style="color: #b0c4de;"&gt;:c&lt;/span&gt; 3 &lt;span style="color: #b0c4de;"&gt;:d&lt;/span&gt; 4)))
  (list c my-d))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (3 4)
&lt;/span&gt;&lt;/pre&gt;


&lt;p&gt;
but if you use &lt;code&gt;defstruct+&lt;/code&gt; to define your structure, you
automatically get a corresponding deconstructing form:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(defstruct+ interval left right)

(let+ ((interval (make-interval &lt;span style="color: #b0c4de;"&gt;:left&lt;/span&gt; 1 &lt;span style="color: #b0c4de;"&gt;:right&lt;/span&gt; 2))
       ((&lt;span style="color: #98fb98;"&gt;&amp;amp;interval&lt;/span&gt; left right) interval))
  (incf right 10)
  interval)  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; #S(INTERVAL :LEFT 1 :RIGHT 12)
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
Multiple values are also supported:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;values&lt;/span&gt; a nil b) (values 1 2 3)))
  (list a b))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 3)
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
You can access array elements in many different ways:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(let+ ((#(a nil b) (vector 1 2 3)))
  (list a b))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 3)
&lt;/span&gt;
(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;array-elements&lt;/span&gt; (a 0 1)
                         (b 2 0))
        #2A((0 1)
            (2 3)
            (4 5))))
  (list a b))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; (1 4)
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
You can use &lt;code&gt;&amp;amp;flet&lt;/code&gt; (and &lt;code&gt;&amp;amp;labels&lt;/code&gt;, if the function needs to refer to
itself) to write functions:
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;(let+ (((&lt;span style="color: #98fb98;"&gt;&amp;amp;flet&lt;/span&gt; add2 (x)
          (+ x 2))))
  (add2 5))  &lt;span style="color: #ff7f24;"&gt;; &lt;/span&gt;&lt;span style="color: #ff7f24;"&gt;=&amp;gt; 7
&lt;/span&gt;&lt;/pre&gt;



&lt;p&gt;
&lt;code&gt;&amp;amp;plist&lt;/code&gt; and &lt;code&gt;&amp;amp;hash-tables&lt;/code&gt; allow access to elements property lists
and hash tables.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-2"&gt;
&lt;h2 id="sec-3"&gt;Read-only forms &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;


&lt;p&gt;
All of the &lt;code&gt;&amp;amp;...&lt;/code&gt; forms have a read-only version, eg &lt;code&gt;&amp;amp;slots-r/o&lt;/code&gt;.
With these, the values are read at the beginning, and you can modify
them without modifying the original structure.  Read-only forms may
also give you a slight increase in speed, and promote better style by
indicating that you are not modifying the original structure.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-4" class="outline-2"&gt;
&lt;h2 id="sec-4"&gt;How to get it &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-4"&gt;


&lt;p&gt;
The library is a available on &lt;a href="https://github.com/tpapp/let-plus"&gt;Github&lt;/a&gt;, under the &lt;a href="http://www.boost.org/users/license.html"&gt;Boost Software License (Version 1.0)&lt;/a&gt;.  The README file there serves as the documentation, see
the source code and unit tests for mode details.  As always, bug
reports and suggestions are welcome.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="postamble"&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-8407038028804388726?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/8407038028804388726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2011/05/introducing-let-destructuring-extension.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8407038028804388726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8407038028804388726'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2011/05/introducing-let-destructuring-extension.html' title='Introducing LET+, a destructuring extension of LET*'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-5690195345533732605</id><published>2010-10-06T09:23:00.000-07:00</published><updated>2010-10-06T09:24:46.569-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-sparsematrix'/><title type='text'>The status of cl-sparsematrix</title><content type='html'>&lt;p&gt;In 2008, I had to solve some linear equations of the form &lt;code&gt;Ax=b&lt;/code&gt;,
where &lt;code&gt;A&lt;/code&gt; was a sparse matrix (usually a design matrix for B-splines).
I wrote up a library called &lt;code&gt;cl-sparsematrix&lt;/code&gt; in one afternoon, and
put it on the web.
&lt;/p&gt;
&lt;p&gt;
This was &lt;b&gt;not&lt;/b&gt; a sophisticated library.  It did three very basic
things: it helped construct a sparse matrix using a hash-table, had a
function to pack that up in &lt;a href="http://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_.28CSC_or_CCS.29"&gt;CSC&lt;/a&gt; format, and finally, a function to
call &lt;a href="http://www.cise.ufl.edu/research/sparse/umfpack/"&gt;UMFpack&lt;/a&gt; via &lt;a href="http://common-lisp.net/project/cffi/"&gt;CFFI&lt;/a&gt; to solve the equation mentioned above.  This was
it.  It worked fine for what I wanted to use it, but it was not a
sophisticated sparse matrix library.
&lt;/p&gt;
&lt;p&gt;
I didn't have a need for sparse matrices ever since, and the library
succumbed to bit rot: some other libraries it depended on moved on,
quite substantially in some cases, and now it doesn't even load
cleanly.  But I still get a few e-mails every month asking about this
library.  So apparently there is a need in the CL community for a
sparse matrix library.  I have no time to clean it up at the moment,
and you are probably better off writing your own.  &lt;b&gt;The library is no longer available online&lt;/b&gt;, because it doesn't work and I don't want to mislead people who are looking for a sparse matrix library.
&lt;/p&gt;
&lt;p&gt;
When &lt;a href="http://github.com/tpapp/lla"&gt;LLA&lt;/a&gt; is finalized, I will include sparse matrix functionality at
some point.  But LLA is undergoing (yet another) major reorganization
now &amp;mdash; I think I finally figured out how to interface native Lisp
arrays to &lt;a href="http://www.netlib.org/lapack/"&gt;LAPACK&lt;/a&gt; in the implementations that support pinned arrays.
So sparse matrices are not on the immediate horizon.  Unless, of
course, I need to solve sparse systems again, and hack up yet another
quick-and-dirty solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5690195345533732605?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5690195345533732605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2010/10/status-of-cl-sparsematrix.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5690195345533732605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5690195345533732605'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2010/10/status-of-cl-sparsematrix.html' title='The status of cl-sparsematrix'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-1883478182536140504</id><published>2010-05-30T11:08:00.000-07:00</published><updated>2010-05-30T11:08:11.324-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-num-utils'/><category scheme='http://www.blogger.com/atom/ns#' term='array indexing'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><title type='text'>Sub-array indexing</title><content type='html'>&lt;p&gt;One of the things I have been missing in CL was convenient indexing
for sub-arrays.  Languages like &lt;a href="http://www.r-project.org"&gt;R&lt;/a&gt; and &lt;a href="http://www.gnu.org/software/octave/"&gt;Octave&lt;/a&gt; all have convenient
sub-array indexing.  I have experimented with various designs before
(some of them I made public, eg &lt;a href="http://github.com/blindglobe/affi-lisp-matrix"&gt;AFFI&lt;/a&gt; and &lt;a href="http://github.com/tpapp/xarray"&gt;xarray&lt;/a&gt;), but none of them
were entirely satisfactory and I kept searching for new solutions.
&lt;/p&gt;
&lt;p&gt;
This is primarily an issue of syntactic convenience: I want to be able
to select elements from arrays without writing (nested) loops.  I also
want to be able to copy elements from arrays to other arrays,
similarly selected.  Speed is welcome, but at this stage it is
secondary: so far, profiling indicates that these operations comprise
a tiny fraction of execution time in my programs, but having the
ability to capture operations using (sub)arrays is an enormous
timesaver and an invaluable semantic abstraction.
&lt;/p&gt;

&lt;div id="outline-container-1" class="outline-2"&gt;
&lt;h2 id="sec-1"&gt;Introduction to &lt;code&gt;sub&lt;/code&gt; &lt;/h2&gt;
&lt;div id="text-1"&gt;


&lt;p&gt;
My latest attempt at tackling this problem is the generic function
&lt;code&gt;sub&lt;/code&gt; in my &lt;a href="http://github.com/tpapp/cl-num-utils"&gt;cl-num-utils&lt;/a&gt; library (BTW, this library is the successor
of my earlier &lt;a href="http://github.com/tpapp/cl-numlib"&gt;cl-numlib&lt;/a&gt;, which is now deprecated, all useful
functionality will end up in other libraries, eventually).  The syntax
is as follows: &lt;code&gt;(sub object &amp;amp;rest ranges)&lt;/code&gt;.  Each &lt;b&gt;range&lt;/b&gt; is either a
&lt;code&gt;fixnum&lt;/code&gt; (selecting a single index), &lt;code&gt;(cons start end)&lt;/code&gt; (selecting
indexes in that range, excluding &lt;code&gt;end&lt;/code&gt; as is usually done for CL
library functions), &lt;code&gt;t&lt;/code&gt; for all indexes, and finally, a vector of
fixnums for anything else.
&lt;/p&gt;
&lt;p&gt;
Let's see some examples:
&lt;/p&gt;


&lt;pre class="example"&gt;
CLNU&amp;gt; (defparameter *a* #2A((1 2 3 4) (5 6 7 8) (9 10 11 12)))
*A*
CLNU&amp;gt; *a*
#2A((1 2 3 4) (5 6 7 8) (9 10 11 12))
CLNU&amp;gt; (sub *a* 1 t) ; second row
#(5 6 7 8)
CLNU&amp;gt; (sub *a* '(1 . 2) t) ; second row as matrix
#2A((5 6 7 8))
&lt;/pre&gt;



&lt;p&gt;
Notice how a single fixnum will drop that dimension (making a vector
from a matrix), while selecting the same row with a &lt;code&gt;cons&lt;/code&gt; doesn't.
&lt;/p&gt;
&lt;p&gt;
For all other cases, you can use vectors:
&lt;/p&gt;


&lt;pre class="example"&gt;
CLNU&amp;gt; (sub *a* t #(0 3)) ; first and last columns
#2A((1 4) (5 8) (9 12))
CLNU&amp;gt; (sub *a* t #(3 0)) ; last and first columns
#2A((4 1) (8 5) (12 9))
&lt;/pre&gt;




&lt;p&gt;
You can also use negative numbers for indexes: if &lt;code&gt;(minusp index)&lt;/code&gt;, it
will select the column &lt;code&gt;(- dimensions index)&lt;/code&gt;:
&lt;/p&gt;


&lt;pre class="example"&gt;
CLNU&amp;gt; (sub *a* -1 t) ; last row
#(9 10 11 12)
CLNU&amp;gt; (sub *a* #(-2 -1) #(-2 -1)) ; bottom right 2x2 matrix
#2A((7 8) (11 12))
&lt;/pre&gt;




&lt;p&gt;
Finally, &lt;code&gt;0&lt;/code&gt; in a &lt;code&gt;cons&lt;/code&gt; corresponds to the largest possible index in
that dimension:
&lt;/p&gt;


&lt;pre class="example"&gt;
CLNU&amp;gt; (sub *a* '(-2 . 0) t) ; last two rows
#2A((5 6 7 8) (9 10 11 12))
&lt;/pre&gt;




&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-2"&gt;
&lt;h2 id="sec-2"&gt;Setting subarrays &lt;/h2&gt;
&lt;div id="text-2"&gt;


&lt;p&gt;
&lt;code&gt;sub&lt;/code&gt; can also be used with &lt;code&gt;setf&lt;/code&gt;:
&lt;/p&gt;


&lt;pre class="example"&gt;
CLNU&amp;gt; *a*
#2A((1 2 3 4) (5 6 7 8) (9 10 11 12))
CLNU&amp;gt; (setf (sub *a* 1 t) #(-1 -2 -3 -4)) ; replace second row
#(-1 -2 -3 -4)
CLNU&amp;gt; *a*
#2A((1 2 3 4) (-1 -2 -3 -4) (9 10 11 12))
CLNU&amp;gt; (setf (sub *a* 2 t) (map 'vector #'+ (sub *a* 0 t) (sub *a* 1 t)))
#(0 0 0 0)
CLNU&amp;gt; *a*
#2A((1 2 3 4) (-1 -2 -3 -4) (0 0 0 0))
&lt;/pre&gt;




&lt;p&gt;
Note that the ranks have to be equal, make sure that you keep/drop
dimensions as needed.
&lt;/p&gt;

&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-2"&gt;
&lt;h2 id="sec-3"&gt;Macros for implementing &lt;code&gt;sub&lt;/code&gt; &lt;/h2&gt;
&lt;div id="text-3"&gt;


&lt;p&gt;
In &lt;code&gt;cl-num-utils&lt;/code&gt;, you also find the macro &lt;code&gt;with-range-indexing&lt;/code&gt;,
which preprocesses the range arguments and implements an internal
counter for row-major indexing.  For example, &lt;code&gt;sub&lt;/code&gt; for arrays is
implemented as
&lt;/p&gt;


&lt;pre class="src src-lisp"&gt;
(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;sub&lt;/span&gt; ((array array) &lt;span class="org-type"&gt;&amp;amp;rest&lt;/span&gt; ranges)
           (&lt;span class="org-keyword"&gt;declare&lt;/span&gt; (optimize debug (speed 0)))
  (&lt;span class="org-keyword"&gt;with-range-indexing&lt;/span&gt; (ranges (array-dimensions array) next-index
                               &lt;span class="org-builtin"&gt;:end?&lt;/span&gt; end?
                               &lt;span class="org-builtin"&gt;:range-dimensions&lt;/span&gt; dimensions)
    (&lt;span class="org-keyword"&gt;let&lt;/span&gt; ((result (make-array (coerce dimensions 'list)
                              &lt;span class="org-builtin"&gt;:element-type&lt;/span&gt;
                              (array-element-type array))))
      (iter
        (until end?)
        (for result-index &lt;span class="org-builtin"&gt;:from&lt;/span&gt; 0)
        (setf (row-major-aref result result-index)
              (row-major-aref array (next-index))))
      result)))
&lt;/pre&gt;




&lt;p&gt;
The macro takes the range specification as the &lt;code&gt;ranges&lt;/code&gt; argument, and
also needs the original dimensions of the array.  &lt;code&gt;next-index&lt;/code&gt; should
be the name of the function that will be used to query the next index:
it increments the internal counter and delivers the next index.  The
internal counter is an array of fixnums, and the index is calculated
with an affine mapping, but the algorithm allows to update the sum
only for the indexes which actually changed.  All this is hidden by
the macro.  &lt;code&gt;end?&lt;/code&gt; is a boolean, which can be used to query when all
the elements have been traversed. &lt;code&gt;dimensions&lt;/code&gt; will be bound to the
dimensions of the result, after allowing for dimension droppings.
&lt;/p&gt;
&lt;p&gt;
This macro is pretty versatile: I used it in &lt;a href="http://github.com/tpapp/lla"&gt;LLA&lt;/a&gt; to implement &lt;code&gt;(sub dense-matrix-like ...)&lt;/code&gt;, &lt;code&gt;((setf sub) array dense-matrix-like ...)&lt;/code&gt;
and &lt;code&gt;((setf sub) dense-matrix-like array ...)&lt;/code&gt; methods, even though
LLA is column-major.  The trick is to swap dimensions.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="postamble"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-1883478182536140504?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/1883478182536140504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2010/05/sub-array-indexing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1883478182536140504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1883478182536140504'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2010/05/sub-array-indexing.html' title='Sub-array indexing'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-6950319651245699952</id><published>2010-05-17T08:56:00.001-07:00</published><updated>2010-05-18T01:37:16.632-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='implementations'/><category scheme='http://www.blogger.com/atom/ns#' term='lla'/><category scheme='http://www.blogger.com/atom/ns#' term='arrays'/><category scheme='http://www.blogger.com/atom/ns#' term='numerical'/><title type='text'>Upgraded array element types and pinned arrays (updated)</title><content type='html'>&lt;p&gt;I am planning to do a major rewrite of my &lt;a href="http://github.com/tpapp/lla/"&gt;LLA&lt;/a&gt; library in the near
future.  LLA, which stands for Lisp Linear Algebra, uses BLAS and
LAPACK to perform operations on matrices (and vectors), ranging from
matrix multiplication to singular value decompositions.  LLA is
experimental, and its aim is to provide semantics which recognize
special matrix types both as inputs and outputs.  Maybe I will blog
about it sometime, but that's not the focus of this post.
&lt;/p&gt;
&lt;p&gt;
Currently, LLA uses Lisp arrays, but wrapped in a class which has a
slot signifying the element type of the arrays.  This is because it is
meant to be portable, and not all implementations have upgraded array
element types for every type LAPACK recognizes (see below).  Also, LLA
matrix representation is currently column major, and Lisp arrays are
row-major.
&lt;/p&gt;
&lt;p&gt;
However, I realized that I can use Lisp arrays in more places - LAPACK
handles row-major arrays just fine (as transposed column-major
arrays).  Besides, having a native Lisp array is nice, eg one can just
use functions like &lt;code&gt;REDUCE&lt;/code&gt; or &lt;code&gt;REPLACE&lt;/code&gt;, without dealing with a
special type.  However, there is a price to pay: when LAPACK routines
are called, the array element type has to be detectable.  For
implementations which upgrade element types use by LLA to themselves
or something specific, this is a cheap operation.  For implementations
that don't, it requires an extra pass.
&lt;/p&gt;
&lt;p&gt;
Another issue is whether your implementation has what SBCL calls
"pinned" arrays.  Pinned arrays can make their contents available to
foreign routines directly with negligible overhead for a limited
duration (or maybe indefinitely, but I prefer the first).
&lt;/p&gt;
&lt;p&gt;
I asked for implementation-specific details on c.l.l, and got the
following information:
&lt;/p&gt;
&lt;table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"&gt;
&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Implementation&lt;/th&gt;&lt;th&gt;Machine&lt;/th&gt;&lt;th&gt;S&lt;/th&gt;&lt;th&gt;D&lt;/th&gt;&lt;th&gt;CS&lt;/th&gt;&lt;th&gt;CD&lt;/th&gt;&lt;th&gt;I32&lt;/th&gt;&lt;th&gt;I64&lt;/th&gt;&lt;th&gt;pinned?&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;SBCL (1.0.38)&lt;/td&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Lispworks (6.0.1)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Lispworks Personal Edition (5.1.1)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Clozure CL (1.4, 1.6)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Clozure CL (1.6)&lt;/td&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;ECL (10.3.1)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;ABCL (0.13.0)&lt;/td&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Allegco CL Enterprise Edition (8.1 &amp;amp; 8.2, Linux and Windows)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Allegco CL Enterprise Edition (8.1 &amp;amp; 8.2, Linux and Windows)&lt;/td&gt;&lt;td&gt;64-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;CLISP (2.48)&lt;/td&gt;&lt;td&gt;both&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;CMUCL (19e)&lt;/td&gt;&lt;td&gt;32-bit&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Corman Common Lisp (3.01, Windows)&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;
The interpretation is this: S, D, CS and CD correspond to (complex)
single and double float.  I32 and I64 are signed-byte types of 32 and
64 bits.  * means that the element type is upgraded to itself,
otherwise the table shows the upgraded type.
&lt;/p&gt;
&lt;p&gt;
The following table gives some details on the pinning mechanism when
the implementation has it:
&lt;/p&gt;
&lt;table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"&gt;
&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;&lt;col align="left"&gt;&lt;/col&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Implementation&lt;/th&gt;&lt;th&gt;Pinning construct&lt;/th&gt;&lt;th&gt;Notes&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;SBCL&lt;/td&gt;&lt;td&gt;sb-sys:with-pinned-objects with sb-sys:vector-sap&lt;/td&gt;&lt;td&gt;pins object only where GC granularity allows&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Clozure CL&lt;/td&gt;&lt;td&gt;ccl:with-pointer-to-ivector&lt;/td&gt;&lt;td&gt;disables GC&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;ECL&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;td&gt;conservative GC, data can be used as long as the object is alive&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;
So LLA is likely to have the following optimization model: it will be
blazingly fast (basically the speed of LAPACK, with a tiny bit of
overhead) on implementations which support all upgraded types and
pinning, and a bit slower on other ones.  If your implementation
supports upgrading some of the above element types to themselves,
those arrays will require no element type detection so they will be
faster.  I64 is only needed on 64-bit machines.
&lt;/p&gt;
&lt;p&gt;
The motivation behind this decision is that if you are doing serious
numerical work, your implementation should support all relevant array
element types and also pinning.  SBCL does, and since I am using that,
the new version of LLA will take advantage of all its nice facilities
&amp;mdash; it already does, but currently it only runs on SBCL so that was
natural.  LLA will be fully functional on other implementations, but
may be slower.
&lt;/p&gt;
&lt;p&gt;
Please keep sending in information for the implementations you don't
see in the table above.  I am especially interested in which
implementations support pinning.  You can use this code snipped to
generate output on array element type upgrading:
&lt;/p&gt;



&lt;pre class="src src-lisp"&gt;
(&lt;span class="org-keyword"&gt;flet&lt;/span&gt; ((&lt;span class="org-warning"&gt;check-upgraded&lt;/span&gt; (type)
         (&lt;span class="org-keyword"&gt;let&lt;/span&gt; ((upgraded (upgraded-array-element-type type)))
           (format t &lt;span class="org-string"&gt;"~A is upgraded to ~A~%"&lt;/span&gt;
                   type
                   (&lt;span class="org-keyword"&gt;if&lt;/span&gt; (equal type upgraded)
                       &lt;span class="org-string"&gt;"itself"&lt;/span&gt;
                       upgraded)))))
  (format t &lt;span class="org-string"&gt;"~2&amp;amp;~A (~A) on ~A (~A)~2%"&lt;/span&gt;
          (lisp-implementation-type) (lisp-implementation-version)
          (machine-type) (machine-version))
  (map nil #'check-upgraded '(single-float double-float
                              (complex single-float) (complex double-float)
                              (signed-byte 32) (signed-byte 64))))
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-6950319651245699952?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/6950319651245699952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2010/05/upgraded-array-element-types-and-pinned.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6950319651245699952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6950319651245699952'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2010/05/upgraded-array-element-types-and-pinned.html' title='Upgraded array element types and pinned arrays (updated)'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-934504673012032263</id><published>2010-03-01T08:07:00.001-08:00</published><updated>2010-03-01T08:07:42.459-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='mistake'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>Revenge of the reader</title><content type='html'>&lt;p&gt;Yesterday, I was compiling a function in SLIME, and I consistently got
&lt;code&gt;error: illegal function call&lt;/code&gt; messages from SBCL.  The function was a
pretty complicated one, and I couldn't figure out the error.  I even
resorted to commenting out sections, until I had an empty shell, with
only the docstring.  Then realization dawned &amp;mdash; here is a simplified
example of how the function looked like:
&lt;/p&gt;



&lt;pre class="src src-lisp"&gt;
(&lt;span class="org-keyword"&gt;defun&lt;/span&gt; &lt;span class="org-function-name"&gt;foo&lt;/span&gt; (bar)
  &lt;span class="org-doc"&gt;"Docstring, followed by accidental dot"&lt;/span&gt;.
  (&lt;span class="org-keyword"&gt;let&lt;/span&gt; ((baz (1+ bar)))
    baz))
&lt;/pre&gt;




&lt;p&gt;
Did you notice the dot?  I didn't, for a while (guess I should take
breaks every hour or so and rest my eyes, especially in the evening).
But &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_da.htm"&gt;the reader&lt;/a&gt; did.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-934504673012032263?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/934504673012032263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2010/03/revenge-of-reader.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/934504673012032263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/934504673012032263'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2010/03/revenge-of-reader.html' title='Revenge of the reader'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-789063061348605237</id><published>2010-01-06T01:08:00.000-08:00</published><updated>2010-01-06T01:08:07.565-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='filk'/><category scheme='http://www.blogger.com/atom/ns#' term='parody'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><title type='text'>God wrote in LISP</title><content type='html'>&lt;p&gt;I was googling for &lt;a href="http://xkcd.com/224/"&gt;this XKCD comic&lt;/a&gt; when I accidentally found &lt;a href="http://www.cs.washington.edu/education/courses/cse505/05wi/eternalflame.mp3"&gt;The Eternal Flame (God Wrote in LISP)&lt;/a&gt; by &lt;a href="http://en.wikipedia.org/wiki/Julia_Ecklar"&gt;Julia Ecklar&lt;/a&gt;.  The song itself is
a parody of a &lt;a href="http://en.wikipedia.org/wiki/Filk_music"&gt;filk&lt;/a&gt;.  The parody lyrics were written by &lt;a href="http://songworm.com/db/songworm-parody/EternalFlame.html"&gt;Bob Kanefsky&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-789063061348605237?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/789063061348605237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2010/01/god-wrote-in-lisp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/789063061348605237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/789063061348605237'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2010/01/god-wrote-in-lisp.html' title='God wrote in LISP'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-8694357841761561522</id><published>2009-12-31T01:46:00.000-08:00</published><updated>2009-12-31T01:46:18.611-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='book review'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Book review: Pro Git by Scott Chacon</title><content type='html'>&lt;p&gt;Like &lt;a href="http://github.com/languages/Common Lisp"&gt;many others&lt;/a&gt;, I use &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; as a version control system for my Lisp
code.  Version control is one of those things that offer a lot of
benefits with relatively little investment: I picked up a few basic
&lt;code&gt;git&lt;/code&gt; commands from tutorials on the internet (&lt;a href="http://help.github.com/"&gt;Github&lt;/a&gt; has a nice
collection), but didn't bother to learn about git in depth.
&lt;/p&gt;
&lt;p&gt;
However, as others started to contribute to my libraries, I was forced
to learn more about certain features, most importantly branching and
merging.  After spending a few hours doing things the wrong way, I
realized that I need to do some reading, and I was lucky to find &lt;i&gt;Pro Git&lt;/i&gt; by Scott Chacon, one of the prominent git developers.  Thanks to
the author and the publisher (&lt;a href="http://apress.com/"&gt;Apress&lt;/a&gt;), the book is available &lt;a href="http://progit.org/book/"&gt;online&lt;/a&gt;.
I really appreciate that Apress makes its books available online so I
can start reading them immediately, and I have already ordered a dead
tree copy.
&lt;/p&gt;
&lt;p&gt;
The book is a pleasure to read, and is really useful.  Instead of
simply rehashing the manual, it focuses on explaining the concepts of
git, and illustrates them with typical workflows.  I found this
invaluable: understanding the concepts behind git made me realize that
I have been doing things the wrong way.  I used &lt;a href="http://subversion.tigris.org/"&gt;subversion&lt;/a&gt; before,
and it was still influencing the way I use git.  For example,
branching in git is really, really cheap, and I learned that I should
do it more often.
&lt;/p&gt;
&lt;p&gt;
My favorite chapters from this book are &lt;a href="http://progit.org/book/ch3-0.html"&gt;Git Branching&lt;/a&gt;, which explains
the concept of branches, gives examples of basic branching and
merging, branch management and typical workflows, and also discusses
remote branches, and &lt;a href="http://progit.org/book/ch5-0.html"&gt;Distributed Git&lt;/a&gt;, which talks about distributed
workflows in more detail.
&lt;/p&gt;
&lt;p&gt;
I have learned a lot from this book, and hopefully it will help me
manage my &lt;a href="http://github.com/tpapp/"&gt;Lisp libraries&lt;/a&gt; better.  So far I have been keeping changes
on my hard disk between "releases" (updates to &lt;code&gt;master&lt;/code&gt;), but now I
think that I will make development branches for new features and push
them more often.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-8694357841761561522?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/8694357841761561522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/12/book-review-pro-git-by-scott-chacon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8694357841761561522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8694357841761561522'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/12/book-review-pro-git-by-scott-chacon.html' title='Book review: Pro Git by Scott Chacon'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-6447008057405159344</id><published>2009-12-31T01:19:00.000-08:00</published><updated>2009-12-31T01:19:16.546-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='product review'/><title type='text'>Maxell pendrive suckage</title><content type='html'>&lt;p&gt;I had to reinstall the OS on my parents' computer during the Christmas
holidays.  I forgot to bring my external hard disk with me, so I
decided to buy a pendrive to backup their files.
&lt;/p&gt;
&lt;p&gt;
Unfortunately, I picked a &lt;b&gt;Maxell Venture&lt;/b&gt; to do the job.  Maxell puts
this pendrive in their &lt;i&gt;Business Range&lt;/i&gt; line.  I learned about this
later because this is &lt;i&gt;not&lt;/i&gt; indicated on the packaging.  If it had
been, I wouldn't have touched the product with a ten-foot pole.  I
consider pendrives a commodity: they should present a standard
interface, and the only qualitative differentiation I can imagine is
sleek and/or durable design or novelty packaging (not that I care for
the latter).
&lt;/p&gt;
&lt;p&gt;
Apparently, some pendrive manufacturers think otherwise.  Maxell
decided that it would indulge consumers with "extra features", such as
"security and file compression software".  Unfortunately, this makes
the pendrive interface non-standard.  The pendrive shows up as &lt;b&gt;two physical devices&lt;/b&gt;, one contains a small partition called &lt;code&gt;SECRET&lt;/code&gt;, the
other has a large partition called &lt;code&gt;PUBLIC&lt;/code&gt;.  Apparently, this feature
is governed by the firmware.  There is no way to repartition the
device (which shows up as &lt;code&gt;/dev/sdb&lt;/code&gt; &lt;b&gt;and&lt;/b&gt; &lt;code&gt;/dev/sdc&lt;/code&gt; &lt;b&gt;at the same time&lt;/b&gt;), and it is impossible to get rid of these "features".  An added
bonus is that I found it impossible to make this pendrive boot: the
BIOS of my computer was understandably confused about this whole
arrangement.
&lt;/p&gt;
&lt;p&gt;
Nice job, Maxell.  I returned the pendrive to the store the next day.
When I googled for a possible solution, I learned about a similar
"extension" called &lt;a href="http://en.wikipedia.org/wiki/U3"&gt;U3&lt;/a&gt;, which is equally useless but at least it can be
&lt;a href="http://www.u3.com/support/#CQ3"&gt;removed&lt;/a&gt; (albeit only using Windows), and the U3 folks are decent
enough to offer removal software on their website.  By the way, Maxell
support still hasn't answered my e-mail.
&lt;/p&gt;
&lt;p&gt;
I think that companies should be free to offer "features" that break
pendrives, but they should be obliged by law to display this warning
message: 
&lt;/p&gt;


&lt;pre class="example"&gt;You are purchasing a pendrive with a non-standard interface.
Generally, this sucks.
Do yourself a favor and buy from one of our competitors.
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-6447008057405159344?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/6447008057405159344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/12/maxell-pendrive-suckage.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6447008057405159344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6447008057405159344'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/12/maxell-pendrive-suckage.html' title='Maxell pendrive suckage'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-5213822146570291793</id><published>2009-12-25T06:26:00.000-08:00</published><updated>2009-12-25T06:29:12.612-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='org-mode'/><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='syntax highlighting'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='blogging'/><title type='text'>Syntax highlighting with org-mode</title><content type='html'>&lt;p&gt;Blogging is probably the best way to disseminate information about new
(features in) libraries in the Lisp community&amp;mdash;if you are reading
this, you are probably subscribed to &lt;a href="http://planet.lisp.org/"&gt;Planet Lisp&lt;/a&gt;, which nicely
aggregates all Lisp-related blogs that are registered. On the other
hand, blogging about Lisp is&amp;mdash;or was&amp;mdash;quite a hassle to me.  I am
using Google's &lt;a href="#blogger.com"&gt;blogger.com&lt;/a&gt;, which has nice features, but I am used to
Emacs and prefer typing text there.  Including Lisp code snippets was
a pain in the butt: I had to keep playing with &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; tags and it
still didn't look right.  But now I had a bit of time to explore the
issue and found a workflow that is 
&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
pretty painless and
&lt;/li&gt;
&lt;li&gt;
does syntax highlighting.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It uses &lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt;, which I already use to
manage my agenda.  I would like to thank &lt;a href="http://emacs-fu.blogspot.com/2009/05/writing-and-blogging-with-org-mode.html"&gt;EMACS-FU&lt;/a&gt;, &lt;a href="http://blogisticreflections.wordpress.com/2009/09/20/welcome-to-blogistic-reflections/"&gt;Blogistic Reflections&lt;/a&gt;, Drew Crampsie, Ross Lonstein, and &lt;a href="http://t-b-o-g.blogspot.com/"&gt;Jānis Džeriņš&lt;/a&gt; for their
help and/or blog posts on using &lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Here is what you should do:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
In Emacs, set &lt;code&gt;org-export-htmlize-output-type&lt;/code&gt; to &lt;code&gt;css&lt;/code&gt;.  This
makes &lt;code&gt;org-mode&lt;/code&gt; emit formatting with &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; elements instead of
inline style directives, which is the default.

&lt;/li&gt;
&lt;li&gt;
Open a source file with &lt;code&gt;org-mode&lt;/code&gt; (eg &lt;code&gt;sample.org&lt;/code&gt;).  Leave it
empty, we just need it to generate some CSS.  Use the Emacs
function &lt;code&gt;org-export&lt;/code&gt; (usually &lt;code&gt;C-c C-e&lt;/code&gt;), and extract the CSS
part.  This is the &lt;b&gt;first part&lt;/b&gt; of all the CSS styling you need.

&lt;/li&gt;
&lt;li&gt;
Generate the &lt;b&gt;second part&lt;/b&gt; with &lt;code&gt;org-export-htmlize-generate-css&lt;/code&gt;.

&lt;/li&gt;
&lt;li&gt;
Paste &lt;b&gt;both parts&lt;/b&gt; into the CSS section served by your blog engine.
For example, on &lt;a href="#blogger.com"&gt;blogger.com&lt;/a&gt; you should go to &lt;i&gt;Layout&lt;/i&gt;, then &lt;i&gt;Edit    HTML&lt;/i&gt;, and paste it &lt;b&gt;after&lt;/b&gt; the &lt;code&gt;&amp;lt;Variable name=...&amp;gt;&lt;/code&gt; section where
the CSS formatting starts.  There will be some overlap between the
two parts and possibly your existing template, but it should not
matter.  Edit colors, fonts, etc to the style you want.  All I did
was change the colors for the &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; tags.

&lt;/li&gt;
&lt;li&gt;
Turn off auto-conversion of line breaks.  On &lt;a href="#blogger.com"&gt;blogger.com&lt;/a&gt;, you
can find &lt;i&gt;Convert line breaks&lt;/i&gt; in the &lt;i&gt;Settings/Formatting&lt;/i&gt;
section.  Unless you do this, your blog engine could introduce
unnecessary &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt; tags in the HTML.

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You are now ready to post.  A simple example looks like this in org-mode: 
&lt;/p&gt;


&lt;pre class="example"&gt;#+TITLE:     Sample blog post
#+AUTHOR:    Your Name
#+EMAIL:     your@email.address
#+LANGUAGE:  en
#+OPTIONS:   H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:tl creator:nil
#+OPTIONS:   TeX:t LaTeX:nil skip:nil d:nil tags:not-in-toc author:nil timestamp:nil
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js

Here is some sample source code:
#+BEGIN_SRC lisp
(defun add2 (x)
  (+ x 2))
#+END_SRC
You can include example output:
#+BEGIN_EXAMPLE
CL-USER&amp;gt; (add2 3)
5
#+END_EXAMPLE
See the [[http://orgmode.org/org.html][Org Manual]] for further details.
&lt;/pre&gt;




&lt;p&gt;
You can include formatting options as shown in the example.
&lt;/p&gt;
&lt;p&gt;
I use the following snippet in Emacs for settings and keybindings:
&lt;/p&gt;


&lt;pre class="src src-emacs-lisp"&gt;(&lt;span class="org-keyword"&gt;defun&lt;/span&gt; &lt;span class="org-function-name"&gt;org-export-body-as-html&lt;/span&gt; ()
  (interactive)
  (org-export-as-html 3 nil nil &lt;span class="org-string"&gt;"blog"&lt;/span&gt; t))

(add-hook 'org-mode-hook
          (&lt;span class="org-keyword"&gt;lambda&lt;/span&gt; ()
            (setq org-export-htmlize-output-type 'css)
            (local-set-key (quote [?\C-c ?\C-x]) 'org-export-body-as-html)))
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5213822146570291793?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5213822146570291793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/12/syntax-highlighting-with-org-mode.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5213822146570291793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5213822146570291793'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/12/syntax-highlighting-with-org-mode.html' title='Syntax highlighting with org-mode'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-342357431435519198</id><published>2009-12-20T04:29:00.000-08:00</published><updated>2009-12-25T04:59:44.765-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='xarray'/><title type='text'>A tour of xarray: part 1</title><content type='html'>&lt;div id="content"&gt;
&lt;h1 class="title"&gt;A tour of xarray&lt;/h1&gt;

&lt;p&gt;I frequently come across situations which require taking slices from
arrays, and sometimes I need other high-level array manipulations,
such as index permutations or projections to row- or column major.  In
an &lt;a href="http://elaine.ihs.ac.at/~tpapp/software/affi.tar.gz"&gt;earlier attempt called &lt;code&gt;affi&lt;/code&gt;&lt;/a&gt;, I handled these things using affine
mappings, but now I realize that those are not general enough, and my
need for these manipulations to be super-efficient was mostly
imaginary.  I started working on a library, which evolved to &lt;a href="http://github.com/tpapp/xarray"&gt;xarray&lt;/a&gt;,
which is able to do these things (and much more&amp;mdash;see the next post!)
for any kind of array-like object, provided that they have the
required minimal interface, defined as a few CLOS method.  This blog
post is the first of a &lt;a href="http://tkpapp.blogspot.com/search/label/xarray"&gt;series&lt;/a&gt; which is meant to give a tour of
&lt;code&gt;xarray&lt;/code&gt;.
&lt;/p&gt;

&lt;div id="outline-container-1" class="outline-2"&gt;
&lt;h2 id="sec-1"&gt;The minimal interface &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-1"&gt;


&lt;p&gt;
&lt;code&gt;Xarray&lt;/code&gt; handles objects which can be addressed using a rectilinear
coordinate system.  No assumptions are made about the storage model,
and if you want some class to be xarray-compatible, just define
methods &lt;code&gt;xdims&lt;/code&gt;, which gives a list of dimensions, and &lt;code&gt;xref&lt;/code&gt; (also
&lt;code&gt;(setf xref)&lt;/code&gt;, if your object is modifiable, but this is not required
for basic functionality), which is a generic function pretty much like
&lt;code&gt;aref&lt;/code&gt;.  Finally, there is the generic function &lt;code&gt;xelttype&lt;/code&gt; to query
element type.  &lt;i&gt;This is all you need to provide&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
Based on &lt;code&gt;xdims&lt;/code&gt;, reasonable defaults are provided for &lt;code&gt;xrank&lt;/code&gt;, which
returns an integer for the number of dimensions, &lt;code&gt;xsize&lt;/code&gt;, which
returns the total number of elements in the object, and &lt;code&gt;(xdim object i)&lt;/code&gt;, which is defined as &lt;code&gt;(nth (xdims object) i)&lt;/code&gt; by default.  Feel
free to define these, though, if there is a "natural" way to do this
for your objects (like it is for arrays, below).
&lt;/p&gt;
&lt;p&gt;
To demonstrate how easy it is to do this for any kind of object, here
are the definitions from &lt;code&gt;array.lisp&lt;/code&gt;, which defines these methods for
Common Lisp arrays:
&lt;/p&gt;



&lt;pre class="src src-lisp"&gt;(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xelttype&lt;/span&gt; ((object array))
  (array-element-type object))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xrank&lt;/span&gt; ((object array))
  (array-rank object))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xdims&lt;/span&gt; ((object array))
  (array-dimensions object))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xdim&lt;/span&gt; ((object array) axis-number)
  (array-dimension object axis-number))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xsize&lt;/span&gt; ((object array))
  (array-total-size object))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; &lt;span class="org-function-name"&gt;xref&lt;/span&gt; ((object array) &lt;span class="org-type"&gt;&amp;amp;rest&lt;/span&gt; subscripts)
  (apply #'aref object subscripts))

(&lt;span class="org-keyword"&gt;defmethod&lt;/span&gt; (&lt;span class="org-function-name"&gt;setf xref)&lt;/span&gt; (value (object array) &lt;span class="org-type"&gt;&amp;amp;rest&lt;/span&gt; subscripts)
  (setf (apply #'aref object subscripts) value))
&lt;/pre&gt;




&lt;p&gt;
In case a specialized method is not provided for an object, the
default fallback methods (in &lt;code&gt;atoms.lisp&lt;/code&gt;) just handle objects as
atoms, ie arrays of rank 0.  After you define the methods &lt;code&gt;xdims&lt;/code&gt;,
&lt;code&gt;xref&lt;/code&gt; and &lt;code&gt;xelttype&lt;/code&gt;&amp;mdash;and nothing more!&amp;mdash;for your class, you can
use &lt;code&gt;xarray&lt;/code&gt;'s views.  The (somewhat sloppy) terminology of &lt;code&gt;xarray&lt;/code&gt;
is to call classes which provide a minimal interface &lt;i&gt;xrefable&lt;/i&gt;.
&lt;/p&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2" class="outline-2"&gt;
&lt;h2 id="sec-2"&gt;Views &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-2"&gt;


&lt;p&gt;
Technically, views are functions mapping a set of rectilinear indexes
to a (sub)set of an xrefable object called the &lt;i&gt;ancestor&lt;/i&gt;.
Practically, they are objects that walk and quack like arrays, but are
usually a thin layer on other array-like objects.
&lt;/p&gt;
&lt;p&gt;
Let's see some examples.  I will use a Common Lisp array as a starting
point, but of course these examples would work with any object as long
as it is xrefable.
&lt;/p&gt;

&lt;/div&gt;

&lt;div id="outline-container-2.1" class="outline-3"&gt;
&lt;h3 id="sec-2.1"&gt;Slices &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2.1"&gt;


&lt;p&gt;
Slicing is the most obvious view that you can have for an array:
&lt;/p&gt;


&lt;pre class="example"&gt;CL-USER&amp;gt; (defparameter *a* (make-array '(3 4) :initial-contents
                              '((1 2 3 4)
                                (5 6 7 8)
                                (9 10 11 12))))
CL-USER&amp;gt; (slice *a* 2 :all)
#&amp;lt;SLICE-VIEW 
#(9 10 11 12)  {B1025A1}&amp;gt;
&lt;/pre&gt;




&lt;p&gt;
Instead of an array, you get a &lt;code&gt;slice-view&lt;/code&gt; object.  &lt;code&gt;Print-object&lt;/code&gt;
for views usually just prints the elements as if they were an array,
even if the ancestor isn't (this was simple to do, fancy printing may
be introduced later at some point, but don't hold your breath).  &lt;code&gt;2&lt;/code&gt;
selects the elements of same index along the 0th dimension, while
&lt;code&gt;:all&lt;/code&gt; selects all elements along the 1st.
&lt;/p&gt;
&lt;p&gt;
You can get an array using &lt;code&gt;take&lt;/code&gt;:
&lt;/p&gt;


&lt;pre class="example"&gt;CL-USER&amp;gt; (take t (slice *a* 2 :all))
#(9 10 11 12)
&lt;/pre&gt;




&lt;p&gt;
The first argument tells &lt;code&gt;take&lt;/code&gt; to return an object &lt;i&gt;similar&lt;/i&gt; to the
ancestor&amp;mdash;we will tackle the concept of similarity and object
creation in the next post about &lt;code&gt;xarray&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;
For now, notice how slice &lt;i&gt;dropped a dimension&lt;/i&gt; when you asked for a
single index.  You can avoid that by making it a list:
&lt;/p&gt;


&lt;pre class="example"&gt;CL-USER&amp;gt;
(slice *a* '(2) :all)
#&amp;lt;SLICE-VIEW 
#2A((9 10 11 12))  {B9EBF59}&amp;gt;
&lt;/pre&gt;



&lt;p&gt;
You can drop unit dimensions with &lt;code&gt;(drop object)&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;
Lists of two elements select ranges (inclusive), which can also
&lt;i&gt;reverse&lt;/i&gt; elements, for example, ='(2 0)= would select the third,
second and first elements along that dimensions.  Negative integers
count from the largest index (which is &lt;code&gt;-1&lt;/code&gt;; think of &lt;code&gt;-i&lt;/code&gt; as &lt;code&gt;(- (xdim object d) i)&lt;/code&gt;) backwards, and &lt;code&gt;:rev&lt;/code&gt; reverses all elements (so
it is equivalent to &lt;code&gt;\'(0 -1)&lt;/code&gt;).  Finally, a vector just picks
individual indexes (which can repeat, occur in any order, be negative
following the conventions above, etc):
&lt;/p&gt;


&lt;pre class="example"&gt;CL-USER&amp;gt; (slice *a* -1 :all)
#&amp;lt;SLICE-VIEW 
#(9 10 11 12)  {AC4FF31}&amp;gt;
CL-USER&amp;gt; (slice *a* :rev '(1 3))
#&amp;lt;SLICE-VIEW 
#2A((10 11 12) (6 7 8) (2 3 4))  {BAC83F9}&amp;gt;
CL-USER&amp;gt; (slice *a* '2 #(1 1 3))
#&amp;lt;SLICE-VIEW 
#(10 10 12)  {BB66859}&amp;gt;
&lt;/pre&gt;





&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2.2" class="outline-3"&gt;
&lt;h3 id="sec-2.2"&gt;Permutations &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2.2"&gt;


&lt;p&gt;
A permutation permutes the dimensions of an xrefable object:
&lt;/p&gt;



&lt;pre class="example"&gt;CL-USER&amp;gt; (take t (permutation *a* 1 0))
#2A((1 5 9) (2 6 10) (3 7 11) (4 8 12))
&lt;/pre&gt;




&lt;p&gt;
Transposing is a special case of permutations, with indexes &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;
(as above).  Of course, you can combine views:
&lt;/p&gt;


&lt;pre class="example"&gt;CL-USER&amp;gt; (slice (permutation *a* 1 0) :rev :rev)
#&amp;lt;SLICE-VIEW 
#2A((12 8 4) (11 7 3) (10 6 2) (9 5 1))  {AAAC849}&amp;gt;
&lt;/pre&gt;




&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-2.3" class="outline-3"&gt;
&lt;h3 id="sec-2.3"&gt;Miscellaneous views &lt;/h3&gt;
&lt;div class="outline-text-3" id="text-2.3"&gt;


&lt;p&gt;
Two other special views are &lt;code&gt;column-major-projection&lt;/code&gt; and &lt;code&gt;flat&lt;/code&gt;
views.  The first one provides a projection of an object &lt;i&gt;as if&lt;/i&gt; the
elements of the two were arranged in column-major order (note that
this may not be the actual storage model, as xarray does not make
assumptions the latter but uses &lt;code&gt;xref&lt;/code&gt;; however, for some special
objects faster methods may be provided):
&lt;/p&gt;



&lt;pre class="example"&gt;CL-USER&amp;gt; (column-major-projection *a* 6 2)
#&amp;lt;COLUMN-MAJOR-PROJECTION-VIEW 
#2A((1 3) (5 7) (9 11) (2 4) (6 8) (10 12))  {BE28921}&amp;gt;
&lt;/pre&gt;




&lt;p&gt;
&lt;code&gt;Flat&lt;/code&gt; views just return an object with a single dimension, with the
order of elements unspecified.  This is advantageous if the object has
a natural representation in some storage model, and we want to perform
operations where the order of elements does not matter (eg sum the
elements).
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;

&lt;div id="outline-container-3" class="outline-2"&gt;
&lt;h2 id="sec-3"&gt;Semantics of views &lt;/h2&gt;
&lt;div class="outline-text-2" id="text-3"&gt;


&lt;p&gt;
&lt;code&gt;(setf xref)&lt;/code&gt;, when provided, sets elements in the &lt;i&gt;ancestor&lt;/i&gt; of an
object: if that is another view, the &lt;i&gt;original ancestor&lt;/i&gt; (ie the
object which is not a view) is modified. (Thus views &lt;i&gt;always share structure&lt;/i&gt;.  If you want to avoid this, use &lt;code&gt;take&lt;/code&gt; to create a new
object.
&lt;/p&gt;
&lt;p&gt;
All the operations shown above are generic functions, you are free to
specialize them.  These methods
&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
don't have to return subclasses of &lt;code&gt;view&lt;/code&gt;, they are free to return any xrefable object as long as it shares structure,
&lt;/li&gt;
&lt;li&gt;
are allowed to combine views.  

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, some CL array slices with contiguous row-major indexes
could be implemented as displaced arrays, or a combination of a
transpose and a slice can be folded into one view if the object
supports that.  Currently, these efficiency hacks are not implemented
as I don't really need them, but the infrastructure is there.
&lt;/p&gt;
&lt;p&gt;
Next time, I will address object creation and some generic operations
on xrefable objects.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="postamble"&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-342357431435519198?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/342357431435519198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/12/tour-of-xarray-part-1.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/342357431435519198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/342357431435519198'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/12/tour-of-xarray-part-1.html' title='A tour of xarray: part 1'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-4464192825178080091</id><published>2009-12-06T07:46:00.000-08:00</published><updated>2009-12-06T07:46:47.021-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ecl'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>first steps with ECL</title><content type='html'>I am living in Austria now and my German is very basic, so I use online translators to cope with the occasional e-mail in German that I can't decipher.  I am using the &lt;a href="http://www.mutt.org/"&gt;mutt&lt;/a&gt; mail user agent, and in the past I have configured it to open HTML attachments in Firefox.  However, with plain text messages manual copy &amp; paste became tedious, so I decided to write a little script that opens them in Firefox.&lt;br /&gt;
&lt;br /&gt;
This gave me a good excuse to play around with &lt;a href="http://ecls.sourceforge.net/"&gt;ECL&lt;/a&gt;, something that I wanted to do for a while.  The choice of CL as a scripting language might seem odd to some people, but I find it is optimal for me.  I am aware that there are DSLs for this specific purpose (called "scripting languages") out there, and some &lt;a href="http://www.gnu.org/software/guile/guile.html"&gt;even&lt;/a&gt; &lt;a href="http://librep.sourceforge.net/"&gt;look&lt;/a&gt; &lt;a href="http://www.scsh.net/"&gt;like&lt;/a&gt; Lisp.  However, I find that it takes a bit of time to find my way around a new language, and since at this point I am convinced that I will keep using CL as my main programming language, learning a scripting language that gives no additional insight would be a wasted effort.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://paste.lisp.org/display/91679"&gt;Here&lt;/a&gt; is the end result.  The script is really simple, and it benefited quite a bit from the comments of people on comp.lang.lisp.  I like using this script, but the greatest benefit I derived from writing it is discovering what a gem &lt;a href="http://ecls.sourceforge.net/"&gt;ECL&lt;/a&gt; is.  For example, I only need to use the two simple commands &lt;br /&gt;
&lt;pre&gt;(compile-file "savebody.lisp" :system-p t)
(c:build-program "savebody" :lisp-files '("savebody.o"))
&lt;/pre&gt;to compile the script to a small &lt;strong&gt;(37K)&lt;/strong&gt; (I am serious &amp;mdash; it is really that small) executable file via C.  A nice summary of simple compilation cases can be found &lt;a href="http://blog.s21g.com/articles/1649"&gt;here&lt;/a&gt;.  Reading the ECL manual, I found that there are even more powerful facilities for &lt;a href="http://ecls.sourceforge.net/new-manual/ch16.html"&gt;building programs&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I am very impressed with ECL, and will definitely consider it as a remarkable implementation in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-4464192825178080091?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/4464192825178080091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/12/first-steps-with-ecl.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4464192825178080091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/4464192825178080091'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/12/first-steps-with-ecl.html' title='first steps with ECL'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-213860005051484516</id><published>2009-06-15T05:29:00.000-07:00</published><updated>2009-06-15T05:38:58.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-2d'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>updates to cl-cairo2 and cl-2d</title><content type='html'>Following the &lt;a href="http://tkpapp.blogspot.com/2009/05/cl-cairo2-context-wart-fixed.html"&gt;discussion&lt;/a&gt; and the resulting &lt;a href="http://tkpapp.blogspot.com/2009/05/cl-cairo2-interface-poll.html"&gt;poll&lt;/a&gt;, I updated cl-cairo2 and consequently cl-2d to use the special variable *context* as the default context.

This does &lt;strong&gt;not&lt;/strong&gt; affect the interface of cl-2d (except for user-defined functions that draw directly on the cairo context, of course), since in cl2d, the context is always saved in the frame and there is no "default" frame.  Nevertheless, updating the cl-2d code was beneficial because I was able to see if the new style makes things easier.  It appears that it simplifies the code quite a bit: I would like to thank everyone who argued for the change.

Enjoy.  Bug reports and contributed code are appreciated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-213860005051484516?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/213860005051484516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/06/updates-to-cl-cairo2-and-cl-2d.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/213860005051484516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/213860005051484516'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/06/updates-to-cl-cairo2-and-cl-2d.html' title='updates to cl-cairo2 and cl-2d'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-5837404644752220849</id><published>2009-05-23T17:00:00.000-07:00</published><updated>2009-05-23T17:11:38.392-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='latex-table'/><category scheme='http://www.blogger.com/atom/ns#' term='latex'/><category scheme='http://www.blogger.com/atom/ns#' term='table'/><title type='text'>announcing latex-table</title><content type='html'>&lt;a href="http://www.cliki.net/latex-table"&gt;Latex-table&lt;/a&gt; is a simple Common Lisp library for writing vectors and matrices into LaTeX tables.  It won't allow you to do anything magical that you could not do in LaTeX otherwise, but it simplifies formatting (mostly numerical) tables.  Floats are aligned on the decimal dot.  Some examples:&lt;pre&gt;(with-open-file (stream "/tmp/horizontal.table" :direction :output
   :if-exists :overwrite :if-does-not-exist :create)
  (labeled-vector-horizontal stream 
        (vector "foo" pi -42)
        (vector "$\\alpha$" "bar" "baz")
        :significant-digits 3))&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_eGqLjgUk4dc/ShiPAny6d2I/AAAAAAAAADA/fEVOLi9YZhM/s1600-h/vector.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 272px; height: 117px;" src="http://3.bp.blogspot.com/_eGqLjgUk4dc/ShiPAny6d2I/AAAAAAAAADA/fEVOLi9YZhM/s400/vector.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5339174599093024610" /&gt;&lt;/a&gt;&lt;pre&gt;(with-open-file (stream "/tmp/matrix.table" :direction :output
   :if-exists :overwrite :if-does-not-exist :create)
  (labeled-matrix stream #2A((11.1 112.55 3)
        (9 1345.79 14.72))
    (vector "foo" "bar" "baz")
    (vector "first" "second")
    :hlines '(1 2 -1 1)))&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_eGqLjgUk4dc/ShiPIZeMg-I/AAAAAAAAADI/ZDZnC0dqubo/s1600-h/matrix.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 147px;" src="http://4.bp.blogspot.com/_eGqLjgUk4dc/ShiPIZeMg-I/AAAAAAAAADI/ZDZnC0dqubo/s400/matrix.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5339174732686984162" /&gt;&lt;/a&gt;

All of these functions use the "raw" interface below, which you can also use directly.&lt;pre&gt;(with-open-file (stream "/tmp/raw.table" :direction :output
   :if-exists :overwrite :if-does-not-exist :create)
  (raw-tabular stream #2A(((:aligned "foo" ""))
     ((:aligned "bar" "baz"))
     ((:aligned "" ".19"))
     ((:left "left"))
     ((:right "right"))
     ((:center "center")))
        #(:aligned)  ; column types
        #(0 0)   ; vertical lines
        #(1 2 0 0 0 0 3))) ; horizontal lines&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShiPROuvLhI/AAAAAAAAADQ/UKR35Nbviz4/s1600-h/raw.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 186px; height: 262px;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShiPROuvLhI/AAAAAAAAADQ/UKR35Nbviz4/s400/raw.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5339174884422397458" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5837404644752220849?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5837404644752220849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/announcing-latex-table.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5837404644752220849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5837404644752220849'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/announcing-latex-table.html' title='announcing latex-table'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_eGqLjgUk4dc/ShiPAny6d2I/AAAAAAAAADA/fEVOLi9YZhM/s72-c/vector.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-7567699123574164524</id><published>2009-05-23T15:08:00.000-07:00</published><updated>2009-05-23T15:19:20.493-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='api'/><category scheme='http://www.blogger.com/atom/ns#' term='interface'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>cl-cairo2 interface poll</title><content type='html'>It seems that what I considered a &lt;a href="http://tkpapp.blogspot.com/2009/05/cl-cairo2-context-wart-fixed.html"&gt;wart&lt;/a&gt; is a feature to some people.  I would like to make the users of cl-cairo2 happy, so I am considering reverting to the older interface.  Also, I experimented with some other code I am using, and I think that wrapping my code in &lt;code&gt;(let ((*context* context1)) ...)&lt;/code&gt; is not too much of a hassle anyway.

So I am conducting an informal poll: please comment below.  If you like the&lt;pre&gt;(move-to context ...)&lt;/pre&gt; interface, say &lt;em&gt;explicit&lt;/em&gt;, if you prefer the &lt;pre&gt;(move-to ... &amp;key (context *context*))&lt;/pre&gt; interface, say &lt;em&gt;global&lt;/em&gt;.  If you are indifferent, just state that.

You can also tell me if you have code that already uses either interface, and whether you it would be a great inconvenience to change that (but I can't imagine that very many people have a lot of code using the explicit interface at this stage).

I have listened to your arguments, so you won't need to repeat them, unless you feel that you have something crucual to add.  I will take a look at the results on Tuesday, May 26, and update the library (and &lt;a href="http://cliki.net/cl-2d"&gt;cl-2d&lt;/a&gt;) if necessary.  I would rather complete the transition quickly, as I want the API to be relatively stable.  I do know that in the previous post I said that there will be no more changes, guess I am &lt;a href="http://en.wikipedia.org/wiki/Dynamic_inconsistency"&gt;dynamically inconsistent&lt;/a&gt; :-P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-7567699123574164524?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/7567699123574164524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-interface-poll.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7567699123574164524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7567699123574164524'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-interface-poll.html' title='cl-cairo2 interface poll'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-1826739380810187917</id><published>2009-05-21T19:02:00.000-07:00</published><updated>2009-05-21T19:08:27.206-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='asdf-install'/><category scheme='http://www.blogger.com/atom/ns#' term='array-operations'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-numlib'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-colors'/><title type='text'>cl-numlib, array-operations and cl-colors migrated to Github; my packages are asdf-installable again</title><content type='html'>Looks like I goofed up when releasing cl-2d: it used a few routines which were sitting on my hard disk but not made public yet.  I think I corrected that, and pushed the new versions to Github.

Also, I think I figured out how to link to tarballs on Github.  Using entries like&lt;pre&gt;:(package "http://github.com/tpapp/cl-2d/tarball/master")&lt;/pre&gt;ASDF goes to Github, where is it redirected to the latest master tarball, and appears to work fine.  If not, let me know and it will be fixed.  Still, I would suggest that you use git to keep updating the libraries if you can.

Thanks to Peter Mikula for reporting the missing library code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-1826739380810187917?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/1826739380810187917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-numlib-array-operations-and-cl.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1826739380810187917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1826739380810187917'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-numlib-array-operations-and-cl.html' title='cl-numlib, array-operations and cl-colors migrated to Github; my packages are asdf-installable again'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-8340237903193828911</id><published>2009-05-21T04:38:00.000-07:00</published><updated>2009-05-21T04:44:55.358-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='license change'/><category scheme='http://www.blogger.com/atom/ns#' term='migration'/><category scheme='http://www.blogger.com/atom/ns#' term='ffa'/><category scheme='http://www.blogger.com/atom/ns#' term='llgpl'/><title type='text'>ffa: complex numbers, license change, migration to Github</title><content type='html'>I have done a few minor updates to my &lt;a href="http://www.cliki.net/FFA"&gt;FFA&lt;/a&gt; library.  It now handles complex numbers (to be precise, arrays of &lt;code&gt;(complex simple-float)&lt;/code&gt; and &lt;code&gt;(complex double-float)&lt;/code&gt;).  Because of the extra complexity (haha), I also added some unit tests that use simple C functions to check that FFA does what it claims to do.

I have also changed the license to &lt;a href="http://www.cliki.net/LLGPL"&gt;LLGPL&lt;/a&gt; (was GPL).  And finally, I have migrated the library to &lt;a href="http://github.com/tpapp/ffa/tree/master"&gt;Github&lt;/a&gt;.  Github is proving really user-friendly and reliable, in the long run I plan to put all my libraries there.

Thanks to William Halliburton for reminding me that the previous repo was out of date.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-8340237903193828911?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/8340237903193828911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/ffa-complex-numbers-license-change.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8340237903193828911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/8340237903193828911'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/ffa-complex-numbers-license-change.html' title='ffa: complex numbers, license change, migration to Github'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-3746640200713546947</id><published>2009-05-19T06:21:00.000-07:00</published><updated>2009-05-19T10:16:53.853-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-2d'/><category scheme='http://www.blogger.com/atom/ns#' term='graphs'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>announcing cl-2d</title><content type='html'>Cl-2d is a two-dimensional graph library for Common Lisp.  It builds on &lt;a href="http://www.cliki.net/cl-cairo2"&gt;cl-cairo2&lt;/a&gt; and thus uses the Cairo library, which provides various backends, including pixel-based (eg PNG, X11) and vector-based (PDF, SVG, PS) ones.  It is meant solely for 2-dimensional plotting (hence the name).  Cl-2d is available from &lt;a href="http://github.com/tpapp/cl-2d/tree/master"&gt;Github&lt;/a&gt;.  The license is &lt;a href="http://www.cliki.net/LLGPL"&gt;LLGPL&lt;/a&gt;.

Cl-2d is designed to be extensible instead of providing a plethora of "canned" functions - the latter of course exist, but the emphasis is on flexibility.  Most plots used in scientific visualization are customized, and the purpose of this library is to make customization easy.  Plotting happens on frames, which are rectangular areas.  A DSL is available for splitting frames.  A frame combined with a mapping from plot coordinates to Cairo coordinates is a drawing area. Functions named plot-* take a frame, set up and return a drawing area (on which you can continue drawing), while draw-* functions draw on an existing drawing area.

This library is still under development, suggestions and contributions are welcome.  I mean to clear up the axes code and add contour plots soon.

See the example/ directory for a wide variety of examples.  Some of the example plots, converted from PDF, are shown below.

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShKzYP-t3aI/AAAAAAAAAB4/EP3L7D4Mc48/s1600-h/trend.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShKzYP-t3aI/AAAAAAAAAB4/EP3L7D4Mc48/s400/trend.png" alt="" id="BLOGGER_PHOTO_ID_5337525737575275938" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_eGqLjgUk4dc/ShKz1Cw0JPI/AAAAAAAAACI/EBSv9gT_RyU/s1600-h/sincos.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/_eGqLjgUk4dc/ShKz1Cw0JPI/AAAAAAAAACI/EBSv9gT_RyU/s400/sincos.png" alt="" id="BLOGGER_PHOTO_ID_5337526232243512562" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_eGqLjgUk4dc/ShKzlETCXrI/AAAAAAAAACA/6OVI54ge2zg/s1600-h/two-sided.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_eGqLjgUk4dc/ShKzlETCXrI/AAAAAAAAACA/6OVI54ge2zg/s400/two-sided.png" alt="" id="BLOGGER_PHOTO_ID_5337525957777579698" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_eGqLjgUk4dc/ShKz90l8XfI/AAAAAAAAACQ/1FyOXiQC1tc/s1600-h/image.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_eGqLjgUk4dc/ShKz90l8XfI/AAAAAAAAACQ/1FyOXiQC1tc/s400/image.png" alt="" id="BLOGGER_PHOTO_ID_5337526383058640370" border="0" /&gt;&lt;/a&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShK0It0nblI/AAAAAAAAACg/eVF7XxmNQC8/s1600-h/weighted.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShK0It0nblI/AAAAAAAAACg/eVF7XxmNQC8/s400/weighted.png" alt="" id="BLOGGER_PHOTO_ID_5337526570219695698" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShLpJWx0SwI/AAAAAAAAAC4/2_FJ53eXuwU/s1600-h/conditions.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShLpJWx0SwI/AAAAAAAAAC4/2_FJ53eXuwU/s400/conditions.png" alt="" id="BLOGGER_PHOTO_ID_5337584855330081538" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_eGqLjgUk4dc/ShK0Nwv5ECI/AAAAAAAAACo/DhBIOoR0IeE/s1600-h/weighted2.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://1.bp.blogspot.com/_eGqLjgUk4dc/ShK0Nwv5ECI/AAAAAAAAACo/DhBIOoR0IeE/s400/weighted2.png" alt="" id="BLOGGER_PHOTO_ID_5337526656904532002" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShK0TlDrVOI/AAAAAAAAACw/Dj0Qlh5CaYA/s1600-h/histogram.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/ShK0TlDrVOI/AAAAAAAAACw/Dj0Qlh5CaYA/s400/histogram.png" alt="" id="BLOGGER_PHOTO_ID_5337526756845507810" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-3746640200713546947?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/3746640200713546947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/announcing-cl-2d.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3746640200713546947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3746640200713546947'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/announcing-cl-2d.html' title='announcing cl-2d'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_eGqLjgUk4dc/ShKzYP-t3aI/AAAAAAAAAB4/EP3L7D4Mc48/s72-c/trend.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-2594877777127655652</id><published>2009-05-15T18:53:00.000-07:00</published><updated>2009-05-15T19:00:21.326-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>cl-cairo2 *context* wart fixed</title><content type='html'>I pushed an updated version of cl-cairo2 to the repository today.  The most important change is the fixing of a major design wart that was the result of a bad initial design choice.  Originally, cl-cairo2 functions had an optional context argument as the last argument, which defaulted to *context*.  This seemed to make sense at the time, it saved typing, but later on I realized it is very unLispy.  So now context is the first argument, and is never optional, *context* is gone.

I realize that this might break some code for people who are using cl-cairo2, and for this I apologize.  But it had to be done sooner or later, I kept putting it off but finally could not bear it any more.  Since I was using macros to generate most of the function definitions, effecting the change was a matter of minutes.  I also cleaned up the documentation a bit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-2594877777127655652?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/2594877777127655652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-context-wart-fixed.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2594877777127655652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2594877777127655652'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-context-wart-fixed.html' title='cl-cairo2 *context* wart fixed'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-7928401034380856571</id><published>2009-05-13T08:12:00.000-07:00</published><updated>2009-05-15T18:04:40.677-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='migration'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><title type='text'>cl-cairo2 migrated to github.com</title><content type='html'>I have migrated cl-cairo2 to github.com.  If you want to install it, just clone from the repository:&lt;pre&gt;git clone git://github.com/tpapp/cl-cairo2.git&lt;/pre&gt;You might have to create a symlink to the asd file in your ASDF &lt;code&gt;systems&lt;/code&gt; directory.  This is just a migration, no new code added.

The package is no longer ASDF-installable.  I have began to hate ASDF-install, it is more trouble than it is worth.  For those who insist, it is possible to download a tar.gz file from Github, but the name of the link changes with updates, so I can't put one on cliki.net.  Believe me, you are just better off pulling it from the git repository.  Eventually, I plan to add support for Mudballs, but not soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-7928401034380856571?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/7928401034380856571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-migrated-to-githubcom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7928401034380856571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7928401034380856571'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2009/05/cl-cairo2-migrated-to-githubcom.html' title='cl-cairo2 migrated to github.com'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-1366767271153399142</id><published>2008-11-14T08:17:00.000-08:00</published><updated>2008-11-14T08:26:10.581-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='job market'/><title type='text'>Job market: please go to my website</title><content type='html'>I am on the Economics job market this year.  If you googled for my name, you might have ended up  on my blog instead.  You can find my papers and CV on my &lt;a href="http://www.princeton.edu/%7Etpapp/"&gt;webpage&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-1366767271153399142?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/1366767271153399142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/11/job-market-please-go-to-my-website.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1366767271153399142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/1366767271153399142'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/11/job-market-please-go-to-my-website.html' title='Job market: please go to my website'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-2474722494707939507</id><published>2008-08-13T05:41:00.000-07:00</published><updated>2008-08-13T05:54:27.695-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><category scheme='http://www.blogger.com/atom/ns#' term='cairo'/><title type='text'>cl-cairo2 updates: win32 and mac extensions</title><content type='html'>Thanks to the contributions Kei Suzuki, cl-cairo2 underwent quite a few changes.  Most importantly, as Kei contributed Win32 and OS X-specific code, I decided to separate all parts of the library that use a GUI.  So now if you load &lt;tt&gt;cl-cairo2&lt;/tt&gt; (using ASDF), only GUI-independent parts of the library will be loaded.

If you need the rest, you will have to load &lt;tt&gt;cl-cairo2-x11&lt;/tt&gt;, &lt;tt&gt;cl-cairo2-mac&lt;/tt&gt; or &lt;tt&gt;cl-cairo2-win&lt;/tt&gt; using ASDF.  All of these put their functions in the &lt;tt&gt;:cl-cairo2&lt;/tt&gt; package, without creating a new one, so the organization of namespaces is simplified.  Also, cl-cairo2 and the GUI extensions are still packaged into a single tarball, which you can download or install directly using ASDF-Install.

Here are some screenshots contributed by Kei Suzuki:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_eGqLjgUk4dc/SKLYWgCCJJI/AAAAAAAAAAo/2Jd-rYbCYTE/s1600-h/lissajous-mac.png"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_eGqLjgUk4dc/SKLYWgCCJJI/AAAAAAAAAAo/2Jd-rYbCYTE/s400/lissajous-mac.png" alt="" id="BLOGGER_PHOTO_ID_5233983598025122962" border="0" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_eGqLjgUk4dc/SKLYpmKnaJI/AAAAAAAAAAw/m1cV80wt39k/s1600-h/lissajous-win.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_eGqLjgUk4dc/SKLYpmKnaJI/AAAAAAAAAAw/m1cV80wt39k/s400/lissajous-win.png" alt="" id="BLOGGER_PHOTO_ID_5233983926089246866" border="0" /&gt;&lt;/a&gt;

You can find the code for these in &lt;tt&gt;tutorial/lissajous.lisp&lt;/tt&gt; and &lt;tt&gt;tutorial/lissajous-win.lisp&lt;/tt&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-2474722494707939507?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/2474722494707939507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/08/cl-cairo2-updates-win32-and-mac.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2474722494707939507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2474722494707939507'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/08/cl-cairo2-updates-win32-and-mac.html' title='cl-cairo2 updates: win32 and mac extensions'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_eGqLjgUk4dc/SKLYWgCCJJI/AAAAAAAAAAo/2Jd-rYbCYTE/s72-c/lissajous-mac.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-3347232434142259506</id><published>2008-07-29T02:14:00.000-07:00</published><updated>2008-07-29T02:28:42.254-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='foreign arrays'/><title type='text'>FFA split into two packages</title><content type='html'>Besides providing `foreign friendly' arrays, my &lt;a href="http://www.cliki.net/ffa"&gt;FFA&lt;/a&gt; package contained a lot of functions that implement commonly used array operations, including elementwise algebra operations, array minima and maxima, etc.

Because these do not depend on &lt;a href="http://www.cliki.net/CFFI"&gt;CFFI&lt;/a&gt;, I decided I would put them into a separate package, named &lt;a href="http://www.cliki.net/array-operations"&gt;ARRAY-OPERATIONS&lt;/a&gt;, which is also installable with &lt;a href="http://www.cliki.net/ASDF-Install"&gt;ASDF-Install&lt;/a&gt;.  It contains a reimplementation of &lt;tt&gt;array-range&lt;/tt&gt;, and also a macro for vectorizing operations, called &lt;tt&gt;vectorize&lt;/tt&gt;:
&lt;pre&gt;
 (let ((a #(1d0 2d0 3d0))
       (b #(4d0 5d0 6d0))
       (c 0.25d0))
   (vectorize (a b)
              (+ a b c 0.25)))  ; =&gt; #(5.5d0 7.5d0 9.5d0)
&lt;/pre&gt;
&lt;tt&gt;(vectorize (&amp;rest vectors) expression)&lt;/tt&gt; sets up symbol macros so that vector names in &lt;tt&gt;vectors&lt;/tt&gt; refer to the appropriate element, then evaluates &lt;tt&gt;expression&lt;/tt&gt; repeatedly and returns the results as a vector.  It also has two keyword arguments: &lt;tt&gt;result-element-type&lt;/tt&gt; (which default to &lt;tt&gt;'double-float&lt;/tt&gt;) determines the element type of this vector, while &lt;tt&gt;into&lt;/tt&gt; places the results in one of the vectors instead (of course the two arguments are mutually exclusive).
&lt;pre&gt;
 (let ((a (vector 1 2 3)))
   (vectorize (a) (+ 1 (* a 2)) :into a)
   a)  ; =&gt; #(3 5 7)
&lt;/pre&gt;
Functions in the new package still strive to create arrays that are foreign-friendly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-3347232434142259506?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/3347232434142259506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/07/ffa-split-into-two-packages.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3347232434142259506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3347232434142259506'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/07/ffa-split-into-two-packages.html' title='FFA split into two packages'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-2536306412798201092</id><published>2008-06-26T05:19:00.000-07:00</published><updated>2008-06-26T11:08:02.438-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='cl-cairo2'/><category scheme='http://www.blogger.com/atom/ns#' term='cairo'/><title type='text'>changes in cl-cairo2</title><content type='html'>Johann Korndoerfer kindly submitted a patch that adds patterns to cl-cairo2, and also includes some code cleanup.  Here is the example Johann contributed to the tutorial, a rainbow created with patterns:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_eGqLjgUk4dc/SGOT9zDt4YI/AAAAAAAAAAc/hBgUiPXYdgA/s1600-h/pattern.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_eGqLjgUk4dc/SGOT9zDt4YI/AAAAAAAAAAc/hBgUiPXYdgA/s400/pattern.png" alt="" id="BLOGGER_PHOTO_ID_5216175483312267650" border="0" /&gt;&lt;/a&gt;

Thanks for the nice work, Johann!  I am happy that others also find cl-cairo2 useful.

cl-cairo2 still suffers from the elusive floating point bug (possibly in libcairo), I am still working on that.  In the meantime, you can work around that by not generating PS files directly, but converting them from PDF or SVG files.

Since &lt;a href="http://common-lisp.net/"&gt;common-lisp.net&lt;/a&gt; appears to be down, I took the opportunity to migrate the repository to git, which I am now hosting on my webpage.  I find git to be much more convenient than SVN, especially when it comes to ease of distribution.   As before, the package remains ASDF-installable.  &lt;span style="font-style: italic;"&gt;Update&lt;/span&gt;: the GIT repository is &lt;a href="http://www.princeton.edu/%7Etpapp/software/cl-cairo2.git"&gt;here&lt;/a&gt;, but can also be found from the &lt;a href="http://www.cliki.net/cl-cairo2"&gt;cliki page for cl-cairo2&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-2536306412798201092?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/2536306412798201092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/06/changes-in-cl-cairo2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2536306412798201092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/2536306412798201092'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/06/changes-in-cl-cairo2.html' title='changes in cl-cairo2'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_eGqLjgUk4dc/SGOT9zDt4YI/AAAAAAAAAAc/hBgUiPXYdgA/s72-c/pattern.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5966353302263378647.post-3261395480140017760</id><published>2008-06-26T01:48:00.000-07:00</published><updated>2008-06-26T02:13:37.324-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='numerical methods'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><title type='text'>announcement: minpack package</title><content type='html'>I have been using a simple solver (based on &lt;a href="http://en.wikipedia.org/wiki/Broyden%27s_method"&gt;Broyden's method&lt;/a&gt;) to finds roots of systems of nonlinear equation, but I encountered an ill-behaving class of problems that required heavier artillery.

Numerical methods have made a lot of progress in the last 50 years.  Methods presented in &lt;a href="http://www.amazon.com/Numerical-Methods-Economics-Kenneth-Judd/dp/0262100711"&gt;introductory&lt;/a&gt; &lt;a href="http://www.amazon.com/Applied-Computational-Economics-Finance-Miranda/dp/0262633094"&gt;textbooks&lt;/a&gt; are quite straightforward and very simple to code, but do not cut the mustard when it comes to more difficult situations (eg when you don't have a good initial guess, your function looks like the fjords of Norway, etc).

State of the art &lt;a href="http://www.amazon.com/Numerical-Optimization-Operations-Financial-Engineering/dp/0387303030"&gt;methods&lt;/a&gt; are powerful, but they are tricky to program: the main idea is easy to grasp, but one has to cover a lot of special cases (eg line-search, niceties of trust-region methods) so implementing them from scratch takes a lot of time (and debugging).  This is why most researchers rely on Fortran (or most recently, C) packages of these methods.

Common Lisp users generally have two alternatives if they don't want to implement these methods from scratch.  They can use the foreign code directly via the FFI, or translate the code using &lt;a href="http://portal.acm.org/citation.cfm?id=241694.241701"&gt;f2cl&lt;/a&gt;, which is available as part of &lt;a href="http://cliki.net/CLOCC"&gt;CLOCC&lt;/a&gt;.  I found the second option more appealing, for the following reasons:
&lt;ul&gt;
&lt;li&gt;fewer dependencies (no need to install/compile foreign libraries)
&lt;/li&gt;&lt;li&gt;no need to have callbacks (which are a pain in the neck)
&lt;/li&gt;&lt;li&gt;better integration into Lisp (eg you can use the condition system)
&lt;/li&gt;&lt;/ul&gt;
This is the first time I used f2cl, but it was quite easy to do, especially as CLOCC already has things set up for MINPACK.  I think that translating from Fortran is the way to go for some libraries, even though I recognize that for libraries like LAPACK where pure performance matters, FFI is the better option, especially as the functions there have simpler interfaces and don't need callbacks and complex condition handling.

MINPACK has already been available as part of CLOCC, but I had a hard time getting the whole thing work in SBCL, and it doesn't use ASDF, so I decided to package it to make it self-contained and ASDF-installable.  The extended version of the project I am working on will probably need homotopy methods, and I am looking forward to packaging that too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-3261395480140017760?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/3261395480140017760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/06/announcement-minpack-package.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3261395480140017760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/3261395480140017760'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/06/announcement-minpack-package.html' title='announcement: minpack package'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-7467872637100580777</id><published>2008-01-12T15:28:00.000-08:00</published><updated>2008-01-12T15:43:26.783-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='sparse linear system'/><category scheme='http://www.blogger.com/atom/ns#' term='sparse matrix'/><title type='text'>announcement: cl-sparsematrix</title><content type='html'>Lately I have been working on algorithms that solve &lt;a href="http://en.wikipedia.org/wiki/Hamilton-Jacobi-Bellman_equation"&gt;Hamilton-Bellman-Jacobi equations&lt;/a&gt; (that describe optimal control problems in continuous time) using the methods of Kushner and Dupuis, which involve sparse stochastic matrices.

The sparse matrix code has stabilized to the point that I cleaned it up today and decided to make it available as a library, in ASDF-installable form.  The package is called &lt;a href="http://www.cliki.net/cl-sparsematrix"&gt;cl-sparsematrix&lt;/a&gt;, and has the following features:
&lt;ul&gt;&lt;li&gt;generalized sparse matrices: elements don't have to be numbers, but can be any object (eg functions for parametrized sparse matrices), of course you have to define what you mean by zero in this case&lt;/li&gt;&lt;li&gt;utility functions for creating, mapping, traversing or copying sparse matrices&lt;/li&gt;&lt;li&gt;numerical operations that make sense for numerical sparse matrices (elementwise addition, subtraction and multiplication, row and column sums, multiplication of rows by corresponding elements in a vector, vector-matrix and matrix-vector products)&lt;/li&gt;&lt;li&gt;a simple interface for UMFpack for solving sparse systems (uses cffi and ffa)&lt;/li&gt;&lt;/ul&gt;You will find an introduction to the main concepts in the code as a PDF file in the documentation/ directory.

As usual, comments and suggestions are appreciated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-7467872637100580777?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/7467872637100580777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2008/01/announcement-cl-sparsematrix.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7467872637100580777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/7467872637100580777'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2008/01/announcement-cl-sparsematrix.html' title='announcement: cl-sparsematrix'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-6150874555535347279</id><published>2007-12-21T12:34:00.000-08:00</published><updated>2007-12-21T12:43:09.840-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='numerical methods'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='rootfinding'/><title type='text'>announcement: cl-numlib</title><content type='html'>&lt;a href="http://www.princeton.edu/%7Etpapp/software.html#cl-numlib"&gt;cl-numlib&lt;/a&gt; is a collection of functions I have been using for numerical methods.  I wrote functions for rootfinding, integration, univariate (Brent, Newton) and multivariate (BFGS) optimization, numerical integration, some functions for generating random numbers and a few utility and miscellaneous functions.

This is not a translation from Fortan: everything in the library was written from scratch.  There are two reasons for doing this: I learned a lot in the process, and I find it much easier to change things in the algorithms when I need to (when working with numerical methods, this is very useful).

There is no separate documentation, but all the functions are well-documented with examples and references where appropriate.

This library is in alpha stage, this means that I tested all my functions and found no bugs, but that of course doesn't exclude the possibility of there being any. Comments, suggestions and bugreports are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-6150874555535347279?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/6150874555535347279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2007/12/announcement-cl-numlib.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6150874555535347279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/6150874555535347279'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2007/12/announcement-cl-numlib.html' title='announcement: cl-numlib'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-5956872588168591840</id><published>2007-12-20T05:26:00.000-08:00</published><updated>2007-12-20T05:55:07.094-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='foreign arrays'/><category scheme='http://www.blogger.com/atom/ns#' term='cffi'/><title type='text'>announcement: ffa</title><content type='html'>While CFFI is very useful API for calling C functions, using foreign functions that expect pointers to arrays has always been something that is tricky to do in Common Lisp.  The two basic approaches are
&lt;ol&gt;&lt;li&gt;allocating a chunk of foreign memory and accessing it from Lisp as needed (as implemented in the &lt;a href="http://middleangle.com/rif/derifatives/category/common-lisp/"&gt;fnv package by rif&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;using native CL arrays and either copying them to/from foreign memory on demand, or taking advantage of implementation-specific features (eg pinning arrays) for direct access where possible&lt;/li&gt;&lt;/ol&gt;The first approach has some advantages, but I find that I am more comfortable with the second one, even if it leads to some loss in speed when the arrays are large and the implementation can't provide direct access for foreign functions.  My &lt;a href="http://www.princeton.edu/%7Etpapp/software.html#ffa"&gt;ffa&lt;/a&gt; (Foreign Friendly Arrays) package provides some convenience functions and macros that take advantage of implementation-specific features when available.

The most important features are the function &lt;code&gt;make-ffa&lt;/code&gt; and the macro &lt;code&gt;with-pointer-to-array&lt;/code&gt;. The function &lt;code&gt;make-ffa&lt;/code&gt; is similar to &lt;code&gt;make-array&lt;/code&gt;, except that it recognizes some CFFI types (eg &lt;code&gt;:double&lt;/code&gt;, &lt;code&gt;:uint32&lt;/code&gt;) and when asked to allocate a multidimensional array, it will do so by displacing a simple array which it creates first.  This allows direct access in some implementations, especially SBCL, while providing multidimensional arrays at the same time.

The macro &lt;code&gt;(with-pointer-to-array (array pointer cffi-type length direction) body)&lt;/code&gt; makes sure that the contents of &lt;code&gt;array&lt;/code&gt; will be mapped to a memory area designated by &lt;code&gt;pointer&lt;/code&gt; during the execution of &lt;code&gt;body&lt;/code&gt;.  &lt;code&gt;cffi-type&lt;/code&gt; determines the foreign element type, &lt;code&gt;direction&lt;/code&gt; tells the macro whether to copy the array to and/or from the memory area (so, for example, if you foreign function needs data but does not modify it, you don't need to copy it back), and by providing length, you ensure that the array contains as many elements as your foreign function needs.  When possible, no copying/conversion will take place (eg a double-float array in SBCL with cffi-type &lt;code&gt;:double&lt;/code&gt;), but the macro will take care of it automatically when needed (issuing some efficiency warnings when practical).

Displacing all arrays from a one-dimensional simple array also allows a few convenience functions, please check the code or the tutorial (provided in the package) for details.  Currently, only SBCL-specific code is provided, for all other implementations, the macro defaults to copying/conversion.  Contributions for other implementations and suggestions for improvements are welcome.

I would like to thank all those who commented on an earlier version of ffa on &lt;a href="http://groups.google.com/group/lisp-matrix-devel"&gt;lisp-matrix-devel&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-5956872588168591840?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/5956872588168591840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2007/12/announcement-ffa.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5956872588168591840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/5956872588168591840'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2007/12/announcement-ffa.html' title='announcement: ffa'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</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-5966353302263378647.post-9172498588304678932</id><published>2007-11-19T19:06:00.000-08:00</published><updated>2007-11-19T19:49:47.124-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bicycle'/><category scheme='http://www.blogger.com/atom/ns#' term='led'/><category scheme='http://www.blogger.com/atom/ns#' term='flashlight'/><category scheme='http://www.blogger.com/atom/ns#' term='light'/><title type='text'>sub-$40 bicycle light</title><content type='html'>As LED technology makes large advances, I decided to see if a simple LED flashlight could serve as a bicycle light.  Bicycle lights generally fall into two categories: some only allow you to be seen (red or white, serving as tail- or headlights, respectively), while the more sophisticated ones allow you to see, illuminating the road ahead.  Since LED lights are quite powerful at this point, I want the latter kind.

Before buying, I set up the following constraints:&lt;ul&gt;&lt;li&gt;price: the light has to be below $40, the cheaper the better.  I already have a pair of lithium-ion powered Dinotte lights, the front rated at 200L, I just need something to serve as a spare or when I have guests who want to bike at night (of course I would give the guest my Dinotte)
&lt;/li&gt;&lt;li&gt;batteries: it has to take standard batteries, AA or AAA.   Chargers and rechargeable batteries are cheap for these, while CR123 is expensive.   Also, if I forget to recharge, I can buy these easily at a convenience store anywhere&lt;/li&gt;&lt;li&gt;small form factor and light weight: I don't want to carry something bulky&lt;/li&gt;&lt;/ul&gt;I ended up getting a &lt;a href="http://www.cabelas.com/cabelas/en/templates/product/standard-item.jsp;jsessionid=3LBHYQFVTLDXZLAQBBKCCN3MCAEFKIWE?_DARGS=/cabelas/en/common/catalog/item-link.jsp_A&amp;amp;_DAV=MainCatcat20075-cat20091-cat20158&amp;amp;id=0045670517716a&amp;amp;navCount=4&amp;amp;podId=0045670&amp;amp;parentId=cat20158&amp;amp;masterpathid=&amp;amp;navAction=push&amp;amp;catalogCode=IH&amp;amp;rid=&amp;amp;parentType=index&amp;amp;indexId=cat20158&amp;amp;hasJS=true&amp;amp;_requestid=128573"&gt;3W LED flashlight from Cabela's&lt;/a&gt;, for $20+shipping.  The nominal output of these lights is 65 lumens, which comes from a single Luxeon LED.  Without further ado, here is a picture of the output (widest setting):

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_eGqLjgUk4dc/R0JT77bAJwI/AAAAAAAAAAM/U5Ng8S_BSXE/s1600-h/cabelas.png"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_eGqLjgUk4dc/R0JT77bAJwI/AAAAAAAAAAM/U5Ng8S_BSXE/s400/cabelas.png" alt="" id="BLOGGER_PHOTO_ID_5134758814184122114" border="0" /&gt;&lt;/a&gt;

The picture was taken at 2m (6.5ft), with the following camera settings: 1/12s exposure, f7.1, focal length 29mm.  I took care not to overexpose the photo.  If you look at it with a photo-processing application like Adobe Photoshop or &lt;a href="http://gimp.org/"&gt;the Gimp&lt;/a&gt;, you will notice a faint illumination (ranging from 20% to 5% of the peak) even outside the readily apparent white circle.

For comparison, here is the light of the Dinotte with the same settings:

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_eGqLjgUk4dc/R0JVIbbAJxI/AAAAAAAAAAU/2GthA78xzQ8/s1600-h/dinotte.png"&gt;&lt;img style="cursor: pointer;" src="http://bp1.blogger.com/_eGqLjgUk4dc/R0JVIbbAJxI/AAAAAAAAAAU/2GthA78xzQ8/s400/dinotte.png" alt="" id="BLOGGER_PHOTO_ID_5134760128444114706" border="0" /&gt;&lt;/a&gt;

Of course, the difference is obvious: the Dinotte is rated at 200 lumens, and has a much nicer lens to spread the light wider.  Nevertheless, I am satisfied with the flashlight's performance, especially considering its price.  Now I am experimenting with different mounting options (Twofish lockblocks should be arriving soon), and will post my experiences.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5966353302263378647-9172498588304678932?l=tkpapp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tkpapp.blogspot.com/feeds/9172498588304678932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://tkpapp.blogspot.com/2007/11/sub-40-bicycle-light.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/9172498588304678932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5966353302263378647/posts/default/9172498588304678932'/><link rel='alternate' type='text/html' href='http://tkpapp.blogspot.com/2007/11/sub-40-bicycle-light.html' title='sub-$40 bicycle light'/><author><name>Tamas K Papp</name><uri>http://www.blogger.com/profile/14669947082318259107</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_eGqLjgUk4dc/R0JT77bAJwI/AAAAAAAAAAM/U5Ng8S_BSXE/s72-c/cabelas.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
