<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Technomancy</title>
  <id>tag:technomancy.us,2007:blog/</id>
  <link href="http://technomancy.us/feed/atom" rel="self" type="application/atom+xml"/>
  <link href="http://technomancy.us/" rel="alternate" type="text/html"/>
  <updated>2010-07-26T10:18:53Z</updated>

  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20we%20watch%20while%20a%20veritable%20tower%20of%20babel%20is%20constructed</id>
    <published>2010-07-24T22:45:24Z</published>
    <updated>2010-07-24T22:45:24Z</updated>

    <link href="http://technomancy.us/139" rel="alternate" type="text/html"/>
    <title>in which we watch while a veritable tower of babel is constructed</title>
    <content type="html">
      &lt;p&gt;This week I was lucky enough to attend
  the &lt;a href=&quot;http://emerginglangs.com&quot;&gt;Emerging Languages&lt;/a&gt;
  conference, a special event nestled snugly in a corner of
  O'Reilly's
  &lt;a href=&quot;http://oscon.com&quot;&gt;OSCON&lt;/a&gt; open source
  conference. Emerging Languages brought together language designers
  and implementors together to share the things that made their
  languages unique and to cross-pollinate ideas.&lt;/p&gt;

&lt;img src=&quot;/i/pod-power.jpg&quot; alt=&quot;Rich Hickey on Pods&quot; /&gt;

&lt;p&gt;The presentations
    covered &lt;a href=&quot;http://p.hagelb.org/emerginglangs.org.html&quot;&gt;a
    wide variety of languages&lt;/a&gt;. The talk on Go was interesting in
    that it wasn't so much about Go as about the historical heritage
    of Go and the languages that led to it. A lot of the interesting
    ideas there came out of Tony
    Hoare's &lt;a href=&quot;http://www.usingcsp.com/&quot;&gt;Communicating
    Sequential Processes&lt;/a&gt; paper, which looks fascinating. The
    talk
    on &lt;a href=&quot;http://futureboy.homeip.net/frinkdocs/&quot;&gt;Frink&lt;/a&gt;
    was a delightful romp through the esoteric and very &lt;i&gt;human&lt;/i&gt;
    world of unit calculation, though the licensing issues
    surrounding that language rule it out for most uses. It's been a
    while since I've done web work, but the talk
    on &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;CoffeeScript&lt;/a&gt;
    made me hope that I never have to write another line of
    Javascript. I also got to see Charlie present
    on &lt;a href=&quot;http://mirah.org&quot;&gt;Mirah&lt;/a&gt;, formerly Duby, which
    I've &lt;a href=&quot;/134&quot;&gt;posted about before&lt;/a&gt;: a language that
    gives you low-level bytecode-equivalent output to Java but
    reduces the pain/verbosity by offering a more reasonable syntax
    and type inference.&lt;/p&gt;

&lt;p&gt;The second day started off strong with an engaging demo of the visual
  &lt;a href=&quot;http://research.microsoft.com/en-us/projects/kodu/&quot;&gt;Kodu&lt;/a&gt;
  language. It's unique in that it's designed to run on XBox
  consoles and can be programmed entirely through the controller by
  manipulating icons. Once again there are licensing issues and it
  won't run on anything but Windows or an XBox, but in this case the
  developers are actively working towards remedying the
  problem. They have clearly put a lot of thought and research into
  keeping it engaging especially for kids.&lt;/p&gt;

&lt;p&gt;After this Rich Hickey presented on
  a &lt;a href=&quot;http://clojure.org&quot;&gt;Clojure&lt;/a&gt; feature tentatively
  called Pods, which are the new name for an experiment he had
  discussed much earlier called cells. The gist is that
  while &lt;a href=&quot;/132&quot;&gt;transients&lt;/a&gt; can be a boon to performance,
  they introduce mutability (albeit very constrained mutability)
  outside the reference model. Pods separate out a very clear
  reference policy where you're always dealing with persistent
  values coming in and out, and the change happens isolated inside
  the pod. (I posted a link to the above photo in the Clojure IRC
  channel, which caused it to erupt in cries of &quot;what are pods?&quot;
  and &quot;where's the documentation for this?&quot;&amp;mdash;a reminder that
  there are many Clojurians who feel the need to constantly stay
  abreast of every latest change no matter how recent.)&lt;/p&gt;

&lt;p&gt;Another highlight of the second day was the talk
  on &lt;a href=&quot;http://factorcode.org&quot;&gt;Factor&lt;/a&gt;, a modern cousin to
  Forth with an excellent compiler and nice tooling. Factor's been
  on my radar for a while since stack-based languages really sound
  like an interesting twist to language design, and everything I
  read about their compiler seems to indicate it's very cutting-edge
  and well-designed. Factor was also the only language presented I
  want to learn that isn't hosted; that is, it compiles straight to
  the metal. The demo focused on showing some the ways that Factor
  retains an astonishing amount of flexibility and dynamicity even
  though it compiles to very fast machine code. The Emacs
  integration &lt;a href=&quot;http://factor-language.blogspot.com/2009/01/screencast-editing-factor-code-with.html&quot;&gt;via
  FUEL&lt;/a&gt; also impressed me.&lt;/p&gt;

&lt;p&gt;There
  were &lt;a href=&quot;http://olabini.com/blog/tag/emerging-languages/&quot;&gt;many,
  many more languages&lt;/a&gt; presented; they came at such a rate that if
  you blinked you'd look up to see the presentation half-through
  already. On the whole this was helpful since it forced presenters
  to focus on a &quot;hook&quot; or two to get you interested enough to dig
  deeper rather than give an overview of features which could easily
  be read from a web site, but such a wild ride left everyone with a
  minor case of mental whiplash.&lt;/p&gt;

&lt;p&gt;It's been a while since I've attended an event that showcased this
  level of energy. I hope to look forward to attending Emerging
  Languages 2011.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20readers%20are%20pointed%20elsewhere</id>
    <published>2010-06-28T00:35:28Z</published>
    <updated>2010-06-28T00:35:28Z</updated>

    <link href="http://technomancy.us/138" rel="alternate" type="text/html"/>
    <title>in which readers are pointed elsewhere</title>
    <content type="html">
      &lt;p&gt;Michael Fogus, co-author of the excellent forthcoming
book &lt;a href=&quot;http://joyofclojure.com/&quot;&gt;The Joy of Clojure&lt;/a&gt;, has
posted &lt;a href=&quot;http://blog.fogus.me/2010/06/28/take-8-phil-hagelberg/&quot;&gt;a
lengthy micro-interview with your humble author&lt;/a&gt; on his
blog. Have a look!&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20is%20divulged%20more%20detail%20than%20is%20generally%20interesting</id>
    <published>2010-05-11T21:20:17Z</published>
    <updated>2010-05-11T21:20:17Z</updated>

    <link href="http://technomancy.us/137" rel="alternate" type="text/html"/>
    <title>in which is divulged more detail than is generally interesting</title>
    <content type="html">
      &lt;p&gt;So this post is ridiculously self-indulgent; you've been
  warned. I've mostly written it out here for my future self to look
  back on in a mix of amusement and embarassment. It's just a
  write-up of the tools I use daily in the style
  of &lt;a href=&quot;http://usesthis.com/&quot;&gt;the interviews at
  usesthis.com&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;What hardware do you use?&lt;/h4&gt;

&lt;p&gt;I use a Thinkpad X200s primarily. It's hard to find a machine
  that's acceptably light (2.4 lbs/1.1 kg) but still has a decent
  resolution; most &quot;small&quot; laptops these days have a vertical
  resolution no greater than my phone, which would be embarrassing for
  me to use. The Thinkpad has the best keyboard of any laptop; I
  appreciate the crisp response. It also has an integrated trackpoint,
  which is nice in that you can move the pointer without taking your
  hands off the home row, but I try to avoid it as much as
  possible. I'm much more productive when using 100% keyboard
  commands. Sometimes I'll just pluck the trackpoint out entirely just
  to make sure I'm not using it without thinking.&lt;/p&gt;

&lt;p&gt;I work from coffee shops frequently since I have a remote job,
  but when I'm
  in &lt;a href=&quot;http://www.flickr.com/photos/technomancy/tags/laboratory/&quot;&gt;my
  code lab&lt;/a&gt; I use a standing desk with an external 23-inch
  monitor. I rotate the monitor to portrait orientation when I'm not
  remote pairing
  with &lt;a href=&quot;http://tmux.sourceforge.net/&quot;&gt;tmux&lt;/a&gt;. I have a
  recliner next to the desk onto which I fall back to for a couple
  hours out of the day. While I'm standing I wear what has been
  affectionately
  termed &lt;a href=&quot;http://www.flickr.com/photos/technomancy/4397554484/&quot;&gt;&quot;keyboard
  pants&quot;&lt;/a&gt;. It's a Kinesis Freestyle with kneepads attached. The
  kneepads are worn significantly above the knee&amp;mdash;the idea is
  to allow myself to type in as neutral of a position as
  possible. My arms are relaxed in a downward position, and my
  wrists are totally straight. It takes some getting used to, but
  from an RSI perspective it's quite beneficial. It also just feels
  great not to be sitting all day.&lt;/p&gt;

&lt;p&gt;I keep a Nexus One phone in my pocket. As far as I know it's the
  only major phone currently available that's designed to be
  rootable by the end user, and hence the only phone I am
  comfortable purchasing. As a nice bonus it also happens to
  be &lt;a href=&quot;http://technomancy.us/134&quot;&gt;one of the best phones
  available&lt;/a&gt;, though it seems absurd to call it a phone. I hardly
  make any actual voice calls on it, though when I do it's VOIP
  calling through &lt;a href=&quot;http://sipdroid.org/&quot;&gt;Sipdroid&lt;/a&gt;. I
  have &lt;a href=&quot;http://www.cyanogenmod.com/&quot;&gt;CyanogenMod&lt;/a&gt;
  installed, which has a really nice auto-tether over USB.&lt;/p&gt;

&lt;h4&gt;And what about software?&lt;/h4&gt;

&lt;p&gt;I start with a boring old Ubuntu GNOME install. To my
  embarrassment I actually even use metacity, the default window
  manager. My secret sauce is
  &lt;a href=&quot;http://burtonini.com/blog/computers/devilspie/&quot;&gt;devilspie&lt;/a&gt;,
  which is a rules engine for window placement and behaviour. I
  &lt;a href=&quot;http://github.com/technomancy/dotfiles/blob/master/.devilspie/max.ds&quot;&gt;fullscreen
  and undecorate all my commonly-used programs&lt;/a&gt; and have certain
  programs only show up on a given virtual desktop. It's flexible enough
  to trick people into thinking I use &lt;a href=&quot;http://xmonad.org/&quot;&gt;a real
  WM&lt;/a&gt;. My other main desktop-level customization
  is &lt;a href=&quot;http://www.nongnu.org/xbindkeys/xbindkeys.html&quot;&gt;xbindkeys&lt;/a&gt;,
  a little app that embeds a Scheme interpreter to configure
  bindings. This is nice because it decouples them from the window
  manager. The only part of GNOME I use on a regular basis is the
  panel. I like having CPU/network/memory graphs available so I can tell
  when my machine is hard at work. The panel wifi tool is pretty handy
  too.&lt;/p&gt;

