<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc=" http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>briancarper.net (λ) (Tag: Origami)</title><link>http://briancarper.net/tag/49/origami</link><description>Some guy's blog about programming and Linux and cows.</description><item><title>Origami rocks, admit it.</title><link>http://briancarper.net/blog/origami-rocks-admit-it</link><guid>http://briancarper.net/blog/origami-rocks-admit-it</guid><pubDate>Tue, 20 Oct 2009 20:41:04 -0700</pubDate><description>&lt;p&gt;Why am I writing about origami here?  Partly because I'm excited.  I bought some &lt;a href=&quot;http://en.wikipedia.org/wiki/Methyl_cellulose&quot;&gt;methyl cellulose&lt;/a&gt; for the first time, and it's like some kind of wonder potion.  You dissolve it in water and smear it all over some paper and when it dries, the paper has gained magical origami powers.  Suddenly it's stronger, it's crisper, and it holds a fold better.  What a wonderful chemical.  It cost $25 for a tiny bag of the stuff, but that bag will probably last me a decade, so it's all good.&lt;/p&gt;

&lt;p&gt;The other reason I want to write about origami at the moment is because I feel it's my duty to spread the joys of origami to fellow geek-kind.&lt;/p&gt;

&lt;p&gt;Origami is a geek hobby if ever there was one.  There's more &lt;a href=&quot;http://langorigami.com/science/science.php4&quot;&gt;science&lt;/a&gt; behind it than most people realize.  Designing a model has close ties to &lt;a href=&quot;http://en.wikipedia.org/wiki/Circle_packing&quot;&gt;circle packing&lt;/a&gt;.  There's &lt;a href=&quot;http://langorigami.com/science/treemaker/TreeMkr40jp_s.pdf&quot;&gt;math involved (PDF)&lt;/a&gt; that I just barely understand.&lt;/p&gt;

&lt;p&gt;It's is deeply satisfying in exactly the same way computer programming is satisfying.  It's the satisfaction of taking a set of very simple rules and ideas, manipulating them in novel ways and coming up with something cool.&lt;/p&gt;

&lt;p&gt;Origami actually has a lot of similarities to programming.  There are primitives: mountain fold, valley fold.  They are combined into something like procedures: reverse folds, sink folds, pleats and crimps.  And those procedures are combined into more complex maneuvers, and when you combine them enough you get a finished model.  &lt;/p&gt;

&lt;p&gt;There are &quot;bases&quot; that are essentially design patterns: certain combinations of folds that are used over and over in different models.  All of these things can be put together in novel ways (recursively!).  A book of origami diagrams is essentially a book of algorithms.&lt;/p&gt;

&lt;p&gt;At the same time there are constraints: use a square, don't cut the paper, etc.  The size of the paper is a constraint.  The kind of paper you use is a constraint: some kinds of paper fold better than others.  In the same way people get a kick out of making &lt;a href=&quot;http://en.wikipedia.org/wiki/Demo_scene&quot;&gt;impressive videos in a few kilobytes of RAM&lt;/a&gt;, there's a great satisfaction in making a model with &lt;a href=&quot;http://origamigallery.net/model/scorpion&quot;&gt;a dozen flaps&lt;/a&gt; out of something that started with four corners.  The constraints define a universe of rules that's small enough to understand and master, yet large enough to leave a lot of possibilities.  The same square can be folded into a spider or an elephant or a race car or a man on a horse.&lt;/p&gt;

&lt;p&gt;But origami is different from programming because (obviously) it's 3D.  There's a lot of thinking involved, but there's also a bit of manual dexterity.  It's a good feeling to shape matter with your hands.  And when you're done you end up with something tangible in a way that a program isn't.  You can stick it on the shelf or give it away as a present.&lt;/p&gt;

&lt;p&gt;Most people don't understand how complex origami can get.  Check out the websites of &lt;a href=&quot;http://chosetec.darkclan.net/origami/&quot;&gt;Brian Chan&lt;/a&gt;, &lt;a href=&quot;http://www.folders.jp/&quot;&gt;KAMIYA Satoshi&lt;/a&gt;, &lt;a href=&quot;http://langorigami.com/index.php4&quot;&gt;Robert Lang&lt;/a&gt;, and &lt;a href=&quot;http://www.giladorigami.com/Gallery_default.html&quot;&gt;Gilad Aharoni&lt;/a&gt;.  It's all (usually) from a single uncut square.  It still amazes me what people can create.&lt;/p&gt;</description></item><item><title>Blog is still going strong</title><link>http://briancarper.net/blog/blog-is-still-going-strong</link><guid>http://briancarper.net/blog/blog-is-still-going-strong</guid><pubDate>Wed, 18 Mar 2009 22:01:11 -0700</pubDate><description>&lt;p&gt;After I implemented that silly CAPTCHA yesterday, the spam was stopped.  There's also a honeypot form field (it's hidden via CSS so humans don't know it's there, and if any bot POSTs text for that field, the data is rejected automatically).  It's silly and easily defeated, yet it stopped all 262 spam attempts since yesterday.  It looks like all the spam is for one site, but it's coming from a huge range of IPs.  So it's probably a botnet.  Thanks, MS Windows!&lt;/p&gt;