&lt;p&gt;Apart from that it's Emacs, Emacs, and Emacs. I am mostly able to
  maintain the illusion that Emacs is the only program I actually
  interact with regularly. I generally have four or five instances
  running at once which is uncommon; most Emacs users keep single
  instances with uptimes in the weeks range. I use this as a
  namespacing technique to keep real work separated from
  play/chat/mail. My staple modes
  are &lt;a href=&quot;http://alexvollmer.com/posts/2009/01/18/meet-magit/&quot;&gt;magit&lt;/a&gt;, &lt;a href=&quot;http://github.com/technomancy/clojure-mode&quot;&gt;clojure-mode&lt;/a&gt;, &lt;a href=&quot;http://common-lisp.net/project/slime/&quot;&gt;slime&lt;/a&gt;,
  &lt;a href=&quot;http://www.emacswiki.org/emacs/ParEdit&quot;&gt;paredit&lt;/a&gt;, &lt;a href=&quot;http://orgmode.org/&quot;&gt;org-mode&lt;/a&gt;,
  and &lt;a href=&quot;http://www.emacswiki.org/emacs/ERC&quot;&gt;erc&lt;/a&gt;. I used
  to waver
  between &lt;a href=&quot;http://emacs-jabber.sourceforge.net/&quot;&gt;jabber.el&lt;/a&gt;
  or &lt;a href=&quot;http://www.emacswiki.org/emacs/ELIM&quot;&gt;elim&lt;/a&gt; and
  leaving the embrace of Emacs for something like Pidgin, which was
  not pleasant at all. But now I'm pretty settled
  on &lt;a href=&quot;http://www.bitlbee.org/main.php/news.r.html&quot;&gt;bitlbee&lt;/a&gt;,
  which allows you to connect to your IM accounts via an IRC
  client.&lt;/p&gt;

&lt;p&gt;I have all my Emacs config (accumulated over years of obsessive
  tweaking) bundled up as
  the &lt;a href=&quot;http://github.com/technomancy/emacs-starter-kit&quot;&gt;Emacs
  Starter Kit&lt;/a&gt;. Lots of other developers use this as a base off
  which to build or just to steal ideas from, which I love. (It's a
  little funny to get bug reports for your own dotfiles.) I try to
  save all my other config in git as well in order to make it easy
  for me to get up and running quickly on a new machine.&lt;/p&gt;

&lt;p&gt;The other key to maintaining the Emacs-all-the-time illusion
  is &lt;a href=&quot;http://conkeror.org&quot;&gt;Conkeror&lt;/a&gt;. Emacs doesn't have
  a modern web browser in it yet, so this is an attempt to trick
  Mozilla Xulrunner into thinking it's Emacs. Apart from being
  implemented in JS instead of lisp, it's a very good
  approximation. The buffer switcher features completion that's far
  better than anything I've used in a mainstream browser, and its
  mouseless browsing support is excellent. It's also very stable as
  long as you don't have any garbage plugins like Adobe Flash
  installed. &lt;strike&gt;Its only flaw is being based on Gecko rather than
  Webkit. I've experimented a bit with mouseless extensions for
  Chromium, but the extension mechanism in that browser is crippled
  in comparison to what's possible in Mozilla, so while the speed
  boost was nice, this ended up being very frustrating in
  practice.&lt;/strike&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: I recant my complaints regarding the speed of
  Gecko in light of
  &lt;a href=&quot;http://nightly.mozilla.org/&quot;&gt;the latest Mozilla
  nightlies&lt;/a&gt;; they are absolutely zippy. I am no longer tempted
  to go back to Chromium. You can use Firefox rather than Xulrunner
  to launch Conkeror by doing &lt;kbd&gt;bin/firefox -app
  ~/src/conkeror/application.ini&lt;/kbd&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately I need to use skype for work. While I've been
  pretty impressed with its ability to use a very limited amount of
  bandwidth, it's quite unstable, and its UI is very awkward. Since
  it's not free software there's very little hope of this improving
  soon. The one thing that eases this pain is the skype plugin
  for &lt;a href=&quot;http://do.davebsd.com/&quot;&gt;gnome-do&lt;/a&gt;. It allows calls
  to be initiated from the keyboard. While I am a fan of the ideas
  behind gnome-do, this is the only thing I use it for since in
  general Emacs does a better job at the kinds of things it
  does.&lt;/p&gt;

&lt;h4&gt;What would your dream setup be?&lt;/h4&gt;

&lt;p&gt;I really wish I could buy a modern laptop with a 4:3 aspect
  ratio. I find the loss of vertical space in widescreens very
  annoying for anything other than watching movies. Apart from that
  the Thinkpad X200s is nearly everything I want in a laptop. In a
  perfect world I would have a battery with the weight of a 4-cell
  and the capacity of a 9-cell. Half the weight of my laptop is the
  battery.&lt;/p&gt;

&lt;p&gt;I recently switched to using gmail in the browser, and while it's
  decent for everyday mail it is markedly inferior to gnus for mailing
  lists. I'm only using it because it syncs with my phone, and setting up
  offlineimap to work with gnus and gmail sounds like a lot of work. This
  is definitely the least-satisfying part of an all-Emacs setup, at least
  if you want to read mail on a mobile device.&lt;/p&gt;

&lt;p&gt;I imagine if they ever get
  the &lt;a href=&quot;http://senseboard.com&quot;&gt;senseboard&lt;/a&gt; working it will
  be a pretty sweet innovation. I could also use a HUD for my phone
  for when I'm in the car. Or possibly on my sunglasses for when I'm
  just walking around; you know... I'm not picky.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20a%20year%20is%20reflected%20upon</id>
    <published>2010-04-24T22:44:44Z</published>
    <updated>2010-04-24T22:44:44Z</updated>

    <link href="http://technomancy.us/136" rel="alternate" type="text/html"/>
    <title>in which a year is reflected upon</title>
    <content type="html">
      &lt;p&gt;It's been &lt;a href=&quot;/124&quot;&gt;a year&lt;/a&gt; since
    the &lt;a href=&quot;http://peepcode.com/products/functional-programming-with-clojure&quot;&gt;PeepCode
    screencast on Clojure&lt;/a&gt; was released. While it's aged
    surprisingly well given the relative youth of the Clojure
    language (1.0 hadn't even been released at the time), there are
    a few things that could use some updates. I thought it would be
    helpful for me to step
    through &lt;a href=&quot;http://github.com/technomancy/mire&quot;&gt;Mire&lt;/a&gt;,
    the sample project that's built up in the screencast, and update
    it to reflect the changes that have since occurred in the
    Clojure ecosystem.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;defproject mire &lt;span class=&quot;string&quot;&gt;&quot;0.13&quot;&lt;/span&gt;
  &lt;span class=&quot;builtin&quot;&gt;:description&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;A multiuser text adventure game/learning project.&quot;&lt;/span&gt;
  &lt;span class=&quot;builtin&quot;&gt;:main&lt;/span&gt; mire.server
  &lt;span class=&quot;builtin&quot;&gt;:dependencies&lt;/span&gt; [[org.clojure/clojure &lt;span class=&quot;string&quot;&gt;&quot;1.2.0-master-SNAPSHOT&quot;&lt;/span&gt;]
                 [org.clojure/clojure-contrib &lt;span class=&quot;string&quot;&gt;&quot;1.2.0-SNAPSHOT&quot;&lt;/span&gt;]]
  &lt;span class=&quot;builtin&quot;&gt;:dev-dependencies&lt;/span&gt; [[leiningen/lein-swank &lt;span class=&quot;string&quot;&gt;&quot;1.2.0-SNAPSHOT&quot;&lt;/span&gt;]
                     [leiningen-run &lt;span class=&quot;string&quot;&gt;&quot;0.3&quot;&lt;/span&gt;]]&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

&lt;h4&gt;&lt;a href=&quot;http://github.com/technomancy/mire/commit/8dd4a5dd&quot;&gt;Commit
    8dd4a5d&lt;/a&gt;: Moving to Leiningen&lt;/h4&gt;

&lt;p&gt;Probably the most obvious thing about the Mire project as it's
  seen in the screencast that shows its age is its ad-hoc
  build. (Step 12 of the screencast) At the time there weren't any
  good ways to build and distribute Clojure projects, so Mire simply
  contained a copy of Clojure and Contrib in its git repository and
  included a shell script to perform compilation and
  packaging. Apart from being just generally tacky, this actually
  caused the repository to bloat up by 16MB due to the fact that git
  is really lousy at storing binary files.&lt;/p&gt;

&lt;p&gt;Kids these days have it so
  easy&amp;mdash;&lt;a href=&quot;http://github.com/technomancy/leiningen&quot;&gt;Leiningen&lt;/a&gt;
  is generally used for managing Clojure projects now. I'm not going
  to go into detail about this here since it's covered well
  elsewhere, namely in the readme as well as
  the &lt;a href=&quot;http://vimeo.com/8934942&quot;&gt;Full Disclojure screencast
  on project management&lt;/a&gt;. (Warning: flash video; a downloadable
  version is available if you create a Vimeo account.) There are
  other alternatives, but this is certainly the most
  straightforward. Leiningen gives you a basic skeleton to work
  from (&lt;kbd&gt;lein new&lt;/kbd&gt;), handles dependencies specified in
  your project file, (&lt;kbd&gt;lein deps&lt;/kbd&gt;) and creates jar files
  for you, (&lt;kbd&gt;lein jar&lt;/kbd&gt;) among other things.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://github.com/technomancy/mire/commit/1326451b&quot;&gt;Commit
    1326451b&lt;/a&gt;: The player and rooms namespaces: alter-var-root&lt;/h4&gt;

&lt;p&gt;The main thing that's going on here is replacing a
  non-toplevel &lt;code&gt;def&lt;/code&gt; with a call
  to &lt;code&gt;alter-var-root&lt;/code&gt;. It's never a good idea to
  call &lt;code&gt;def&lt;/code&gt; from within a function. I tried to justify it by
  the fact that in this case it was a function that was only meant
  to be called at startup time as the docstring emphasized, (to
  initialize the rooms map) but it still felt wrong.&lt;/p&gt;

&lt;p&gt;The problem is that the rooms map must be loaded from a bunch of
  files on disk, but the directory to load from isn't known until
  the &lt;code&gt;-main&lt;/code&gt; function is called. So some mutability is
  called for here, but it's not really enough to justify a ref or an
  atom since once the server starts it will never change. In the
  updated version, &lt;code&gt;alter-var-root&lt;/code&gt; replaces
  the &lt;code&gt;def&lt;/code&gt;. It takes a var (&lt;code&gt;mire.rooms/rooms&lt;/code&gt; in
  this case) along with a function to apply to the current value of
  the var and uses the return value as the new root value of the
  var. It's also possible to simulate change to a var
  using &lt;code&gt;binding&lt;/code&gt;, but this only affects the current thread,
  and in this case we want the changes to be available to all
  threads.&lt;/p&gt;

&lt;p&gt;Justifiable use of &lt;code&gt;alter-var-root&lt;/code&gt; is rare, but
  startup-time mutability is one of those places it makes sense.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://github.com/technomancy/mire/commit/0dbd3402&quot;&gt;Commit
    0dbd3402&lt;/a&gt;: The commands namespace: contrib shuffle&lt;/h4&gt;

&lt;p&gt;This one is pretty basic; it's mostly just adjusting to the new
  layout of Clojure Contrib. A number of namespaces got
  moved: &lt;code&gt;clojure.contrib.duck-streams&lt;/code&gt;
  became &lt;code&gt;clojure.contrib.io&lt;/code&gt;, &lt;code&gt;clojure.contrib.str-utils&lt;/code&gt;
  became &lt;code&gt;clojure.contrib.string&lt;/code&gt;, etc. In this case we
  switched from calling &lt;code&gt;clojure.contrib.str-utils/str-join&lt;/code&gt;
  to &lt;code&gt;clojure.contrib.string/join&lt;/code&gt;. Some of these namespaces
  (most of &lt;code&gt;io&lt;/code&gt; and some of &lt;code&gt;seq&lt;/code&gt;) will be promoted out
  of Contrib and into Clojure itself before the final 1.2.0
  release.&lt;/p&gt;

&lt;p&gt;The other thing worth noting here is that in the original version
  of Mire there were a lot of unqualified calls to &lt;code&gt;use&lt;/code&gt;,
  which bring in &lt;i&gt;all&lt;/i&gt; the vars from the specified
  namespace. It's a lot more idiomatic now to either switch
  to &lt;code&gt;require&lt;/code&gt; with &lt;code&gt;:as&lt;/code&gt; to alias the namespace to a
  short name or to stick with &lt;code&gt;use&lt;/code&gt; but to limit the list of
  vars using the &lt;code&gt;:only&lt;/code&gt; qualifier to avoid pulling every
  single thing in, which is the approach taken here. This may seem
  like a bit of up-front busywork, but makes it easier to track down
  dependencies between namespaces and fix them in cases like the
  Contrib upgrade where things get switched around.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://github.com/technomancy/mire/commit/0a0fa0fa&quot;&gt;Commit
    0a0fa0fa&lt;/a&gt;: Upgrade server namespace: the resources directory&lt;/h4&gt;

&lt;p&gt;Here we see more careful &lt;code&gt;use&lt;/code&gt; usage along with moving the
  room data files from &lt;code&gt;data/rooms/&lt;/code&gt;
  to &lt;code&gt;resources/rooms/&lt;/code&gt; following Leiningen conventions. The
  resources dir is meant for files that aren't code but are still
  used by the project, like HTML templates or data files like the
  rooms that Mire uses. They will get included in the jar file when
  the project is packaged.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;http://github.com/technomancy/mire/commit/43ce1f4e&quot;&gt;Commit
    43ce1f4e&lt;/a&gt;: The test suite: clojure.test and use-fixtures&lt;/h4&gt;

&lt;p&gt;In the Clojure 1.1 release the &lt;code&gt;test-is&lt;/code&gt; library got
  promoted from Contrib into Clojure itself, so that's reflected
  here. We also move them to a separate &lt;code&gt;test&lt;/code&gt; directory to
  reflect Leiningen convention. The tests for &lt;code&gt;mire.rooms&lt;/code&gt;
  now uses the &lt;code&gt;use-fixtures&lt;/code&gt; function, which is a great way
  to abstract out common setup to be shared among tests.&lt;/p&gt;

&lt;p&gt;While OOP test frameworks use setup/teardown methods,
  the &lt;code&gt;use-fixtures&lt;/code&gt; feature of &lt;code&gt;clojure.test&lt;/code&gt; takes
  advantage of the fact that tests themselves are functions. A
  fixture is simply a function that takes a function argument. In
  our case the fixture just runs the function inside some bindings,
  but other common uses of fixtures are to create data on disk in a
  try/finally block and clean up when it finishes or to
  conditionally run the tests only if a given network service is
  accessible. There's a lot of flexibility with &lt;code&gt;clojure.test&lt;/code&gt;
  fixtures.&lt;/p&gt;

&lt;h4&gt;What Isn't Here&lt;/h4&gt;

&lt;p&gt;There have been a lot more new features introduced to Clojure
  since Mire was released. We haven't
  covered &lt;a href=&quot;/132&quot;&gt;transients&lt;/a&gt;, &lt;a href=&quot;http://clojure.org/protocols&quot;&gt;protocols&lt;/a&gt;,
  &lt;a href=&quot;http://clojure.org/datatypes&quot;&gt;deftype&lt;/a&gt;, or
  the &lt;a href=&quot;http://debasishg.blogspot.com/2010/04/thrush-in-clojure.html&quot;&gt;thrush
  combinators&lt;/a&gt; mostly because these aren't introductory-level
  topics, but also because they're the trendy new exciting topics
  and have been covered well elsewhere. But I hope this has been
  enough to modernize the Mire project and help extend the relevance
  of the screencast and associated codebase. Thanks for tuning
  in!&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20the%20maintainer's%20perspective%20is%20considered</id>
    <published>2010-03-29T19:58:00Z</published>
    <updated>2010-03-29T19:58:00Z</updated>

    <link href="http://technomancy.us/135" rel="alternate" type="text/html"/>
    <title>in which the maintainer's perspective is considered</title>
    <content type="html">
      &lt;p&gt;In the past few months I've had a number of contributions pour in
  for some of my projects. It's been really exciting to see this
  level of community involvement, and I try to do everything I can
  to encourage users to get involved in development. But I don't
  have a lot of free time these days&amp;mdash;with two small kids I'm
  lucky to have a few hours a week to address incoming patches, much
  less work on new features.&lt;/p&gt;

&lt;img src=&quot;/i/github-inbox.png&quot; alt=&quot;github inbox (dramatization)&quot;
     title=&quot;(dramatization)&quot; /&gt;

&lt;p&gt;There are a few things that could streamline the process a bit,
  so I thought I'd take some time to explain how these projects look
  from the maintainer's side and the things that contributors could
  do to make their patches easy to apply.&lt;/p&gt;

&lt;h4&gt;Coordinating&lt;/h4&gt;

&lt;p&gt;For simple stuff it's great just to get patches out of the
  blue. For more involved work, however, it's important to
  communicate so that parallel feature work doesn't interfere. For
  my projects, there are few enough people working on them that
  usually mentioning it on the mailing list is plenty. Larger
  projects will often track in-progress features using a ticket
  system, so in that case you'll probably want to do both. Then
  you can fork/checkout the project and get started.&lt;/p&gt;

&lt;h4&gt;Branches&lt;/h4&gt;

&lt;p&gt;The first thing to remember is to keep all your work in topic
  branches. Most people just commit directly to the master branch,
  but then it's trickier for them to keep in sync with
  upstream. Every time you pull in the latest changes it causes a
  merge commit. This needlessly clutters up the history and makes it
  difficult for maintainers to find the exact changes they are
  looking for. It gets worse if there are multiple unrelated
  features committed directly to master. Even once your changes are
  merged, it's likely that pulling changes after that point will
  still result in merge commits rather than fast-forwards simply
  because the same set of changes were applied in a different
  order. So keeping your work in a separate branch per feature/fix
  allows the master history to be kept clean.&lt;/p&gt;

&lt;p&gt;When it's time for a maintainer to merge your branch, they have a
  choice to either rebase it on top of the current master and then
  commit it, maintaining a linear history, or merge it in to master
  with a single merge commit. The latter is usually done in the case
  of longer-lived branches where you want to be able to group
  together a whole series of commits under a single feature. It's a
  bit silly/noisy to leave a merge commit lying around from merging
  a branch with only one or two commits.&lt;/p&gt;

&lt;h4&gt;Cleanliness&lt;/h4&gt;

&lt;p&gt;I'm a little more picky about the silly little things than most
  maintainers; I prefer my projects to be free of trailing
  whitespace and to use 80-column width, standard indentation, and
  no tabs. It's easy enough to enforce this in Emacs:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;(setq whitespace-style '(trailing lines space-before-tab
                          indentation space-after-tab)
      whitespace-line-column 80)

  &lt;span class=&quot;comment-delimiter&quot;&gt;;; &lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;add hooks for every major mode you use
&lt;/span&gt;(add-hook 'clojure-mode-hook (&lt;span class=&quot;keyword&quot;&gt;lambda&lt;/span&gt; () (whitespace-mode 1)))&lt;/pre&gt;

&lt;p&gt;In an ideal world, projects would have great test coverage and
  bugfix patches would always include first a test that fails in
  order to highlight the problem the patch addresses, then the
  implementation that causes the test to pass. Many of my projects
  unfortunately fall into the tricky-to-test zone either by way of
  complex asynchronous I/O or UI-heavy pieces of code, making this
  ideal difficult to achieve. In any case, it gives maintainers much
  more confidence when applying a patch if they can use tests to
  verify it's behaving as intended. It just takes a big burden off
  the person performing the merge if they only have to manually
  verify that the test passes and makes sense rather than checking
  by hand that the implementation is behaving as expected.&lt;/p&gt;

&lt;p&gt;I've found that in Clojure it's good to aim for function bodies
  of ten lines or less, modulo exception handling and
  logging. Naturally there will be places where this isn't
  practical, but it's good to keep this in mind and carefully
  examine longer functions to see if there would be a cleaner way to
  break things up. It should go without saying that using pure
  functions as much as possible and consolidating all I/O and
  mutation into a few places will also help a great deal to make
  things easier to read.&lt;/p&gt;

&lt;h4&gt;Sending it off&lt;/h4&gt;

&lt;p&gt;Personally I find it easiest to work with changes that are
  published to a remote git repository. Generally this means people
  create forks on Github, but there's no reason other options
  like &lt;a href=&quot;http://gitorious.org&quot;&gt;Gitorious&lt;/a&gt; or even a
  self-hosted git repo wouldn't work. Github pull requests work
  well, although please do &lt;em&gt;not&lt;/em&gt; send them without a message
  explaining what the changes do. Github has a &quot;feature&quot; whereby you
  can send pull requests to everyone with a fork of a project; this
  is a terrible, terrible thing that you should never use. Most of
  the people on that list forked the project months and months ago
  and forgot about it, so please don't spam them.&lt;/p&gt;

&lt;p&gt;Some people prefer to just mail patches or attach patches to bug
  tracker tickets. It's easy to generate these patches by
  running &lt;kbd&gt;git format-patch master&lt;/kbd&gt; from your topic
  branch.&lt;/p&gt;

&lt;p&gt;And it's an unfortunate fact of life that some projects require
  copyright assignment before they can accept nontrivial patches, so
  check for that first. In some cases a paper form is even required,
  which can bring a further unexpected delay into the picture.&lt;/p&gt;

&lt;h4&gt;Commit Access&lt;/h4&gt;

&lt;p&gt;In some cases I know I'm just not able to give a project the
  attention it deserves and I volunteer certain contributors for the
  post of maintainer. Sometimes this is because I just can't give a
  project the attention it needs to keep up with incoming patches,
  and sometimes (as with Hugo Duncan and his excellent work
  on &lt;a href=&quot;http://github.com/technomancy/swank-clojure/tree/swank-break&quot;&gt;swank-clojure
  break&lt;/a&gt;) it's because I just don't want to be a bottleneck
  keeping their awesome work from getting in.&lt;/p&gt;

&lt;p&gt;In these cases I like to ask that changes don't get merged to
  master until they've been reviewed by at least one person other
  than the author. If you're a committer that's applying patches
  someone else sent in, then you're doing the review, otherwise just
  try to get some help from IRC or the project's mailing list to
  review your patch before it makes it to master.&lt;/p&gt;

&lt;p&gt;All that said, keep the patches coming! I love getting them.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20telephone%20seems%20like%20entirely%20the%20wrong%20word</id>
    <published>2010-02-07T21:35:24Z</published>
    <updated>2010-02-07T21:35:24Z</updated>

    <link href="http://technomancy.us/134" rel="alternate" type="text/html"/>
    <title>in which telephone seems like entirely the wrong word</title>
    <content type="html">
      &lt;p&gt;After years of resisting phone ownership followed by a few years
  of owning a 2003-era Nokia dumbphone, I finally decided to make
  the jump when the Nexus One was announced. I've got a strong
  distaste for systems that &lt;a href=&quot;http://apple.com/iphone&quot;&gt;place
  arbitrary restrictions on their users&lt;/a&gt;, and while the Android
  OS itself doesn't have any, many Android phones before the Nexus
  One have had the carriers interfere with the user's control over
  their phone, though not to the same offensive degree as
  Apple. The Nexus One is sold directly through Google without
  giving the carriers a chance to sully it.&lt;/p&gt;

&lt;h3&gt;Daily Usage&lt;/h3&gt;

&lt;p&gt;The screen is just brilliant, and the 800x480 resolution means
  everything is sharp. The OS is very smooth and responsive. Having
  spent so long on a system where the keyboard is king and the mouse
  is only used in exceptional cases, switching to the inverse
  situation on the phone is a bit odd, but not as disorienting as
  you'd expect. Like any handheld keyboard, the Nexus's is bad for
  writing anything longer than a tweet, but it's certainly no worse
  than the hardware keyboard on the
  old &lt;a href=&quot;http://www.amazon.com/Sharp-SL-5500-Zaurus-PDA/dp/B000063D6E&quot;&gt;Zaurus&lt;/a&gt;
  I toy around with occasionally or the one on my Kindle. The built-in apps work great, and
  if you take the plunge to fully switch to GMail, it pretty much
  makes syncing your mailbox a solved problem.&lt;/p&gt;

&lt;img src=&quot;/i/nexus-one.jpg&quot; alt=&quot;nexus logo&quot; align=&quot;right&quot; /&gt;

&lt;p&gt;There are a few nit picks like the color balance being a bit off
  on the camera, the way the face buttons don't trigger unless you
  push the upper half, and the fact that the built-in jabber client
  only supports a single account. But these are all pretty minor or
  easy to work around. The only thing that really bugs me about it
  is the fact that there's no ZeroConf implementation yet for the
  platform. But there are people working on this, so it's just a
  matter of time.&lt;/p&gt;

&lt;h3&gt;Oh, and using it to Talk?&lt;/h3&gt;

&lt;p&gt;It turns out you can also use the Nexus One to interface with the
  global legacy telephone system and make calls on that. Supposedly
  it has a very nice dual-mic noise suppression system for when you
  do this, but I've only made a handful of test calls so far. I got
  a &lt;a href=&quot;http://www.t-mobile.com/shop/plans/cell-phone-plans-detail.aspx?tp=tb1&amp;rateplan=T-Mobile-Total-Internet-Rate-Plan&quot;&gt;data-only
  plan&lt;/a&gt; for half of what the regular voice+data plans go for and
  had planned to use &lt;a href=&quot;http://sipdroid.org/&quot;&gt;Sipdroid&lt;/a&gt; to
  make VoIP calls with it, but then I realized I just don't make
  voice calls any more. So while there's a barely-noticeable delay
  with SIP calls over the 3G network, it really doesn't bother me. I
  also have used
  the &lt;a href=&quot;http://code.google.com/p/android-wired-tether/&quot;&gt;Wired
  Tether&lt;/a&gt; app to hook up my laptop on the go and can confirm that
  calls via Skype sound fine too. So it's nice that T-Mobile isn't
  blocking that on a network level. They do seem to be the
  least-user-hostile of all the US carriers.&lt;/p&gt;

&lt;h3&gt;Hacking It&lt;/h3&gt;

&lt;p&gt;Of course once you get past the formalities, the question that
  matters to a hacker is how it feels to hack. I've only really
  gotten started with this, but my initial report is fairly
  positive. The official toolsets are either Eclipse or Ant, neither
  of which give me warm fuzzies, but luckily you can use Ant out of
  the box without getting exposed to the XML-editing ickiness.&lt;/p&gt;

&lt;img src=&quot;/i/garrett.png&quot; alt=&quot;garrett demo&quot; align=&quot;left&quot; /&gt;

&lt;p&gt;Getting programs onto the device is pretty simple. Once your
  source is ready, you run &lt;kbd&gt;ant debug&lt;/kbd&gt;, which produces a
  .apk package. You can use the &lt;kbd&gt;adb&lt;/kbd&gt; (android debugger)
  program to load it up over USB, but since I keep leaving my USB
  cable various places, I prefer just &lt;kbd&gt;scp&lt;/kbd&gt;ing it to my
  server and pointing my device's browser directly at the .apk. You
  can also use this to install dev builds of various apps before
  they have been uploaded to the Market.&lt;/p&gt;

&lt;p&gt;The API seems pretty sane. A lot of thought has gone into the
  notion of supporting a single front-and-center application while
  allowing others to run in the background without impacting battery
  life and performance too severely. I've played a bit with the
  graphics tools, and they remind me a fair bit
  of &lt;a href=&quot;http://processing.org&quot;&gt;Processing&lt;/a&gt;, which is a good
  thing. I haven't done much intricate UI work with a lot of buttons
  or menus, but that kind of stuff can be tedious even in the nicest
  environments.&lt;/p&gt;

&lt;h3&gt;Language of Choice&lt;/h3&gt;

&lt;p&gt;Since the Android VM is based on the JVM, there's a whole host of
  languages that can run on it. Unfortunately, Dalvik is no
  Hotspot&amp;mdash;it currently lacks JIT, and the GC is merely
  serviceable rather than astoundingly good like Hotspot's. The lack
  of a good GC makes using &lt;a href=&quot;/132&quot;&gt;persistent data
  structures&lt;/a&gt; a real drag since they generate a lot of ephemeral
  garbage, so Clojure is not a good choice. The lack of JIT coupled
  with CPUs that are comparatively low-powered means that
  while &lt;a href=&quot;http://groups.google.com/group/ruboto&quot;&gt;JRuby
  runs&lt;/a&gt;, it's not altogether pleasant, especially considering the
  blitz with which regular apps perform. I've been told there is
  some low-hanging fruit for improving performance on Android, so
  this is likely to improve to a degree. Rhino, Python, Lua, Scala,
  and others work, (including, I'm told, even some legacy languages
  like Java, if you can imagine that) but I decided to try the
  less-traveled route with something
  called &lt;a href=&quot;http://github.com/headius/duby&quot;&gt;Duby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Duby is a language created by Charles Nutter, the head of the
  JRuby project. JRuby is an amazing feat in part because Ruby's
  object model is vastly different from what's natively available on
  the Java platform. By an astounding effort they've managed to put
  together a first-class Ruby implementation, but it does beg the
  question: what would a modern language look like that
  went &lt;i&gt;with&lt;/i&gt; the grain of its host instead of violently
  against it? Duby is an attempt to answer that question.&lt;/p&gt;

&lt;p&gt;The syntax of Duby is nearly identical to that of Ruby; it only
  adds type declarations to method definitions. Yes, that means it's
  statically-typed. While it has type inference, it's not
  Hindley-Milner-style, it's closer to Scala's. Locals get their
  types inferred, it's only arguments in method definitions that
  need hints. So far I keep forgetting this nearly every time
  I write a new method since it looks so close to Ruby otherwise,
  but I'm sure I'll get the hang of it. Closures are implemented, so
  you can iterate over collections with blocks. Duby is also unique
  in that it literally has no runtime&amp;mdash;its literals translate
  directly to ArrayLists and HashMaps, so once you've compiled, the
  code is more or less identical to what the Java compiler would
  have output.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: Duby has (thankfully) been renamed &lt;a
  href=&quot;http://mirah.org&quot;&gt;Mirah&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Progress&lt;/h3&gt;

&lt;p&gt;So far I've only put together a couple toy apps: Hello World, and
  a &lt;a href=&quot;http://github.com/technomancy/Garrett&quot;&gt;graphics demo
  with a bouncing ball&lt;/a&gt;. Unfortunately, Duby is a &lt;i&gt;very&lt;/i&gt;
  immature language, and it shows. Starting out I had to go to
  Charlie at nearly every turn with stack traces. Half the time it
  would be my fault, and half the time it would be something
  as-yet-unsupported by the compiler. But so far he's been able to
  turn around and bring in all the features I need, which has been
  quite amazing. I'm hoping to get a chance to dive into the
  compiler source myself and get to the point where I can add
  features I need with minimal guidance.&lt;/p&gt;

&lt;p&gt;Adapting the Android build process to Duby was surprisingly easy. You
  &lt;a href=&quot;http://github.com/technomancy/Garrett/blob/master/build.xml#L67&quot;&gt;redeclare
    the compile task&lt;/a&gt; to call the Duby compiler instead of javac,
    tell it to output its bytecode in the right directory, and the
    rest of it just falls into place.&lt;/p&gt;

&lt;p&gt;My next plans are to add more interactivity to my graphics demo;
  I'd like to play with creating objects and applying motion rules
  to them; I hope to come up with something my two-year-old would
  get a kick out of. So far it's been a lot of fun and a great way
  to explore the capabilities of this remarkable device.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which,%20were%20a%20title%20to%20be%20summarized%20from%20the%20content,%20it%20would%20be%20altogether%20too%20similar%20to%20many%20of%20the%20titles%20used%20for%20past%20articles,%20possibly%20to%20the%20point%20of%20indistinguishability</id>
    <published>2010-01-31T18:10:28Z</published>
    <updated>2010-01-31T18:10:28Z</updated>

    <link href="http://technomancy.us/133" rel="alternate" type="text/html"/>
    <title>in which, were a title to be summarized from the content, it would be altogether too similar to many of the titles used for past articles, possibly to the point of indistinguishability</title>
    <content type="html">
      &lt;p&gt;Anyone who follows my exploits will have noticed I'm a tireless
  proponent of &lt;a href=&quot;http://tromey.com/elpa&quot;&gt;ELPA&lt;/a&gt;, the Emacs
  Lisp Package Archive. As a maintainer of several Elisp libraries,
  ELPA makes my life easier by helping me sidestep the boring
  problems of distribution and installation. You may not know that
  package.el, the software behind ELPA, has been submitted for
  inclusion in the next version of Emacs. I've taken up the task of
  getting it ready.&lt;/p&gt;

&lt;img src=&quot;/i/flight-museum.jpg&quot; alt=&quot;museum of flight bridge&quot;
     align=&quot;right&quot; /&gt;

&lt;p&gt;Including something like package.el into Emacs is a big job, and
  it's something that can only happen gradually. Emacs comes with a
  number of applications such as &lt;a href=&quot;http://orgmode.org&quot;&gt;Org
  Mode&lt;/a&gt; and &lt;a href=&quot;http://gnus.org&quot;&gt;Gnus&lt;/a&gt; that are developed
  externally to Emacs and merged periodically into the main Emacs
  source tree. If they were to be redone as packages they could
  still be distributed with Emacs builds but kept out of the source
  tree. They could also be upgraded and installed/removed
  independently of Emacs' historically long release cycles.&lt;/p&gt;

&lt;p&gt;If you've submitted packages to ELPA before, you know it's a
  process that could use some streamlining. Currently it's all done
  by email, and packages must be manually uploaded by a single
  maintainer before they appear to users. This has long been the
  biggest shortcoming of ELPA. I've written some additions
  (package-maint.el) that allow you to automate the maintenance of a
  package source. Basically you provide it with a list of git URLs,
  and it will check out each tagged version and create a package
  from it. Of course, that wouldn't be useful without giving clients
  the ability to get packages from multiple sources at once, which I
  also added to package.el.&lt;/p&gt;

&lt;p&gt;If you maintain any Emacs packages of your own, please try out
  &lt;a href=&quot;http://github.com/technomancy/package.el&quot;&gt;my changes to
  package.el&lt;/a&gt;. If you use any of my packages, try upgrading and
  adding my package source to your list.&lt;/p&gt;

  &lt;pre class=&quot;code&quot;&gt;(add-to-list 'package-archives
             '(&quot;technomancy&quot; . &quot;http://repo.technomancy.us/emacs/&quot;) t)&lt;/pre&gt;

  &lt;p&gt;That way you'll get access to my updates as soon as they're
    tagged rather than waiting for them to be manually uploaded,
    though currently the latest versions of all my packages are in
    ELPA. Next steps are closer integration with Emacs in order to
    have packages installable on a system-wide level as well as a
    per-user level, prerelease version number support, and
    extraction of some built-in Emacs libraries as
    packages. Suggestions, bug reports, and patches welcome!&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20persistence%20proves%20a%20propitious%20property</id>
    <published>2009-12-22T15:14:16Z</published>
    <updated>2009-12-22T15:14:16Z</updated>

    <link href="http://technomancy.us/132" rel="alternate" type="text/html"/>
    <title>in which persistence proves a propitious property</title>
    <content type="html">
      &lt;p&gt;When you read about functional languages, one of the things that
  frequently comes up is the value of persistent data structures. If
  you come from an OOP background where persistent means &quot;it gets
  saved to disk&quot;, this is a little confusing until you do a little
  digging to find out it's a different meaning of the word
  persistent; you discover that it just means the data structures
  are immutable. This is technically true; all persistent data
  structures are immutable. But this understanding is a little bit
  lacking&amp;mdash;it doesn't really get at the meaning of
  persistent.&lt;/p&gt;

&lt;p&gt;The point of persistence in this case is that future versions of
  the object in question can be created without changing either the
  value &lt;b&gt;or&lt;/b&gt; the performance characteristics of the existing
  instance. So when you've got a vector that you want to work with,
  you can create another vector based on the original, but with a
  few new items added to it. In languages that provide persistent
  data structures this is done without copying; internally the
  portions of the vector that are the same use a shared
  structure. But there are some pseudo-persistent implementations
  that cheat; as you create more and more versions based on the
  original vector, the performance of the original degrades even
  though the value is preserved. This is avoided in true persistent
  implementations such as Clojure's.&lt;/p&gt;

&lt;p&gt;The other important thing about understanding persistence is
  understanding what it's not. A new feature in Clojure 1.1 is the
  addition of &lt;a href=&quot;http://clojure.org/transients&quot;&gt;transient&lt;/a&gt;
  data structures. Transients provide speed boosts in cases where
  you decide performance is more important than persistence by using
  mutable data structures in a controlled, thread-safe way. If you
  don't understand what persistence means then you might see the
  fact that they are mutable and use them as you would in an
  imperative language&amp;mdash;but that's not what they're meant for!
  The key to understanding transients is not that they're mutable
  but that they're &lt;i&gt;not persistent&lt;/i&gt;. The fact that they are
  mutable is an implementation detail; you should treat them like
  regular immutable data structures, you just shouldn't rely on
  their persistent qualities.&lt;/p&gt;

&lt;p&gt;Focusing on immutability is focusing on the negative: what
  you &lt;i&gt;can't&lt;/i&gt; do. Thinking in terms of persistence is focusing
  on the positive: there are a certain set of guarantees that we may
  rely on. If you decide in some cases to give up those guarantees
  for speed benefits, transients allow you to do that, but you
  shouldn't think of them as your old imperative friends you can
  alter as you wish.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20projects%20may%20be%20more%20easily%20compiled%20and%20distributed</id>
    <published>2009-11-25T22:28:10Z</published>
    <updated>2009-11-25T22:28:10Z</updated>

    <link href="http://technomancy.us/131" rel="alternate" type="text/html"/>
    <title>in which projects may be more easily compiled and distributed</title>
    <content type="html">
      &lt;a href=&quot;http://www.flickr.com/photos/31151628@N03/4010921064/&quot;&gt;&lt;img src=&quot;i/leiningen.jpg&quot; alt=&quot;leiningen portrait&quot; align=&quot;right&quot; /&gt;&lt;/a&gt;
&lt;p&gt;So build tools have been a long-standing pain point when working
  on Clojure projects. Most projects have used JVM-centric tools
  like ant or maven, which are far more complicated than what you
  need to build Clojure, and on top of that must be configured with
  XML. It could be made to work, and in the case of projects with
  significant dependencies it was much better than doing it by hand,
  but it was a pain.&lt;/p&gt;

&lt;p&gt;Last week I
  launched &lt;a href=&quot;http://github.com/technomancy/leiningen&quot;&gt;Leiningen&lt;/a&gt;,
  which is a project that brings a native build tool to Clojure. It
  seems to have people pretty excited about it, which leads me to
  believe I'm far from the only one who's been feeling the pain
  here. It's configured using a Clojure file called project.clj like
  the sample below.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;defproject leiningen &lt;span class=&quot;string&quot;&gt;&quot;1.0.0-SNAPSHOT&quot;&lt;/span&gt;
  &lt;span class=&quot;builtin&quot;&gt;:description&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;A build tool designed not to set your hair on fire.&quot;&lt;/span&gt;
  &lt;span class=&quot;builtin&quot;&gt;:main&lt;/span&gt; leiningen.core
  &lt;span class=&quot;builtin&quot;&gt;:dependencies&lt;/span&gt; [[org.clojure/clojure &lt;span class=&quot;string&quot;&gt;&quot;1.1.0-alpha-SNAPSHOT&quot;&lt;/span&gt;]
                 [org.clojure/clojure-contrib &lt;span class=&quot;string&quot;&gt;&quot;1.0-SNAPSHOT&quot;&lt;/span&gt;]
                 [ant/ant-launcher &lt;span class=&quot;string&quot;&gt;&quot;1.6.2&quot;&lt;/span&gt;]
                 [org.apache.maven/maven-ant-tasks &lt;span class=&quot;string&quot;&gt;&quot;2.0.10&quot;&lt;/span&gt;]]
  &lt;span class=&quot;builtin&quot;&gt;:dev-dependencies&lt;/span&gt; [[org.clojure/swank-clojure &lt;span class=&quot;string&quot;&gt;&quot;1.0&quot;&lt;/span&gt;]]&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;h3&gt;Testing&lt;/h3&gt;

&lt;p&gt;This one's pretty straightforward: &lt;kbd&gt;lein test&lt;/kbd&gt; searches
  the test/ directory for namespaces and runs the tests in each.&lt;/p&gt;

&lt;h3&gt;Building&lt;/h3&gt;

&lt;p&gt;Running &lt;kbd&gt;lein jar&lt;/kbd&gt; will compile your code and package it
  up as a .jar file. If you specify a &lt;code&gt;:main&lt;/code&gt; class in
  your project config, this will be an executable jar with the class
  you specified. If you just want to compile your code, there's
  a &lt;kbd&gt;compile&lt;/kbd&gt; task for that too. Alternatively if you want
  to build a standalone jar that includes all your project's
  dependencies for easier distribution, you can do that
  with &lt;kbd&gt;lein uberjar&lt;/kbd&gt;.&lt;/p&gt;

&lt;h3&gt;Dependency Management&lt;/h3&gt;

&lt;p&gt;This is the fun part. Rather than tracking down and downloading
  all your dependency jars manually (or worse: &lt;i&gt;checking them
  in&lt;/i&gt; to your source repository), Leiningen provides
  a &lt;kbd&gt;deps&lt;/kbd&gt; task to automatically download them and place
  them in the lib/ directory. This uses some Maven code under the
  covers, but don't panic&amp;mdash;you won't have to see a bit of XML
  unless you want to. It pulls from the central Maven repositories
  by default as well as
  from &lt;a href=&quot;http://build.clojure.org&quot;&gt;Clojure's nightly builds&lt;/a&gt;
  and &lt;a href=&quot;http://clojars.org&quot;&gt;http://clojars.org&lt;/a&gt;. Clojars
  has built-in search, but if you want to pull a library from the
  central repository, you can search for it
  on &lt;a href=&quot;http://jarvana.com&quot;&gt;Jarvana&lt;/a&gt;. You can also specify
  development dependencies with the &lt;code&gt;:dev-dependencies&lt;/code&gt;
  key for things that shouldn't be pulled in at production or
  included in the standalone jar; the syntax is the same.&lt;/p&gt;

&lt;h3&gt;Publishing with Clojars&lt;/h3&gt; &lt;p&gt;By a stroke of luck I dropped
hints about Leiningen the week before I made a public announcement
only to find out that Alex Osborne was approaching the same problem
from the other direction.  He'd been cooking up a web site and
service for hosting Clojure libraries independently of my work on
Leiningen, and we started talking about ways to integrate the
two. So now Leiningen makes it easy to publish jars publicly via
Clojars so other projects can depend on them. The day after
announcing Clojars, Alex was &lt;a
href=&quot;http://www.infoq.com/news/2009/11/clojars-leiningen-clojure&quot;&gt;interviewed
on InfoQ&lt;/a&gt; about the site and how it interacts with Leiningen, so
I was thrilled to see both our projects getting exposure so
quickly.&lt;/p&gt;

&lt;h3&gt;Coming Soon...&lt;/h3&gt; &lt;p&gt;Soon after the 0.5.0 release, Alex along
with Dan Larkin (of the wonderful &lt;a
href=&quot;http://github.com/danlarkin/clojure-json&quot;&gt;Clojure JSON
library&lt;/a&gt; fame) started diving in and adding
features. &lt;strike&gt;We've got &lt;a
href=&quot;http://github.com/technomancy/leiningen/blob/master/todo.org&quot;&gt;a
few more tasks&lt;/a&gt; on the plate targeted for a 1.0 release, but
should be right around the corner.&lt;/strike&gt; &lt;b&gt;Update&lt;/b&gt;: &lt;a
href=&quot;http://github.com/technomancy/leiningen/blob/1.0.0/NEWS&quot;&gt;Leiningen
1.0 released&lt;/a&gt;. If you'd like to say hi or drop a line, there's
a #leiningen channel on freenode as well as a &lt;a
href=&quot;http://groups.google.com/group/leiningen&quot;&gt;mailing
list&lt;/a&gt;. If you found this useful, you should take a look at the &lt;a href=&quot;http://peepcode.com/products/functional-programming-with-clojure&quot;&gt;Clojure PeepCode screencast&lt;/a&gt;.&lt;/p&gt;

&lt;p style=&quot;font-size: 80%&quot;&gt;Logo
by &lt;a href=&quot;http://lorenbroach.blogspot.com/&quot;&gt;Loren Broach&lt;/a&gt;.&lt;/p&gt;
&lt;!-- TODO: note that some tasks implicitly call others --&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20things%20are%20mapped,%20but%20also%20reduced</id>
    <published>2009-11-13T20:29:30Z</published>
    <updated>2009-11-13T20:29:30Z</updated>

    <link href="http://technomancy.us/130" rel="alternate" type="text/html"/>
    <title>in which things are mapped, but also reduced</title>
    <content type="html">
      &lt;p&gt;A while ago Tim Bray had a project called
  the &lt;a href=&quot;http://www.tbray.org/ongoing/When/200x/2007/09/20/Wide-Finder&quot;&gt;Wide
  Finder&lt;/a&gt; to collect implementations of a log parsing problem in
  different languages to see which ones made it easy to take
  advantage of massively-parallel hardware. The idea is to accept a
  web server log file and return statistics for which pages have
  been requested the
  most. &lt;a href=&quot;http://www.tbray.org/ongoing/When/200x/2009/11/11/Clojure-References&quot;&gt;Yesterday&lt;/a&gt;
  he posted a follow-up in Clojure using refs.&lt;/p&gt;

&lt;p&gt;While his version is interesting for someone just getting into
  the language because it uses refs (probably the sexiest piece of
  the language), I think a map/reduce approach is a little more
  idiomatic since it can be done with no explicit state change.&lt;/p&gt;

&lt;p&gt;I'll step
  through &lt;a href=&quot;http://p.hagelb.org/wide_finder.clj.html&quot;&gt;my
  implementation&lt;/a&gt; piece-by-piece. Note that it is naïve and
  could be optimized for speed at the expense of straightfowardness,
  especially with regard to reading from disk;
  my intent here is simply to explain the functional approach.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: Commenters have posted a version that totally
  smokes my agent-based implementation in terms of performance and
  simplicity. I'm leaving it up because I think it's a fun romp in
  the land of higher-order functions; if you think having
  higher-order functions means &quot;I can pass a block
  to &lt;code&gt;Array#map&lt;/code&gt; in Ruby&quot; then you're in for a treat.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;ns&lt;/span&gt; wide-finder
  &lt;span class=&quot;string&quot;&gt;&quot;A basic map/reduce approach to the wide finder using agents.
  Optimized for being idiomatic and readable rather than speed.&quot;&lt;/span&gt;
  &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;:use&lt;/span&gt; [clojure.contrib.duck-streams &lt;span class=&quot;builtin&quot;&gt;:only&lt;/span&gt; [reader]]&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Every Clojure file opens with a call to the &lt;code&gt;ns&lt;/code&gt;
  macro. This defines a namespace (&lt;code&gt;wide-finder&lt;/code&gt;) and
  states any dependencies it may have on other namespaces, in this
  case the &lt;code&gt;reader&lt;/code&gt; function from
  the &lt;code&gt;duck-streams&lt;/code&gt; contrib library. Omitting
  the &lt;code&gt;:only&lt;/code&gt; clause would cause it to make all
  the &lt;code&gt;duck-streams&lt;/code&gt; vars available in this namespace,
  but it's usually better to be explicit about what you need.&lt;/p&gt;

&lt;p&gt;We'll start with the entry point. The &lt;code&gt;find-widely&lt;/code&gt;
  function below takes a filename and a number of agents to work
  with. Agents can be thought of as independent asynchronous workers
  that share a thread pool and keep a single state value. They are
  initialized with the &lt;code&gt;agent&lt;/code&gt; function that takes a
  starting state. We'll be using each agent to keep a map of pages
  to hit counts, so we map this function over a list
  of &lt;code&gt;n&lt;/code&gt; empty maps generated by &lt;code&gt;repeat&lt;/code&gt; to
  get our list of initialized agents.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;defn&lt;/span&gt; &lt;span class=&quot;function-name&quot;&gt;find-widely&lt;/span&gt; [filename n]
  &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;let&lt;/span&gt; [agents &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;map&lt;/span&gt; agent &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;repeat&lt;/span&gt; n {}&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;]
    &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;dorun&lt;/span&gt; &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;map&lt;/span&gt; #&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;send&lt;/span&gt; %1 count-line %2&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;cycle&lt;/span&gt; agents&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;line-seq&lt;/span&gt; &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;reader filename&lt;span class=&quot;esk-paren&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;apply&lt;/span&gt; await agents&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;apply&lt;/span&gt; merge-with + &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;map&lt;/span&gt; deref agents&lt;span class=&quot;esk-paren&quot;&gt;))))&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Once the agents are initialized, we send them
  work. Our &lt;code&gt;line-seq&lt;/code&gt; sets up a lazy sequence of lines
  from the file. We map over this sequence together with an infinite
  loop of the &lt;code&gt;agents&lt;/code&gt; we construct
  using &lt;code&gt;cycle&lt;/code&gt;. The &lt;code&gt;map&lt;/code&gt; function can loop
  over multiple sequences in parallel and will stop when the
  shorter one runs out, so this is just a way of pairing each line
  in the file with an agent in a round-robin fashion.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;dorun&lt;/span&gt; &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;map&lt;/span&gt; #&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;send&lt;/span&gt; %1 count-line %2&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;cycle&lt;/span&gt; agents&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;line-seq&lt;/span&gt; &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;reader filename&lt;span class=&quot;esk-paren&quot;&gt;))))&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;The code that does the mapping is the anonymous
  function &lt;code&gt;#(send %1 count-line %2)&lt;/code&gt;, which adds a call
  to the &lt;code&gt;count-line&lt;/code&gt; function to the agent's internal
  queue. This could be written in more traditional lambda form
  as &lt;code&gt;(fn [a line] (send a count-line line)&lt;/code&gt;;
  the &lt;code&gt;#()&lt;/code&gt; form is simply
  shorthand. The &lt;code&gt;count-line&lt;/code&gt; function will be called
  with two arguments: the agent's current value and the next line in
  the seq. That function will return a new value for the agent.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;doseq&lt;/span&gt; [a agents] &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;await a&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Once all the work has been queued up, it's necessary to
  call &lt;code&gt;await&lt;/code&gt; on each agent to make sure it has a chance
  to finish its queue. If we used &lt;code&gt;map&lt;/code&gt; here, it would
  be a no-op, since &lt;code&gt;map&lt;/code&gt; merely creates a lazy sequence;
  it does not actually perform the function calls until the value is
  needed. Since it's not in the tail-call position, the value would
  simply be discarded. Note that the same problem
  would occur in the previous call to map, but wrapping it in
  a &lt;code&gt;dorun&lt;/code&gt; call forces the lazy seq to be evaluated.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;apply&lt;/span&gt; merge-with + &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;map&lt;/span&gt; deref agents&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Once that's done we can call &lt;code&gt;deref&lt;/code&gt; on each agent to
  get its value. But this gives us &lt;code&gt;n&lt;/code&gt; maps rather than a
  list of totals, so we need to merge the values.
  &lt;code&gt;merge-with&lt;/code&gt; is a special case of &lt;code&gt;reduce&lt;/code&gt;
  that assumes it works on a sequence of maps and merges key
  collisions using the provided function, in this
  case &lt;code&gt;+&lt;/code&gt;. This gives us a map of page names to hit
  counts.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;defn&lt;/span&gt; &lt;span class=&quot;function-name&quot;&gt;count-line&lt;/span&gt; [counts line]
  &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if-let&lt;/span&gt; [[_ hit] &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;re-find&lt;/span&gt; #&lt;span class=&quot;string&quot;&gt;&quot;GET /(\d+) &quot;&lt;/span&gt; line&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;]
    &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;update-in counts [hit] inc-or-init&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt;
    counts&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Finally we have the function that actually performs the
  counting. As mentioned, it takes an agent's state (which is the current
  map of pages to hits) and a line from the log file. If the line
  matches the regex &lt;code&gt;#&quot;GET /(\d+) &quot;&lt;/code&gt;, then we return an
  updated version of the &lt;code&gt;counts&lt;/code&gt; map that increments the
  entry corresponding to the hit. The other interesting thing here
  is that &lt;code&gt;if-let&lt;/code&gt; uses &lt;em&gt;destructuring&lt;/em&gt;: by
  binding the return value of &lt;code&gt;re-find&lt;/code&gt; to a vector form,
  it splits the value in two. The first element (the full matched
  string) is bound to the unused &lt;code&gt;_&lt;/code&gt; local, and the
  second element (the match group corresponding to the actual page
  path) is bound to &lt;code&gt;hit&lt;/code&gt;.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;defn&lt;/span&gt; &lt;span class=&quot;function-name&quot;&gt;inc-or-init&lt;/span&gt; [i]
  &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; i &lt;span class=&quot;esk-paren&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;builtin&quot;&gt;inc&lt;/span&gt; i&lt;span class=&quot;esk-paren&quot;&gt;)&lt;/span&gt; 1&lt;span class=&quot;esk-paren&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The only piece left is the tiny &lt;code&gt;inc-or-init&lt;/code&gt; function
  that increments the counter given it but treats nil as zero. This
  would be unnecessary if we could construct hash-maps with custom default
  values, which a perusal of the implementation of PersistentHashMap.java
  seems to indicate is supported, though it's not exposed anywhere
  through a Clojure function. This is the piece of the puzzle that
  I'm the least happy with, but it may be possible to eliminate it.&lt;/p&gt;

&lt;p&gt;In any case, this is a simple example of how to break up a
  commonplace problem using a classic map/reduce strategy and
  immutable data structures. I have no idea how it compares in terms
  of performance to the other Wide Finder implementations since the
  logs I have for this site are not exactly the hundred-megabyte
  blockbuster kind of logs
  that &lt;a href=&quot;http://tbray.org/ongoing&quot;&gt;ongoing&lt;/a&gt; enjoys, but
  the fact that it can be parallelized in twelve lines is a
  testament to the expressiveness of the language.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20the%20effects%20of%20distance%20are%20reduced</id>
    <published>2009-10-03T15:37:47Z</published>
    <updated>2009-10-03T15:37:47Z</updated>

    <link href="http://technomancy.us/129" rel="alternate" type="text/html"/>
    <title>in which the effects of distance are reduced</title>
    <content type="html">
      &lt;p&gt;Since joining &lt;a href='http://sonian.net'&gt;Sonian&lt;/a&gt; in April,
  I've been part of a distributed team that has grown to four
  Clojure programmers all living in different states of the
  US. While it's been great to be able to draw from a wide pool of
  talent, working with a distributed team has its challenges.  While
  we had
  everyone &lt;a href='http://www.flickr.com/photos/technomancy/tags/sonian/'&gt;in
  Seattle&lt;/a&gt; for a week we got to do lot of pair programming, but
  after everyone went back home we were left wondering how we could
  emulate that over-the-shoulder atmosphere without all being
  physically in one place.&lt;/p&gt;

&lt;p&gt;We tried VNC, but it was simply too laggy. Then we tried
  &lt;a href='http://haruska.com/2009/09/29/remote-pair-programming/'&gt;shared
    screen sessions&lt;/a&gt;. This worked out pretty well. The defining
    characteristic here is that both participants see exactly the
    same thing. Only one can edit at a time, which is usually not a
    big deal when you're pairing. Since it's shared on a per-session
    basis rather than a per-document basis, it means you can share
    things like the woefully under-appreciated &lt;kbd&gt;M-x
    erevision&lt;/kbd&gt; feature, which is fantastic for code
    reviews. But it still feels a bit restrictive and out of the
    regular groove. We also use 3G a lot, and unfortunately port
    forwarding is not permitted by AT&amp;amp;T, our ISP.&lt;/p&gt;

&lt;img src=&quot;/i/rudel.png&quot; alt=&quot;rudel&quot; /&gt;

&lt;p&gt;Then I discovered &lt;a href='http://rudel.sf.net'&gt;Rudel&lt;/a&gt;, an
  Emacs client for the &lt;a href='http://gobby.0x539.de/trac/'&gt;Obby
  protocol&lt;/a&gt;. Years ago I'd started &lt;a href='/45'&gt;my own
  implementation of this called Ebby&lt;/a&gt;, but I wasn't aware of the
  more nuanced implications of the protocol, so my implementation
  was never very robust. Rudel, on the other hand, does a great job
  of allowing us to share documents among collaborators in
  real-time.&lt;/p&gt;

&lt;p&gt;Now we use Rudel for our main solution and then fall back to
  screen whenever we want to do something that involves
  synchronizing the whole screen. While you can run shell or SLIME
  sessions in Rudel, it's a bit awkward since only the original
  publisher of the document can actually interact with the
  subprocess. The other person can enter commands, but they can't
  run them, since pressing &lt;kbd&gt;enter&lt;/kbd&gt; will simply insert a
  newline. I have been playing with the idea of using the Obby chat
  functionality as a side-channel to perform these kinds of things,
  but I haven't written any code for it yet.&lt;/p&gt;

&lt;p&gt;One thing you've really got to be careful with in this situation
  is communicating who's responsible for committing. Otherwise you
  could easily get conflicting commits. SIP works great for talking
  through this vocally, though unfortunately mostly at work we're
  using Skype, which has a fairly lousy client for GNU/Linux.&lt;/p&gt;

&lt;!--  &lt;p&gt;Of course, this is only feasible if everyone on the team can work
  in an environment that's obby-aware. Gobby, the reference
  implementation, is a pretty weak editor for coding, and Rudel
  seems to be the only other existing implementation. So if an
  intrepid Vim user came along who could implement an Obby client in
  Vimscript, we might be able to consider him, but for now we're an
  all-Emacs team.&lt;/p&gt; --&gt;

&lt;p&gt;I'm working with Jan, the Rudel author, towards an 0.2 release
  (quite soon, it looks like) which should improve stability pretty
  significantly. At that point I should be able to bundle it up for
  ELPA, though if you're running an Emacs that's older than October
  2009 you will still need to install
  the &lt;a href='http://cedet.sf.net/eieio.shtml'&gt;eieio&lt;/a&gt; library by
  hand.&lt;/p&gt;

&lt;p&gt;Anyway, if you work on a distributed team, you
  should &lt;a href='http://rudel.sf.net'&gt;give it a shot&lt;/a&gt;. Until 0.2
  is released, you'll have best luck with the development
  version:&lt;/p&gt;

&lt;p&gt;&lt;kbd&gt;bzr branch
    bzr://rudel.bzr.sourceforge.net/bzrroot/rudel/trunk rudel&lt;/kbd&gt;&lt;/p&gt;

&lt;p&gt;Then in your Emacs config:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;(load-file &quot;/PATH/TO/RUDEL/rudel-loaddefs.el&quot;)&lt;/pre&gt;

&lt;p&gt;Once you've got a Gobby server running, &lt;kbd&gt;M-x
    rudel-join-session&lt;/kbd&gt; should get you connected, and &lt;kbd&gt;C-c
    c s&lt;/kbd&gt; will let you subscribe to a new document. Have fun!&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20it%20is%20time%20for%20something%20that%20is%20almost%20completely%20different</id>
    <published>2009-08-31T21:24:34Z</published>
    <updated>2009-08-31T21:24:34Z</updated>

    <link href="http://technomancy.us/128" rel="alternate" type="text/html"/>
    <title>in which it is time for something that is almost completely different</title>
    <content type="html">
      &lt;p&gt;Remember that funky leaf shape you used to draw with your ruler
  in math class in high school when you got bored? I can't be the
  only one who did this...&lt;/p&gt;

&lt;p&gt; Right before _why the lucky stiff took himself
  &lt;a href='http://ejohn.org/blog/eulogy-to-_why/'&gt;off the grid&lt;/a&gt; I
  started reading up on his experiments with code and art, and he
  spoke pretty highly of
  the &lt;a href='http://processing.org'&gt;Processing&lt;/a&gt; language as a
  very approachable way to get into programming. As someone who got
  started coding in QBasic, I've always felt that the amount of
  effort needed to get started in most modern languages is quite a
  shame. Sure you can get going easily with text, but when you're
  new to it you want to see pictures drawn and colors fly around the
  screen. Processing restores that level of immediacy; if you want a
  line, you call the &lt;code&gt;line&lt;/code&gt; function; there's no fussing
  with setting up an event loop or a menu bar or any of that
  nonsense.&lt;/p&gt;

&lt;img src=&quot;/i/chu-small.png&quot; alt=&quot;chu&quot; align=&quot;right&quot; /&gt;

&lt;p&gt;The problem is that while Processing is a great toolkit for
  drawing, it's is actually a pretty poor language when it comes to
  computational expressivity. It's statically-typed without any sort
  of inference, and there are no first-class functions or
  associative data type literals. Iteration is only possible using
  the most primitive of C-style &lt;code&gt;for&lt;/code&gt; loops, and there's a
  shameful level of statefulness in much of the core
  functionality... You're not going to miss these things if you're
  just starting out with programming, but as a seasoned hacker,
  going back to a language like that feels quite limiting.&lt;/p&gt;

&lt;p&gt;Luckily Processing is implemented on the JVM, so any other
  JVM-hosted languages can call out to it trivially. My weapon of
  choice right now is Clojure, and there's an adapter library that
  &lt;a href='http://github.com/rosado/clj-processing'&gt;fits the bill
  nicely&lt;/a&gt;. (A &lt;a href='http://wiki.github.com/jashkenas/ruby-processing'&gt;ruby 
  bridge&lt;/a&gt; exists too.) I've been playing around with it and have started a
  &lt;a href='http://github.com/technomancy/sketchbook'&gt;sketchbook
  project&lt;/a&gt; containing each of the programs I've written so far.&lt;/p&gt;

&lt;img src=&quot;/i/myu-small.png&quot; alt=&quot;myu&quot; align=&quot;left&quot; /&gt;

&lt;p&gt;The first thing you notice when you read up on Processing and
  take a look at some of the shorter sketches is that very simple
  ideas often yield interesting and subtle results. This image
  simply bounces a circle around the window while varying its
  opacity in a sine pattern. It's
  around &lt;a href='http://github.com/technomancy/sketchbook/blob/master/src/sketchbook/myu.clj'&gt;thirty
  lines of Clojure&lt;/a&gt;, but you can see emergent weave patterns in
  it. This
  is a &lt;a href='http://www.complexification.net/gallery/machines/substrate/appletl/index.html'&gt;fairly
  common occurrence&lt;/a&gt; among Processing projects.&lt;/p&gt;

&lt;p&gt;The canonical &lt;a href='http://www.amazon.com/Processing-Programming-Handbook-Designers-Artists/dp/0262182629/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1251782317&amp;sr=8-1'&gt;handbook
  by Reas and Fry&lt;/a&gt; has proven to an excellent introduction. It's
  geared towards beginner programmers, but the sections are broken
  up well so that it's easy to skip those on control and iteration
  while still getting a lot out of the more art-focused parts if
  you're coming from a programming background.&lt;/p&gt;

&lt;p&gt;A nice bonus of being JVM-hosted is that it's possible to run
  Processing programs as applets (remember applets?) in the
  browser. I haven't gotten mine exported yet, but having the option
  to share easily makes it a lot more fun; I hope to have a
  sketchbook page uploaded soon. In the mean time
  it's &lt;a href='http://github.com/technomancy/sketchbook'&gt;on
  Github&lt;/a&gt; if you want to try it yourself.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: I've compiled &lt;a href='/misc/sketchbook.jar'&gt;all my
  sketches so far together for download&lt;/a&gt;. Depending on your OS
  you may be able to double-click on it; otherwise just launch it
  with &lt;kbd&gt;java -jar sketchbook.jar&lt;/kbd&gt;. The &lt;code&gt;chu&lt;/code&gt;
  sketch has trouble launching, and there's one bug where the
  sketches' window size is wrong upon launch, but you can adjust
  that.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20a%20brotherhood%20gathers</id>
    <published>2009-06-06T22:27:32Z</published>
    <updated>2009-06-06T22:27:32Z</updated>

    <link href="http://technomancy.us/127" rel="alternate" type="text/html"/>
    <title>in which a brotherhood gathers</title>
    <content type="html">
      &lt;p&gt;This week I had the good fortune to be in San Francisco
  for &lt;a href='http://www.meetup.com/The-Bay-Area-Clojure-User-Group/calendar/10417495/'&gt;a
  meeting of the Bay Area Clojure Meetup&lt;/a&gt;. This meeting was a
  special event since Clojure's creator, Rich Hickey, was in town
  for the big JavaOne conference. We ended up packing out the room
  with sixty people, which made it probably the largest gathering of
  Clojure programmers ever.&lt;/p&gt;

&lt;p&gt;The meeting began with a handful of so-called &quot;lightning talks&quot;
  (of various lengths) on all sorts of topics. A few highlights were
  Amit
  Rathore's &lt;a href='http://s-expressions.com/2009/05/02/startup-logbook-distributed-clojure-system-in-production-v02/'&gt;Swarmiji&lt;/a&gt;
  clustering library and George Jahad's talk
  on &lt;a href='http://georgejahad.com/clojure/cljdb.html'&gt;decompiling
  Clojure with jdb&lt;/a&gt;, which showed tools to get a new perspective
  on how your code gets compiled.&lt;/p&gt;

&lt;p&gt;After these Rich gave a talk on the recent work he's been doing
  on chunked sequences. Basically when a seq wraps a vector or
  vector-like collection, rather than every first/rest invocation
  breaking the vector down piece by piece, the seq can break a chunk
  of the vector off to work on all at once and keep its own internal
  counter that points to the current position in the chunk. The
  motivation here was that while you generally can rely on the seq
  abstraction to map over each element in a vector in a functional
  manner, sometimes performance concerns force you to use a more
  imperative-style loop instead. With the chunking in place, the map
  approach is even more performant than the less-idiomatic loop, so
  there's one fewer reason to stray from the functional
  approach. It's really encouraging to see that Rich is making this
  a priority&amp;mdash;he wants to make sure that you never get
  penalized for doing things the elegant way.&lt;/p&gt;

&lt;p&gt;After this Rich hosted a Q&amp;amp;A session, from which two main
  points stuck in my mind. He mentioned that before the 1.0 release,
  he &lt;a href='http://groups.google.com/group/clojure/browse_thread/thread/2ee2b28e9dd3516b/b09cdc226c95383a'&gt;asked
  what people thought would be a good set of short-term goals for
  the project&lt;/a&gt;, to which the response was overwhelmingly &quot;move
  off SVN to git&quot;. Since the project was still fresh of a jump from
  SourceForge to Google Code, he was reluctant at first, but he
  seems to have been convinced that the distributed approach is
  what's best for the community. He promised us that the move will
  happen. He's
  currently &lt;a href='http://github.com/richhickey'&gt;experimenting
  with GitHub&lt;/a&gt; and making sure for himself that tool support is
  good enough.&lt;/p&gt;

&lt;p&gt;The other question of particular interest
  was &lt;a href='http://blog.objectmentor.com/articles/2009/06/05/rich-hickey-on-testing'&gt;that
  of tests&lt;/a&gt;. Rich doesn't write tests for Clojure. The community
  has contributed a test suite, but it's kept in a separate
  repository and doesn't offer full coverage. Rich's opinion is that
  tests are for finding bugs, and that he is able to avoid bugs by
  reasoning out the problem up front, so it's not a wise use of his
  time for him to write his own tests, though he does appreciate and
  run the community-provided suite. This made me very nervous at
  first, but the next day I read
  &lt;a href='http://web.mac.com/ben_moseley/frp/paper-v1_01.pdf'&gt;Out
    of the Tarpit&lt;/a&gt; [PDF], a paper he recommended at the meeting.
    The paper makes a strong case for informal reasoning being a
    suitable substitute for test cases in codebases that exhibit
    referential transparency. While I still prefer TDD for its help
    in the design phase of coding, I'm much more ready to accept the
    notion that thinking through the problem up front and verifying
    it with manual tests is actually a feasible approach to getting
    working code in functional languages, though of course in
    situations where mutability is the norm it leads to disastrous
    results.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: &lt;a href='http://tomfaulhaber.blip.tv'&gt;Videos&lt;/a&gt;
  are up! (Unfortunately flash-only; sorry!)&lt;/p&gt;

    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20are%20found%20tricks%20of%20the%20trade%20concerning%20clojure%20authorship</id>
    <published>2009-05-27T17:35:46Z</published>
    <updated>2009-05-27T17:35:46Z</updated>

    <link href="http://technomancy.us/126" rel="alternate" type="text/html"/>
    <title>in which are found tricks of the trade concerning clojure authorship</title>
    <content type="html">
      &lt;p&gt;So it turns out getting set up to write Clojure code can be a
  little tricky. There are a lot of disconnected tidbits about how folks
  have figured out how to configure things, but it can be a bit
  tricky to tell the difference between, &quot;hey, this is how I finally
  got it to work&quot; and &quot;this is how you really should be doing it&quot;. I
  figure I know about as much about using Clojure with Emacs as
  anybody, so here's a run-through of how I've done my setup. There
  are a lot of moving parts, but bear with me; most of the
  installation is automated.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Spoiler Alert&lt;/b&gt;: Using SLIME with Clojure is now much
  easier than the instructions detailed below indicate. This page is
  left up as it provides some background that may be helpful, but if
  you just want to get going with
  SLIME, &lt;a href=&quot;/swank-clojure.html&quot;&gt;use ELPA&lt;/a&gt;.&lt;/p&gt;

&lt;a name=&quot;pieces&quot;&gt;&lt;/a&gt;
&lt;h3&gt;The Pieces&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;a href='http://tromey.com/elpa'&gt;ELPA&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;The Emacs Lisp Package Archive functions as a centralized
    store for Emacs libraries and provides automated installation and
    upgrades.&lt;/dd&gt;

  &lt;dt&gt;&lt;a href='http://github.com/jochu/clojure-mode'&gt;clojure-mode&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;This gets you syntax highlighting, indentation, and other basic
    goodies for editing .clj files.&lt;/dd&gt;

  &lt;dt&gt;&lt;a href='http://common-lisp.net/project/slime/'&gt;SLIME&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;The Superior Lisp Interaction Mode for Emacs was originally
    written to support interacting with Common Lisp subprocesses from
    within Emacs, but it's been extended to work with other
    lisps.&lt;/dd&gt;

  &lt;dt&gt;&lt;a href='http://github.com/jochu/swank-clojure'&gt;swank-clojure&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;An adapter for SLIME that allows it to work with Clojure.&lt;/dd&gt;

  &lt;dt&gt;&lt;a href='http://github.com/jochu/clojure-mode'&gt;clojure-test-mode&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;This provides support for running Clojure tests from within
    Emacs buffers and seeing the results displayed inline.&lt;/dd&gt;

  &lt;dt&gt;&lt;a href='http://mumble.net/~campbell/emacs/paredit.el'&gt;paredit&lt;/a&gt;&lt;/dt&gt;
  &lt;dd&gt;Paredit auto-balances parentheses and other matched chars to
  make sure you don't end up with structurally invalid
  expressions.&lt;/dd&gt; &lt;/dl&gt;

&lt;a name=&quot;installation&quot;&gt;&lt;/a&gt;
&lt;h3&gt;Installation&lt;/h3&gt;

&lt;p&gt;The easiest way to get started is to grab ELPA. If you
  use &lt;a href='http://github.com/technomancy/emacs-starter-kit'&gt;Emacs
  Starter Kit&lt;/a&gt; you've already got ELPA. (If you're new to Emacs,
  you might want to use the Starter Kit anyway as a base for your
  own customizations; also check out
  the &lt;a href='http://peepcode.com/products/meet-emacs'&gt;PeepCode
  screencast&lt;/a&gt;.) Use &lt;kbd&gt;M-x package-list-packages&lt;/kbd&gt; to pull
  up the package list. Move down to &lt;code&gt;clojure-mode&lt;/code&gt; and
  press &lt;kbd&gt;i&lt;/kbd&gt; to mark it for installation, then
  press &lt;kbd&gt;x&lt;/kbd&gt; to go.&lt;/p&gt;

&lt;p&gt;Once it's installed you should be able to work with .clj files,
  and you may be happy with just this. It has rudimentary subprocess
  support with &lt;kbd&gt;M-x run-lisp&lt;/kbd&gt;, which is good enough for
  many, including Rich Hickey, the creator of Clojure. But most of
  us find it much more convenient to interact more richly with a
  running Clojure process as we code.&lt;/p&gt;

&lt;p&gt;&lt;strike&gt;Pressing &lt;kbd&gt;M-x clojure-install&lt;/kbd&gt; will kick off the
  Clojure installation process. Once you choose a download location,
  it will download a number of repositories and compile Clojure
  itself, so it will take a few minutes. (It requires having git,
  Java 1.5+, and ant installed.)  When it's done, it will configure
  SLIME and swank-clojure, and it will give you instructions on a
  few lines to add to your personal config (usually found
  in &lt;code&gt;$HOME/.emacs.d/init.el&lt;/code&gt;) so it will work for future
  sessions.&lt;/strike&gt; Deprecated in favour
  of &lt;a href=&quot;/swank-clojure.html&quot;&gt;similar functionality in
  swank-clojure&lt;/a&gt;.&lt;/p&gt;

&lt;a name=&quot;usage&quot;&gt;&lt;/a&gt;
&lt;h3&gt;Usage&lt;/h3&gt;

&lt;p&gt;Hitting &lt;kbd&gt;M-x slime&lt;/kbd&gt; will launch a new Clojure session in
  a &lt;code&gt;*slime-repl*&lt;/code&gt; buffer. You can also interact with
  the &lt;code&gt;*inferior-lisp*&lt;/code&gt; buffer, but the slime-repl buffer provides
  a higher-level interface with a few extra niceties. The REPL
  works as you'd expect, but you can hit &lt;kbd&gt;,&lt;/kbd&gt; to activate
  some shortcuts, the most useful being &lt;kbd&gt;i&lt;/kbd&gt; to change the
  current namespace (with tab-completion) and &lt;code&gt;restart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Back in your .clj buffers, &lt;kbd&gt;C-x C-e&lt;/kbd&gt; has been rebound to
  execute the form under the point in Clojure instead of Elisp. This
  is handy, but you won't get accurate line numbers from stack
  traces involving functions loaded this way. Pressing &lt;kbd&gt;C-c
  C-k&lt;/kbd&gt; will load the entire file and ensure stack traces come
  through accurately.&lt;/p&gt;

&lt;p&gt;As you type out function calls, you should see their argument
  list show in the minibuffer. This is called &lt;code&gt;eldoc&lt;/code&gt;, and
  it's a great way to get a quick refresher about what a function
  expects. For full documentation lookup you'll need to get handy
  with &lt;kbd&gt;C-c C-d d&lt;/kbd&gt; though. Finally you can
  use &lt;kbd&gt;M-.&lt;/kbd&gt; to jump to the definition of any given
  function.&lt;/p&gt;

&lt;a name=&quot;projects&quot;&gt;&lt;/a&gt;
&lt;h3&gt;Projects&lt;/h3&gt;

&lt;p&gt;Of course, after a while you'll be done with just playing at the
  REPL and want to hack on a real project. Since the JVM doesn't
  allow you to modify the classpath at runtime, you need to specify
  up front where it should look for code. The simplest thing to do
  is add &lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;test/&lt;/code&gt;, &lt;code&gt;lib/&lt;/code&gt;,
  and &lt;code&gt;classes/&lt;/code&gt; (for AOT compilation, if desired)
  directories in your project root to the classpath. Then you place
  your dependency jars in the &lt;code&gt;lib&lt;/code&gt; directory. &lt;strike&gt;If
  you've got complicated dependencies, you could
  &lt;a href='http://github.com/dysinger/clojure-pom'&gt;use maven to
  manage them&lt;/a&gt;, but if you've only got a couple it's not hard to
  do by hand.&lt;/strike&gt;
  Use &lt;a href=&quot;http://github.com/technomancy/leiningen&quot;&gt;Leiningen&lt;/a&gt;
  for dependency management and other build needs.&lt;/p&gt;

&lt;p&gt;Invoking &lt;kbd&gt;M-x swank-clojure-project&lt;/kbd&gt; will prompt you for
  a project root and start SLIME with the classpath configured
  appropriately.&lt;/p&gt;

&lt;a name=&quot;tests&quot;&gt;&lt;/a&gt;
&lt;h3&gt;Tests&lt;/h3&gt;

&lt;p&gt;If you've written automated tests for your project using
  the &lt;code&gt;clojure.test&lt;/code&gt; library (which you should), you can
  use &lt;code&gt;clojure-test-mode&lt;/code&gt; to run them. Install it
  via &lt;kbd&gt;M-x package-list-packages&lt;/kbd&gt;, and then you can
  use &lt;kbd&gt;C-c C-,&lt;/kbd&gt; to run the tests in the current
  buffer. Failures and errors get highlighted, so if you want to see
  details about a failure, move the point to the red region and
  press &lt;kbd&gt;C-c C-'&lt;/kbd&gt;.&lt;/p&gt;

&lt;h3&gt;Happy Hacking&lt;/h3&gt;

&lt;p&gt;I hope this is helpful and clears up some confusion. Now get out
  there and &lt;a href='http://github.com/languages/Clojure'&gt;write some
    code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: If you are using Slime with both Clojure and
  Common Lisp, refer to the instructions
  at &lt;a href='http://felipero.posterous.com/1446961'&gt;http://felipero.posterous.com/1446961&lt;/a&gt;.&lt;/p&gt;

    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20a%20tool%20helps%20with%20relaxation</id>
    <published>2009-05-19T17:20:29Z</published>
    <updated>2009-05-19T17:20:29Z</updated>

    <link href="http://technomancy.us/125" rel="alternate" type="text/html"/>
    <title>in which a tool helps with relaxation</title>
    <content type="html">
      &lt;p&gt;I've been experimenting a bit with &lt;a href='http://couchdb.apache.org'&gt;CouchDB&lt;/a&gt; recently. I've been really impressed with how quickly it lets you get started; interacting with it always feels &lt;i&gt;obvious&lt;/i&gt;. I've spent enough time doing web apps to get tired of how everyone always jumps straight to the unholy combination of a relational database system and object-relational mapper whenever they need any persistence. (When all you have is a hammer...) So using CouchDB with a functional language is a breath of fresh air.&lt;/p&gt;
&lt;img src='/i/relax.png' alt='relax.el' align='right' /&gt;
&lt;p&gt;Putting together a CouchDB adapter in Clojure is really a matter of no more than a page worth of code once you've got an &lt;a href='http://github.com/technomancy/clojure-http-client'&gt;HTTP client&lt;/a&gt;, so it's left as an exercise to the reader. Since functional languages encourage working closer to your core data types (which have clear mappings to JSON) there's very little cognitive overhead when it comes to using Couch for persistence.&lt;/p&gt;
&lt;p&gt;Last week while I was in Portland I put together a client written in Elisp &lt;a href='http://github.com/technomancy/relax.el'&gt;called relax.el&lt;/a&gt;. This lets you browse Couch databases from the comfort of Emacs. It also lets you edit documents straight from an Emacs buffer, which is much more convenient than using the browser's text tools from Futon.&lt;/p&gt;
&lt;p&gt;There are a few quirks with regard to pagination, (just press &lt;kbd&gt;g&lt;/kbd&gt; if it gets messed up) but it's pretty useful as it is. It should be in &lt;a href='http://tromey.com/elpa'&gt;ELPA&lt;/a&gt; soon, so &lt;kbd&gt;M-x knock-yourself-out&lt;/kbd&gt;.&lt;/p&gt;
    </content>
  </entry>
  
  <entry xml:base="http://technomancy.us">
    <author><name>Phil Hagelberg</name></author>
    <id>tag:technomancy.us,2007:in%20which%20codes%20are%20peeped%20at,%20in%20clojure</id>
    <published>2009-04-24T21:30:08Z</published>
    <updated>2009-04-24T21:30:08Z</updated>

    <link href="http://technomancy.us/124" rel="alternate" type="text/html"/>
    <title>in which codes are peeped at, in clojure</title>
    <content type="html">
      &lt;p&gt;I'm very proud to announce the release of my latest
  project, &lt;a href='http://peepcode.com/products/functional-programming-with-clojure'&gt;Functional
  Programming with Clojure&lt;/a&gt;,
  a &lt;a href='http://peepcode.com'&gt;PeepCode&lt;/a&gt; screencast created
  with &lt;a href='http://topfunky.com'&gt;Geoffrey Grosenbach&lt;/a&gt;. We
  were lucky to have Rich Hickey, the creator of Clojure do the
  technical review.&lt;/p&gt;

&lt;a href='http://peepcode.com/products/functional-programming-with-clojure'&gt;
  &lt;img src='/i/peepcode-clojure-title.png' alt='FP with CLJ' align='right' /&gt;&lt;/a&gt;

&lt;p&gt;I've &lt;a href='/121'&gt;blogged&lt;/a&gt; about &lt;a href='/122'&gt;Clojure&lt;/a&gt;
  before. It's becoming clear that with the way multi-core systems
  are becoming the norm, functional programming provides tools to
  handle concurrency in a straightforward way. Languages like
  Haskell and Erlang are experiencing surges in popularity, but
  Clojure brings some &lt;a
  href='http://constc.blogspot.com/2009/03/relativity-of-simultaneity.html'&gt;great
  new tricks&lt;/a&gt; of its own to the table. Part of this is its
  heritage as part of the Lisp family of languages, part of it is
  being built on a really solid virtual machine, and part of it is
  Rich's ingenuity that shines in its design.&lt;/p&gt;

&lt;img src='/i/peepcode-clojure-reduce.png' alt='reduce' align='left' /&gt;

&lt;p&gt;If you've been wanting to dive into Clojure, this is a great way
  to get started quickly. The screencast steps through the development
  of &lt;a href='http://github.com/technomancy/mire'&gt;Mire&lt;/a&gt;, a
  multiplayer text adventure. I found this to be an fitting
  project to showcase Clojure's strengths since it involves
  concurrent processing while still requiring state to be shared
  between threads, and it's simple enough to cover in an hour.&lt;/p&gt;

&lt;p&gt;So take a look! I think
  you'll &lt;a href='http://search.twitter.com/search?q=clojure+peepcode'&gt;like&lt;/a&gt;
  it.&lt;/p&gt;
    </content>
  </entry>
  
</feed>