&lt;p&gt;I rewrote my whole CRUD layer so that I could use it for more than one database at once, and then rewrote my gallery code to take advantage, and now two hours later I have my &lt;a href=&quot;http://origamigallery.net&quot;&gt;origami gallery&lt;/a&gt; back up and running.  Both sites are running from the same JVM.  I wonder how many sites I can have going at once before the server melts into a puddle of Java-inflicted goo.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  PID PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
11338 16   0  512m 128m  12m S    0  0.3   0:28.33 java
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Good thing I have plenty of RAM on the server.  From looking at before and after shots of the memory usage, 66 MB is the JVM itself, and 40MB more is Jetty and Compojure and my code and all the dependencies.  Then the last ~20 MB or so is my database slurped into RAM.  So I can probably fit another few tens of thousands of posts and comments in here before I have to worry much.  The real test will be letting this thing run for a couple weeks and see how hard it leaks.&lt;/p&gt;</description></item><item><title>Clojure: 1, Common Lisp: 0</title><link>http://briancarper.net/blog/clojure-1-common-lisp-0</link><guid>http://briancarper.net/blog/clojure-1-common-lisp-0</guid><pubDate>Mon, 19 Jan 2009 02:56:04 -0800</pubDate><description>&lt;p&gt;Waaaay back in January 2008 I finished my &lt;a href=&quot;http://origamigallery.net&quot;&gt;origami gallery&lt;/a&gt; photo-blog, written from scratch in Common Lisp.  It took me about a month and half of struggling to get it going.  &lt;/p&gt;

&lt;h2&gt;Shattered Dreams&lt;/h2&gt;

&lt;p&gt;Ah, to be young again.  I was very enthusiastic about learning a Lisp, and Common Lisp was just about the best in town.  I'd recently read &lt;a href=&quot;http://www.gigamonkeys.com/book/&quot;&gt;Practical Common Lisp&lt;/a&gt; and maybe I hadn't imbibed the Kool-Aid yet, but I'd sipped it quite a bit.  &lt;/p&gt;

&lt;p&gt;Then reality came a'knocking.  SBCL couldn't run on my server's VPS without hacking and recompiling it (many times) to fix memory-mapping issues and get threading working.  Cleanly installing all the necessary libraries via ASDF was a problem and a half.  Learning Emacs and SLIME was just about the most painful computer experience I've ever been through.&lt;/p&gt;

&lt;p&gt;And those were the big things.  There were so many little things.  Dealing with pathnames in a language that was written before modern-day pathnames were semi-standardized.  Destructive vs. safe list operations.  Crappy hash-table support, to the point where I gave up and used lists for everything.  CL-SQL, which is pretty good but whose syntax and verbosity and quirkiness leaves much to be desired.  (I never got the CLOS stuff in CL-SQL working.)  &lt;/p&gt;

&lt;p&gt;Trying to wrap my head around macros enough to use CL-WHO effectively (never did get it right).  Trying to wrap my brain around CL packages and setting up ASDF to work with my own code (I got this working, but I couldn't tell you how at this point).  The list goes on and on.&lt;/p&gt;

&lt;p&gt;Once I finished the site, I was proud of slogging through it, but I was also exhausted.  Common Lisp is language that looks great on paper but it never clicked with me.  I set up some Debian init scripts on my server to make sure SBCL would start if my server restarted, and then I tried my best to forget about it.  I was burned out.&lt;/p&gt;

&lt;p&gt;Sometime a few weeks ago, my origami gallery stopped working.  Nothing but 404's.  I'm not sure when or why.  I tried running my script to restart the SBCL background process and it died with a Bible-and-a-half worth of errors in SBCL.  Sigh.  I didn't have the patience or the desire to fix it.&lt;/p&gt;

&lt;h2&gt;Clojure to the rescue&lt;/h2&gt;

&lt;p&gt;So, today on a whim I decided to re-write the site in &lt;a href=&quot;http://clojure.org&quot;&gt;Clojure&lt;/a&gt; to get it back up and running, using &lt;a href=&quot;http://github.com/weavejester/compojure/tree/master&quot;&gt;Compojure&lt;/a&gt;, a nice new Clojure web framework.&lt;/p&gt;

&lt;p&gt;I'm happy to say I'm already done.  &lt;a href=&quot;http://origamigallery.net&quot;&gt;My newly-Clojure-powered origami gallery, up and running.&lt;/a&gt;  Cheerfully untested in Internet Explorer, but works in Firefox and Opera.&lt;/p&gt;

&lt;p&gt;Start to finish the whole thing took me 8 hours.  That includes time writing that little thumbnail-scrolling strip at the bottom in JQuery, a bit of Javascript to hide and show the comments pane, a new stylesheet, and also a bit of time to resize and touch up a couple of new photos of new models to post.  The whole site weighs in at 350 lines of Clojure code, which includes an ORM-ish database layer, all of the HTML (s-exp style) and all the controller code.&lt;/p&gt;

&lt;p&gt;It was such a joy to write, compared to my first slog through Common Lisp.  But why?  I don't feel appreciably smarter than I was a year ago.  Why did it take me 8 hours this time but 2 months last time?  Probably thanks to Clojure itself.&lt;/p&gt;

&lt;p&gt;Deploying SBCL was one of my biggest roadblocks last time.  By contrast, installing Clojure is easy, even in its infancy where there are sometimes quirks with SLIME compatibility and such.  These problems are always minor and the mailing list is always on top of them.&lt;/p&gt;

&lt;p&gt;Installing libs is easy, you throw a jar into a directory and you're done.  I deployed everything to my Debian server in 15 minutes, which included installing the JVM for the first time, fetching Clojure and all required libs, compiling them, and setting up an environment.  (Pro-tip, there's a new bash launcher script in &lt;a href=&quot;http://code.google.com/p/clojure-contrib/source/checkout&quot;&gt;clojure-contrib&lt;/a&gt; now, which makes starting Clojure a bit easier and more standard.)&lt;/p&gt;

&lt;p&gt;How do you install MySQL support for Clojure?  You don't; you install it for Java.  There is &lt;a href=&quot;http://dev.mysql.com/usingmysql/java/&quot;&gt;official documentation&lt;/a&gt; on the MySQL website about getting it to work.  It's a single jar file you download and throw into your CLASSPATH.  Then get the SQL lib from clojure-contrib; 5 minutes of documentation reading, and I was done.  When's the last time you saw official documentation on a vendor's website for a Lisp?&lt;/p&gt;

&lt;p&gt;That's how it is with Clojure.  Compojure uses &lt;a href=&quot;http://www.mortbay.org/jetty/&quot;&gt;Jetty&lt;/a&gt; as its HTTP server.  Jetty is mature, stable, widely used and very well documented.  If we had to wait for someone to write an HTTP server for Clojure from scratch, where would we be?  I can't say enough times how great it is to be able to slurp up all the Java resources in the world and play with them in a Lisp.&lt;/p&gt;

&lt;p&gt;But it's the little things too, that make Clojure such a joy.  How do you concatenate strings in Clojure?  &lt;code&gt;(str string1 string2 string3)&lt;/code&gt;.  How do I access the name of a &quot;comment&quot; object?  &lt;code&gt;(:name comment)&lt;/code&gt;.  How do I set up Compojure so that when someone accesses the url &lt;code&gt;&quot;/&quot;&lt;/code&gt; it calls a function called index-page?  &lt;code&gt;(defservlet my-servlet (GET &quot;/&quot; (index-page)))&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;The Compojure HTML-generating library takes full advantage of Clojure literal syntax so that you can do things like &lt;code&gt;[:a {:href &quot;http://google.com&quot;} (str &quot;Goo&quot; &quot;gle&quot;)]&lt;/code&gt; to output an HTML link, using a mixture of vector and hash literals and function calls.  This alone makes it far more pleasant to use than CL-WHO (and much nicer than writing raw HTML).&lt;/p&gt;

&lt;p&gt;And so on.  Easy easy easy.  &lt;/p&gt;

&lt;h2&gt;Example one: What time is it?&lt;/h2&gt;

&lt;p&gt;Here is an issue that exemplifies the kind of hassle I went through in Common Lisp, that I never hope to go through again.  How can you get Common Lisp to tell you the current time, and store it in your database?  I use this when people post comments, to capture the time the comment was posted.  And some other things.&lt;/p&gt;

&lt;p&gt;You can read all about getting the current time in Common Lisp &lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_get_un.htm#get-universal-time&quot;&gt;here&lt;/a&gt; or &lt;a href=&quot;http://cl-cookbook.sourceforge.net/dates_and_times.html&quot;&gt;here&lt;/a&gt;.  Ignoring that there are two representations of time to choose from (universal vs. internal), the important thing to note is that neither is easily used for anything.  CL-SQL meanwhile has types &lt;a href=&quot;http://clsql.b9.com/manual/def-view-class.html&quot;&gt;&quot;wall-time&quot; and &quot;universal-time&quot;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So we'll go with universal time.  This seemed to be the most popular way to store a time in a database field, back when I researched it.  Universal time is a count of milliseconds since 1900.  How do you turn this into something a database can understand as a timestamp, or turn it into something readable for human beings?  Many languages stores times in a similar way as a huge integer, but most also give you really easy ways to turn millisecond counts into something legible.  Not in Common Lisp.  Instead, it's as simple as &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(multiple-value-bind
    (second minute hour date month year day-of-week dst-p tz)
    (get-decoded-time)
    (format t &quot;It is now ~2,'0d:~2,'0d:~2,'0d of ~a, ~d/~2,'0d/~d (GMT~@d)&quot;
          hour
          minute
          second
          (nth day-of-week *day-names*)
          month
          date
          year
          (- tz)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In other words, it's not simple.  At all.  Sure it's just a couple of utility functions (and learning the magic, cryptic FORMAT language) away, but multiply a couple of utility functions by the dozens upon dozens of times I have to do this kind of crap for a simple 300-line website, and it turns out I'm not making a website any longer, instead I'm ad-hoc re-writing Common Lisp to do what any language invented in the past two decades can do out of the box.  (e.g., in Ruby it's &lt;code&gt;Time.now&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I never did get this working entirely right for my site.  Timestamps worked and were stored in the DB, but they were never in the proper timezone for some reason.  I could've fixed it, but it was a low-priority problem below sundry other problems.&lt;/p&gt;

&lt;p&gt;So how do you do this in Clojure?  When I use the SQL lib from clojure-contrib, TIMESTAMP values in the database end up as Java Timestamp objects in Clojure by the time I see them.  You can read about it &lt;a href=&quot;http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Timestamp.html&quot;&gt;here&lt;/a&gt; in simple, easily-navigable javadoc.  I call &lt;code&gt;(.toString timestamp)&lt;/code&gt; and it gives me a human-readable version of the time.  Or I can just do &lt;code&gt;(str timestamp)&lt;/code&gt;.  Or I can use &lt;code&gt;.toLocaleString&lt;/code&gt; (deprecated) or use a &lt;code&gt;DateFormat&lt;/code&gt; object if I want anything fancier.  The end.  Because Java can do it, Clojure can do it.&lt;/p&gt;

&lt;h2&gt;Example two: Filenames&lt;/h2&gt;

&lt;p&gt;How do I get a list (or vector) of all the files in a directory?  For my photo-blog I use this to get lists of thumbnails for the photos.  In Clojure it was simple enough that I wrote it out myself; there may be a shorter way.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defn glob [dirname] (into [] (.list (new java.io.File dirname))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For Common Lisp you probably want to asdf-install &lt;a href=&quot;http://www.weitz.de/cl-fad/#list-directory&quot;&gt;CL-FAD&lt;/a&gt;, which &quot;&lt;em&gt;Returns a 'fresh' list of pathnames corresponding to the truenames of all files within the directory named by the non-wild pathname designator dirname.&lt;/em&gt;&quot;  What the hell does that even mean?  In fact I do know what it means, but only after plenty of reading.  Completely unnecessary reading, if I was using any other language.&lt;/p&gt;

&lt;p&gt;Just be careful with filenames, because CL has &lt;a href=&quot;http://www.gigamonkeys.com/book/files-and-file-io.html&quot;&gt;two ways of representing directories&lt;/a&gt;, and this also varies between implementations.  This is enough of a problem that a &lt;a href=&quot;http://www.gigamonkeys.com/book/practical-a-portable-pathname-library.html&quot;&gt;whole chapter of PCL&lt;/a&gt; is devoted to writing a library to fix it.&lt;/p&gt;

&lt;p&gt;I think the reason I got this project done so much more quickly this time is mostly because I'm using a better language for the job.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: hi Reddit.  Thanks for DDOS-murdering my server.  :)&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Yikes!</title><link>http://briancarper.net/blog/yikes-3</link><guid>http://briancarper.net/blog/yikes-3</guid><pubDate>Wed, 20 Feb 2008 23:49:25 -0800</pubDate><description>&lt;p&gt;My &lt;a href=&quot;http://origamigallery.net&quot;&gt;origami website&lt;/a&gt; server kept hitting a limit on &quot;privvmpages&quot;, which is a cap (by the VPS) on some aspect of system memory.  SBCL died with some interesting notes about heap exhaustion.  I already had to &lt;a href=&quot;http://briancarper.net/2008/01/26/sbcl-on-debian-sucks/&quot;&gt;hack SBCL&lt;/a&gt; even to get it to start on my server.  And now this. I'm running a VBulletin + a Rails app + my Lisp site but none of them are high-traffic and you'd think the server could handle it.  I figured I must be doing something wrong.&lt;/p&gt;

&lt;p&gt;Luckily lots of other people apparently were also doing it wrong.  Google for &quot;vps sbcl&quot; and you'll find plenty of people having difficulty running it.  Through googling I learned of the handy &lt;code&gt;ROOM&lt;/code&gt; function which tells you some things about SBCL's current memory usage.  And also &lt;code&gt;SB-EXT:GC&lt;/code&gt; which in SBCL appears to invoke the garbage collector immediately.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Dynamic space usage is:   72,748,936 bytes.
Read-only space usage is:      1,912 bytes.
Static space usage is:         2,736 bytes.
Control stack usage is:        1,244 bytes.
Binding stack usage is:          336 bytes.
Control and binding stack usage is for the current thread only.
Garbage collection is currently enabled.
etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Is 72MB good or bad?  I don't know, but I'd guess bad, given that my server was dying.  So next I went through all of the packages my package depended on, and loaded them manually one by one to see how much usage was increasing for each.  CL-WHO + CLSQL + CL-FAD + CL-PPCRE + HUNCHENTOOT were increasing memory usage by about 10MB total, apparently.  My own package, which does nothing but run my website, was increasing it another 21MB.  Ouch.  Clearly I was doing something very wrong.&lt;/p&gt;

&lt;p&gt;So then I started loading each of the functions in each of my own files one by one, in order, to try to account for those 21MB.  This is easy to do in Slime via &lt;code&gt;C-c C-c&lt;/code&gt;.  After each I invoked the GC and checked my memory usage again.  I noticed that one inconspicuous function was adding around 9MB to that number.  It was a function where I was doing a glob of a bunch of filenames, then removing every filename that matched the string &quot;thumbs&quot;.  Here's the relevant part:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(remove-if #'(lambda (p) (cl-ppcre:scan &quot;thumbs&quot;
                                        (namestring p)))
           (cl-fad:list-directory (merge-pathnames (name model)
                                                   *photo-dir*)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When I changed it to this, my memory usage went down by 9MB:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(let ((thumbs-regex (cl-ppcre:create-scanner &quot;thumbs&quot;)))
  (remove-if #'(lambda (p) (cl-ppcre:scan thumbs-regex
                                          (namestring p)))
             (cl-fad:list-directory (merge-pathnames (name model)
                                                     *photo-dir*))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes!  Still not sure what was going on there.  Perhaps it would be best if I didn't rely so heavily on regular expressions to begin with.&lt;/p&gt;

&lt;p&gt;I've heard said that Lisp can be dangerous because expensive things don't necessarily look expensive.  Code that looks short might macro-expand into enormous amounts of code and you may never notice.  Though I imagine the same can be true of any language, and normal function calls can just as easily hide a lot of complexity.  I can't blame Lisp, I can only blame myself for not profiling my code better.  Lesson learned to be more careful, I guess.  I just hope this helps fix my memory exhaustion problems.  Otherwise back to the drawing board.&lt;/p&gt;</description></item><item><title>RSS feed (Common Lisp)</title><link>http://briancarper.net/blog/rss-feed-common-lisp</link><guid>http://briancarper.net/blog/rss-feed-common-lisp</guid><pubDate>Mon, 18 Feb 2008 18:26:58 -0800</pubDate><description>&lt;p&gt;I made an &lt;a href=&quot;http://origamigallery.net/feed&quot;&gt;RSS 2.0 feed&lt;/a&gt; for my &lt;a href=&quot;http://origamigallery.net/&quot;&gt;origami gallery&lt;/a&gt; the other day.  Thanks to &lt;a href=&quot;http://weitz.de/cl-who/&quot;&gt;CL-WHO&lt;/a&gt; this is trivial.  Here's the complete code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;; RSS
(defun rss ()
  (cl-who:with-html-output-to-string (s nil :prologue &quot;&amp;lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;ISO-8859-1\&quot; ?&amp;gt;&quot;)
    (:rss :version &quot;2.0&quot; :|xmlns:atom| &quot;http://www.w3.org/2005/Atom&quot;
          (:channel (:title &quot;An Origami Gallery&quot;)
                    (:link &quot;http://origamigallery.net&quot;)
                    (:|atom:link| :href &quot;http://origamigallery.net/feed&quot; :rel &quot;self&quot; :type &quot;application/rss+xml&quot;)
                    (:description &quot;A photo gallery.  Of origami models.&quot;)
                    (loop for model in (all-models)
                          do (htm (:item (:title (str (fullname model)))
                                         (:link (str (absolute-url model)))
                                         (:guid  (str (absolute-url model)))
                                         (:description (str (clean-remarks (remarks model)))))))))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are other Common Lisp libraries to make RSS feeds, which may have made this even easier, but I like CL-WHO.&lt;/p&gt;

&lt;p&gt;Interesting about this code is how short it is.  CL-WHO is an example of embedding another language in Common Lisp (e.g. a domain specific language), in this case, XML or HTML.  &lt;/p&gt;

&lt;p&gt;XML in particular happens to map very nicely onto s-expressions, allowing nested tags and attribute/value pairs and whatnot.  Except that s-exps are far less verbose than XML, far nicer to type, and far easier to read in my opinion.  One quirk here is that CL-WHO uses keyword symbols for XML tag names (CL keyword symbols begin with a colon), and XML uses colons for namespaces.  To make a keyword symbol with a colon in the middle in CL, you have to surround it in pipes.  No big deal though.&lt;/p&gt;

&lt;p&gt;This kind of thing isn't entirely possible or quite as elegant in most other languages.  (Ruby does pretty good though.)  In PHP, for example, you can mix up PHP and HTML content, but the PHP interpreter doesn't parse the HTML or do anything interesting with it.  It just treats it as a bunch of strings; embedding PHP in HTML is just a shortcut for string concatenation.  &lt;/p&gt;

&lt;p&gt;You could write a library in PHP to generate XML code (and I'm sure such libraries exist) but they're either going to have some kind of functional / OO interface, which will make it very verbose and probably clunky to use in comparison to CL, or else it's going to be something like Smarty which actually isn't PHP at all but rather a separate language with its own parser and interpreter or compiler that itself happens to be written in PHP.  What you could not easily do is write PHP code that turns other PHP code into an XML document.&lt;/p&gt;

&lt;p&gt;But that's largely what CL-WHO does.  Because CL-WHO parses the s-exps that represent my XML data, if I forget a closing paren, Lisp will yell at me, so my XML is guaranteed to be well-formed.  CL-WHO doesn't verify that I'm using proper RSS tags in the proper places or anything but it could easily be extended to do that.  See &lt;a href=&quot;http://www.gigamonkeys.com/book/practical-an-html-generation-library-the-interpreter.html&quot;&gt;PCL&lt;/a&gt; for an HTML interpreter/compiler which can verify that you only use valid HTML tags, for example.&lt;/p&gt;

&lt;p&gt;CL-WHO also lets me change whether my XML attribute values are in single or double quotes, or whether I want to allow empty tags (as in old HTML) or require them all to be closed, and other such things.  CL-WHO can nicely indent my XML, or generate it unindented.&lt;/p&gt;

&lt;p&gt;And since this is all just Common Lisp, you see that I can embed a loop right in the middle of the XML s-exps, or do conditionals, or I could write a function that generates some or all these s-exps for me programatically.  Or any number of other things.  I have all of Common Lisp at my fingertips to create these s-exps.&lt;/p&gt;

&lt;p&gt;See also &lt;a href=&quot;http://www.defmacro.org/ramblings/lisp.html&quot;&gt;&quot;The Nature of Lisp&quot;&lt;/a&gt; which is a nice long discussion of how Lisp is a better XML than XML.  (And I do mean looong.  I haven't read the whole article myself, but enough to know it's pretty good.)&lt;/p&gt;</description></item><item><title>One benefit of a Lisp-driven website</title><link>http://briancarper.net/blog/one-benefit-of-a-lisp-driven-website</link><guid>http://briancarper.net/blog/one-benefit-of-a-lisp-driven-website</guid><pubDate>Mon, 11 Feb 2008 22:06:23 -0800</pubDate><description>&lt;p&gt;My &lt;a href=&quot;http://origamigallery.net/&quot;&gt;Common Lisp-powered origami photoblog&lt;/a&gt; is still up and running smoothly so far.  (I posted more models, go look, shameless plugs and so on and so forth.)  No major problems to report in the past couple weeks.&lt;/p&gt;

&lt;p&gt;One huge benefit (in my opinion) of a site run on Common Lisp is the way you can solve the &quot;admin control panel&quot; problem.  Most web site frameworks / blog engines / message boards have some control panel interface, for example the one I'm using to type this blog entry.&lt;/p&gt;

&lt;p&gt;Why are control panels necessary?  You could SSH to your server and run SQL queries directly to input your blog posts.  One reason we don't do this is because it bypasses the logic of your website.  We use a PHP form so that it can complain if you type a post with no title, or run a filter to convert your line-breaks to HTML tags, or do spell-checking, or whatever.  It does all these things before entering your data into the DB, and then when the DB does need to be updated, it updates it in a consistent way.  If multiple tables need to be updated, it doesn't forget to do them all.  Etc. etc.&lt;/p&gt;

&lt;p&gt;The problem I have with control panels is that due to limitations of web languages and how the internet works, these control panels must be run as web pages just like any other.  Meaning they're open and accessible to the world if you visit the right URL.  &lt;/p&gt;

&lt;p&gt;To solve this we start heaping on the passwords.  Above and beyond SQL client access and FTP access and shell account access, we make a brand new custom layer of user accounts and permissions.  Only we implement it using .htaccess files and SQL hacks and fragile HTTP connections and cookies and sessions.  And then we get to test how well we did by letting every script kiddie and crawler-bot in the world hammer on it at will.&lt;/p&gt;

&lt;p&gt;I agonized about how to make a &quot;control panel&quot; for my photo blog.  These things aren't easy to get right.  Eventually, I realized it wasn't necessary.  The REPL is my control panel.  I can implement the necessary logic as simple Lisp functions.  When I want to post a new model, I SSH to my server, fire up Emacs, connect to the Lisp running on my running server via local SLIME, and run an &lt;code&gt;ADD-MODEL&lt;/code&gt; function.  Simple.  Lisp automatically timestamps my posts, and checks for empty-string model names, and all the other good stuff you'd want from a control panel.  (Plus if it fails, I get a debugger.)&lt;/p&gt;

&lt;p&gt;What about authentication?  I get that for free.  SSH is my authentication.  Authentication is what SSH is made for and it's going to be far better at it than some web-page SQL-based hack-job I come up with.  I don't even have to remember a password, since I have certificates set up for passwordless login.  And there's no URL that points to my photo blog control panel, which is nice.&lt;/p&gt;

&lt;p&gt;What about letting multiple people log into the &quot;control panel&quot;?  Anyone you don't trust to SSH into a shell account usually shouldn't be trusted to log into a Wordpress or VBulletin control panel either in my opinion.  Run Lisp as a non-privileged user (probably should be doing that anyways, I am) and run SSH in a chroot if you really care.&lt;/p&gt;

&lt;p&gt;What about the typical web gallery feature of letting you upload an image and then having it automatically thumbnailed?  I wrote a two line shell script that uses ImageMagick (which is likely what a PHP-run gallery would be using anyways) to thumbnail all my photos locally, then rsyncs them to my server.  Why re-invent the wheel?  &lt;/p&gt;

&lt;p&gt;Couldn't Perl or Ruby or PHP do the same thing?  Well, Perl/Ruby/PHP don't run persistently on the server.  So it'd be a bit different.  Couldn't you write some standalone scripts to run from the commandline to insert new posts into your blog?  I suppose, but it surely wouldn't be as nice an interface as Slime in Emacs, unless you enjoy using bash as your text editor.  And have fun with quoting / escaping.  (&lt;code&gt;EDIT: As some readers reminded me, yes they can run persistently via Apache hackery.  And Rails has a &quot;console&quot;.  I stand corrected.&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;The REPL obviously isn't a solution to every problem.  If your authentication requirements are complex enough, you'll have to build something yourself.  And it's a problem if your users don't know Lisp (and yeah, that right there kills it for 99.999998% of the world).  Web-based control panels have the benefit of being &quot;so easy anyone can use them&quot;.&lt;/p&gt;

&lt;p&gt;But for my needs, and probably the needs of a great many websites run by one or two trusted Linux-savvy people who just need to be able to securely update the site once in a while, a few Linux tools + the REPL works beautifully.&lt;/p&gt;</description></item><item><title>Anti-climactic!</title><link>http://briancarper.net/blog/anti-climactic</link><guid>http://briancarper.net/blog/anti-climactic</guid><pubDate>Tue, 29 Jan 2008 03:09:50 -0800</pubDate><description>&lt;p&gt;&lt;a href=&quot;http://origamigallery.net/&quot;&gt;My origami gallery / photo blog.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I won't call it finished, since I plan to keep working on it and the code needs a major cleanup.  But hey, it's up and running and it displays photos, so it has fulfilled its purpose.  It's all Common Lisp top to bottom, too.  (Aside from JQuery.)  I need to make it so that it degrades nicely if you don't have Javascript enabled.  But that's all just HTML tweaks, very easy at this point.  Tested on Firefox2 and Firefox3, Opera9 and IE7.  Currently a tad broken in Konqueror but I'm getting there.  IE6 can bite me.&lt;/p&gt;

&lt;p&gt;I've been so busy working on the code for that site that I haven't had time to really start folding models to post there, other than a few to start off.  That'll change now.  It'll be nice to have some folding time.&lt;/p&gt;

&lt;p&gt;My current art/origami gallery on this site has some really, really bad photos in it, so I plan not to re-use most of those for the new site.  I am not a photographer, sadly.  But I found some tutorial somewhere about how to make a &quot;light box&quot;.  Essentially, cut a hole in a cardboard box, cover the hole with something translucent like white tissue paper, put a lightbulb over the hole, and curve a nice white piece of posterboard in the bottom of the box to use as a backdrop.  So easy even I could do it, and it cost me a total of $7 for a tiny desk lamp and some light bulbs.  But it's immensely improved the quality of my photos.  (Which isn't saying much.)&lt;/p&gt;

&lt;p&gt;Now the test is whether the server is still running tomorrow morning when I wake up.  Tomorrow or the next day, I'll post a summary of things I've learned on this trek into Common Lisp.&lt;/p&gt;</description></item><item><title>Yikes</title><link>http://briancarper.net/blog/yikes-2</link><guid>http://briancarper.net/blog/yikes-2</guid><pubDate>Fri, 14 Dec 2007 03:28:48 -0800</pubDate><description>&lt;p&gt;I bought two more domains today in preparation for a new site I'm making.  I realized today that I own six domain names, and none of them really serve any purpose.  How many domains do you need to own before they take away your nerd card and give you the platinum nerd card upgrade?&lt;/p&gt;

&lt;p&gt;I surely don't make any money from any of my sites.  In fact all they cost me a fair amount each year.  What is the motivation for making a blog, or a fansite, I wonder?  Does it just feel good to have a voice and to be heard?&lt;/p&gt;

&lt;p&gt;In any case, I now know how to set up Bind9 for multiple domains on a single machine.  I think.  This is the fun of running your own server and not having a clue what you're doing.  &lt;/p&gt;

&lt;p&gt;My new site is going to be a gallery for origami.  My crusty old gallery of origami photos is by far the most popular section of this site even though I never ever update it.  And even though I can't take a good photo to save my life.  So I'm going to split it off into a new site.&lt;/p&gt;

&lt;p&gt;I'm unsure what photoblog software to use.  &lt;a href=&quot;http://www.pixelpost.org/&quot;&gt;Pixelpost&lt;/a&gt; is very minimalistic and looks good, but it's a bit too inflexible for my needs.  And I'm so sick of reading/writing PHP that I don't want to make it work for me.  Today I was reading about mod_lisp and &lt;a href=&quot;http://common-lisp.net/project/cl-weblocks/&quot;&gt;Weblocks&lt;/a&gt;, and toyed with the idea of writing up my own photoblog software in Common Lisp using that or one of the other Lisp web frameworks.  It's a thought.  It'd be a fun way to learn the language.  I have to see how much time I have.&lt;/p&gt;</description></item><item><title>Origami cactuar yay</title><link>http://briancarper.net/blog/origami-cactuar-yay</link><guid>http://briancarper.net/blog/origami-cactuar-yay</guid><pubDate>Sat, 28 Oct 2006 00:34:14 -0700</pubDate><description>&lt;p&gt;I've been trying off-and-on to make an origami &lt;a href=&quot;http://images.google.com/images?q=cactuar&quot;&gt;Cactuar&lt;/a&gt; for a long time.  I spent a few hours on it each day this week and finally came up with something half-respectable.  I'm proud of it, it's approximately the second original model I've ever made.  Maybe I should post a crease pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://origamigallery.net/model/cactuar&quot;&gt;&lt;img src=&quot;http://origamigallery.net/thumbs/cactuar/01&quot; alt=&quot;cactuar&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Origami woes</title><link>http://briancarper.net/blog/origami-woes</link><guid>http://briancarper.net/blog/origami-woes</guid><pubDate>Sat, 21 Oct 2006 22:52:04 -0700</pubDate><description>&lt;p&gt;I'm to the point where I can make just about anything if I have diagrams for it, and I can make a lot of things given a crease pattern and a lot of time.  But when it comes to making up my own stuff, I still without exception fail horribly.  There are two or three things I've either never seen an origami version of, or don't have the diagrams for, that I'd love to make on my own.  But I can't even seem to scratch the surface in starting to make them.  Oh how I've tried.&lt;/p&gt;

&lt;p&gt;My 12th grade calculus teacher said that you can't teach someone creativity, and there are certain things that you either get or you don't.  I'm not sure if I buy that.  If there are rules that govern something, if there's any kind of pattern that says &quot;if X applies here it also applies over there&quot;, then you can learn it and use it in the future.  But I have a fear that there are certain things where there are no rules.  Creativity may be loosely defined as venturing into territory where the rules are not yet known and no one has ever been before.  Consistently being creative means consistently moving through territory where the rules are unknown, which is rather functionally equivalent to living in a world where there are no rules.  Which is probably my worst nightmare.&lt;/p&gt;

&lt;p&gt;But my goal isn't to forge new mathematical systems.  There are thousands of years of tradition here and in the past hundred years there's been tons of formal mathematical progress.  All I want is to tweak things that I and other people already know and end up with a bit of a different result.  It's not 100% creativity.  In fact it's mostly not at all.  So I have hope that no matter how bad I am at it, I can learn this.  Assuming that &quot;creativity can't be learned&quot; is at all valid in the first place.&lt;/p&gt;</description></item><item><title>Dollar bill origami</title><link>http://briancarper.net/blog/dollar-bill-origami</link><guid>http://briancarper.net/blog/dollar-bill-origami</guid><pubDate>Mon, 19 Jun 2006 10:22:05 -0700</pubDate><description>&lt;p&gt;This site was impressive enough that I just had to post a link: &lt;a href=&quot;http://www.flickr.com/photos/grechuh/&quot;&gt;dollar bill origami&lt;/a&gt;.  Someone at origami club this week mentioned that they'd seen a dollar bill flower in a pot, but never could find the diagrams.  There is a picture of a similar model at this gallery.  I do believe I can reverse-engineer it, which should make a few people happy at least.&lt;/p&gt;</description></item></channel></rss>

