<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  
  <channel>
    <title>contrapunctus</title>
    <link>http://contrapunctus.net/</link>
    <description>Web site for Christopher League</description>
    <lastBuildDate>Tue, 17 Jul 2012 00:07:00 EDT</lastBuildDate>
    <language>en-us</language>
    <atom:link href="http://contrapunctus.net/blog/feed" rel="self" type="application/rss+xml"></atom:link>
    <item>
      <title>ANTLR Example in C</title>
      <link>http://contrapunctus.net/blog/2012/antlr-c</link>
      <guid>http://contrapunctus.net/blog/2012/antlr-c</guid>
      <pubDate>Tue, 17 Jul 2012 00:07:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4504040859/" title="Windswept tree by chris league, on Flickr"><img src="http://farm5.staticflickr.com/4044/4504040859_966a8d4d7a_m.jpg" width="240" height="160" alt="Windswept tree" /></a>
    </div><p>As a project, a student wants to implement a parser for a small
      language in C/C++. I considered reaching back into my ancient
      experience with YACC/Bison, but instead we decided to
      try <a href="http://antlr.org/">ANTLR</a>. This is
      an <i>LL(*)</i> parser generator that produces a
      recursive-descent (top-down) implementation. YACC/Bison, in
      contrast, are <i>LR</i> (bottom-up).</p><p>Let me interject here that I never considered parsing a very
      interesting problem in language implementation. I'm open to
      arguments to the contrary; maybe it just isn't to my taste. As a
      programmer, I appreciate clean and regular syntax, but as a
      language implementer I see the appeal of Lisp's non-syntax –
      just give me the AST directly.</p><p>ANTLR is written in Java, but supports several other languages
      for its output. The documentation for these other languages is a
      bit sparse, so it may be best to learn its capabilities in Java
      and then port them. Ultimately, I was reading
      the <tt>antlr3.h</tt> files to figure out the capabilities of
      tree and string types.</p><p>ANTLR has some useful operators for structuring and rewriting
      the resulting AST, which is especially helpful given the
      restriction against left-recursive grammars. Some examples also
      use a separate specification for a <i>tree grammar</i> that
      interprets the output of the parser in some way. We definitely
      want a grammar that produces an AST, but for further processing
      we'll stick to straight C/C++ without needing the tool.</p><h2>ExprCppTree.g</h2><p>Here is the grammar file. One of the tricks for later
      post-processing is that you want to define as many named tokens
      as possible: replacing something like <tt>('+'|'-')</tt>
      with <tt>(PLUS|MINUS)</tt> is beneficial because you can switch
      on the token type using <tt>case PLUS</tt> in the
      interpreter.</p><pygment lang="antlr">
grammar ExprCppTree;

options {
    language = C;
    output = AST;
    ASTLabelType=pANTLR3_BASE_TREE;
}

@header {
    #include <assert.h>
}

// The suffix '^' means make it a root.
// The suffix '!' means ignore it.

expr: multExpr ((PLUS^ | MINUS^) multExpr)*
    ;

PLUS: '+';
MINUS: '-';

multExpr
    : atom (TIMES^ atom)*
    ;

TIMES: '*';

atom: INT
    | ID
    | '('! expr ')'!
    ;

stmt: expr NEWLINE -> expr  // tree rewrite syntax
    | ID ASSIGN expr NEWLINE -> ^(ASSIGN ID expr) // tree notation
    | NEWLINE ->   // ignore
    ;

ASSIGN: '=';

prog
    : (stmt {pANTLR3_STRING s = $$stmt.tree->toStringTree($$stmt.tree);
             assert(s->chars);
             printf(" tree \%s\n", s->chars);
            }
        )+
    ;

ID: ('a'..'z'|'A'..'Z')+ ;
INT: '~'? '0'..'9'+ ;
NEWLINE: '\r'? '\n' ;
WS : (' '|'\t')+ {$$channel = HIDDEN;}; </pygment><h2>ExprCppTree.cpp</h2><p>One other thing I ought to point out here is that I'm using the
      tilde <tt>~</tt> as the negation operator, as in SML. This
      avoids having to figure out conflicts between subtraction and
      negation.</p><pygment lang="c++">
#include "ExprCppTreeLexer.h"
#include "ExprCppTreeParser.h"
#include <cassert>
#include <map>
#include <string>
#include <iostream>

using std::map;
using std::string;
using std::cout;

class ExprTreeEvaluator {
    map<string,int> memory;
public:
    int run(pANTLR3_BASE_TREE);
};

pANTLR3_BASE_TREE getChild(pANTLR3_BASE_TREE, unsigned);
const char* getText(pANTLR3_BASE_TREE tree);

int main(int argc, char* argv[])
{
  pANTLR3_INPUT_STREAM input;
  pExprCppTreeLexer lex;
  pANTLR3_COMMON_TOKEN_STREAM tokens;
  pExprCppTreeParser parser;

  assert(argc > 1);
  input = antlr3AsciiFileStreamNew((pANTLR3_UINT8)argv[1]);
  lex = ExprCppTreeLexerNew(input);
  tokens = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT,
                                            TOKENSOURCE(lex));
  parser = ExprCppTreeParserNew(tokens);

  ExprCppTreeParser_prog_return r = parser->prog(parser);

  pANTLR3_BASE_TREE tree = r.tree;

  ExprTreeEvaluator eval;
  int rr = eval.run(tree);
  cout << "Evaluator result: " << rr << '\n';

  parser->free(parser);
  tokens->free(tokens);
  lex->free(lex);
  input->close(input);

  return 0;
}

int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree)
{
    pANTLR3_COMMON_TOKEN tok = tree->getToken(tree);
    if(tok) {
        switch(tok->type) {
        case INT: {
            const char* s = getText(tree);
            if(s[0] == '~') {
                return -atoi(s+1);
            }
            else {
                return atoi(s);
            }
        }
        case ID: {
            string var(getText(tree));
            return memory[var];
        }
        case PLUS:
            return run(getChild(tree,0)) + run(getChild(tree,1));
        case MINUS:
            return run(getChild(tree,0)) - run(getChild(tree,1));
        case TIMES:
            return run(getChild(tree,0)) * run(getChild(tree,1));
        case ASSIGN: {
            string var(getText(getChild(tree,0)));
            int val = run(getChild(tree,1));
            memory[var] = val;
            return val;
        }
        default:
            cout << "Unhandled token: #" << tok->type << '\n';
            return -1;
        }
    }
    else {
        int k = tree->getChildCount(tree);
        int r = 0;
        for(int i = 0; i < k; i++) {
            r = run(getChild(tree, i));
        }
        return r;
    }
}

pANTLR3_BASE_TREE getChild(pANTLR3_BASE_TREE tree, unsigned i)
{
    assert(i < tree->getChildCount(tree));
    return (pANTLR3_BASE_TREE) tree->getChild(tree, i);
}

const char* getText(pANTLR3_BASE_TREE tree)
{
    return (const char*) tree->getText(tree)->chars;
} </pygment><h2>Demo</h2><p>Given the text file:</p><pygment lang="text">
a = 3
b = 14
(a+b)-2 * ~4 </pygment><p>This program outputs:</p><pygment lang="text">
 tree (= a 3)
 tree (= b 14)
 tree (- (+ a b) (* 2 ~4))
Evaluator result: 25 </pygment><h2>Update</h2><p>This works with ANTLR version 3.2 (debian stable), but I also
    learned today there are some significant C API changes in the
    latest, version 3.4. For one, <tt>antlr3AsciiFileStreamNew</tt>
    must be replaced with <tt>antlr3FileStreamNew(filename,
    ANTLR3_ENC_8BIT)</tt>.
</p>]]></content:encoded>
    </item><item>
      <title> H8</title>
      <link>http://contrapunctus.net/blog/2012/h8</link>
      <guid>http://contrapunctus.net/blog/2012/h8</guid>
      <pubDate>Fri, 23 Mar 2012 00:03:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_180_3 right unlink">
  <a href="http://www.flickr.com/photos/chrisleague/4502643072/" title="Oz by chris league, on Flickr"><img src="http://farm5.staticflickr.com/4052/4502643072_7b5be70135_m.jpg" width="184" height="240" alt="Oz" /></a>
</div><p>I have mixed feelings about the conviction of Dharun Ravi. Obviously
the death of Tyler Clementi broke my heart, and Ravi’s actions were
pretty vile. But it’s a mistake to presume a direct link between a few
incidents of boorish badgering and a suicide.</p><p>I don’t think there’s any doubt that Ravi would not be in this
circumstance if Clementi were still alive. So here’s the awful message
the conviction sends to beleaguered kids: the way to get back at your
bully is to throw yourself off a bridge.</p><p>Please don’t. Find a safe zone, call the <a href="http://www.thetrevorproject.org/">Trevor
Project</a>. Find a way to stay with
us. The world will learn to love you as you are, I promise. It gets
better.</p>]]></content:encoded>
    </item><item>
      <title>Subpixels</title>
      <link>http://contrapunctus.net/blog/2012/subpixelize</link>
      <guid>http://contrapunctus.net/blog/2012/subpixelize</guid>
      <pubDate>Tue, 13 Mar 2012 00:03:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/6169355798/" title="BAM pixels by chris league, on Flickr"><img src="http://farm7.staticflickr.com/6175/6169355798_87f310e597_m.jpg" width="240" height="143" alt="BAM pixels" /></a>
      <a href="http://www.flickr.com/photos/chrisleague/6954277683/" title="MOAR pixels by chris league, on Flickr"><img src="http://farm8.staticflickr.com/7182/6954277683_5cf3175293_m.jpg" width="240" height="143" alt="MOAR pixels" /></a>
    </div><div class="frame_400_5 right unlink">
      <img src="/pix/2012/bart.png" width="400" height="414" alt="Bart Simpson rendered in RGB" />
    </div><p>Every day on my way to the office, I pass this large animated
    display on Flatbush Avenue for the Brooklyn Academy of Music. It's
    a good illustration for computing novices of how pixels in an
    image are made up solely of red, green, and blue lights. On this
    sign, it's easy to see the subpixel configuration when you are up
    close:</p><pre>
      <span style="color: #0a0">G</span><span style="color: #f00">R</span><span style="color: #00f">B</span>
      <span style="color: #00f">B</span><span style="color: #f00">R</span><span style="color: #0a0">G</span>
</pre><p>Below it is another sign, with differently-shaped pixels, that
    I saw recently in Orlando. It has one blue light in the center,
    with two red and green lights at diagonals.</p><p>I decided to write a program I could use to demonstrate what
    any image would look like when rendered by the BAM sign. Each
    pixel in
    the <a href="https://github.com/league/subpixelize/raw/master/bart-in.png">input
    image</a> is expanded into 4×3 pixels in the output image,
    including a black margin between each group of subpixels.</p><p>You can see the result to the right. Bart's eyes still look
    relatively white, but if you look close or zoom in, they're made
    up only of red-green-blue dots. Below is the code, using
    the <a href="http://www.imagemagick.org/Magick++/">Magick++
    library</a>. See
    also <a href="https://github.com/league/subpixelize">the
    subpixelize repository</a> on github.</p><pygment lang="c++">
#include <Magick++.h>
#include <iostream>
#include <cassert>

using std::cout;
using std::string;
using namespace Magick;

/* Each pixel in input image is rendered as
 *    GRBx
 *    BRGx
 *    xxxx
 * in the output image. So pixels are 4x3,
 * including inter-pixel space.
 */

int main(int argc, char** argv)
{
    InitializeMagick(*argv);
    if(argc != 3) {
        cout << "Usage: " << argv[0] << " input.png output.png\n";
        exit(1);
    }

    const string inputPath = argv[1];
    const string outputPath = argv[2];

    cout << "Loading " << inputPath << '\n';
    Image in (inputPath);
    Geometry gin = in.size();
    assert(in.depth() <= 8);
    assert(in.type() == TrueColorType);
    cout << gin.width() << 'x' << gin.height() << '\n';

    Geometry gout(gin.width()*4, gin.height()*3);

    Image out;
    out.size(gout);
    out.magick("RGBA");
    cout << "Writing " << outputPath << '\n';
    for(unsigned x = 0; x < gin.width(); x++) {
        for(unsigned y = 0; y < gin.height(); y++) {
            Color c = in.pixelColor(x,y);
            unsigned i = x*4;
            unsigned j = y*3;
            // Row 0: GRB
            out.pixelColor(i+0, j+0, Color(0, c.greenQuantum(), 0));
            out.pixelColor(i+1, j+0, Color(c.redQuantum(), 0, 0));
            out.pixelColor(i+2, j+0, Color(0, 0, c.blueQuantum()));
            // Row 1: BRG
            out.pixelColor(i+0, j+1, Color(0, 0, c.blueQuantum()));
            out.pixelColor(i+1, j+1, Color(c.redQuantum(), 0, 0));
            out.pixelColor(i+2, j+1, Color(0, c.greenQuantum(), 0));
        }
    }
    out.write(outputPath);
    return 0;
}
    </pygment>]]></content:encoded>
    </item><item>
      <title>Gamer generations</title>
      <link>http://contrapunctus.net/blog/2011/zork</link>
      <guid>http://contrapunctus.net/blog/2011/zork</guid>
      <pubDate>Mon, 03 Oct 2011 00:10:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/6107501457/" title="IMG_3471 by chris league, on Flickr"><img src="http://farm7.static.flickr.com/6202/6107501457_4b3225b691_m.jpg" width="240" height="160" alt="IMG_3471" /></a>
    </div><p>A recent email exchange with a curious student that brought
    back memories. Posted without further comment.</p><blockquote>
      <p><b>Subject:</b> Zork<br /> Are you fimilar with this text
        based video game of the 80s? If so can you explain to me how
        it was made, programming-wise?</p>
    </blockquote><p>OMG definitely. Spent many hours solving Zork 2 and/or 3,
        many of them with my high school buddy in the office of our
        chemistry teacher, who was also a fan.</p><p>I really don't know much about how they were programmed,
        although I did try to reproduce some of the basic ideas on my
        own. There were some listings in magazines of programs in
        BASIC that implemented simpler text adventures, I might have
        just modified those.</p><p>Here's a reference to
      one <a href="http://en.wikipedia.org/w/index.php?title=Adventure_game&amp;oldid=480965807">from
          Wikipedia</a>:</p><blockquote>
        Pirate Adventure, was an original game in a similar style to
        Adventure—its source code, written in BASIC, was published in the
        December 1980 issue of Byte magazine.[41][44]
        </blockquote><p>but I can't find the article online.</p>]]></content:encoded>
    </item><item>
      <title>Blackboard, my nemesis, we meet again.</title>
      <link>http://contrapunctus.net/blog/2011/blackboard</link>
      <guid>http://contrapunctus.net/blog/2011/blackboard</guid>
      <pubDate>Wed, 10 Aug 2011 00:08:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_360_5 right unlink">
      <a href="http://www.meetup.com/ny-scala/photos/2120721/" title="New York Scala Enthusiasts - meetup.com"><img src="http://photos2.meetupstatic.com/photos/event/4/9/e/9/event_35658921.jpeg" width="360" height="215" /></a>
    </div><p>I almost made my peace with Blackboard for the upcoming
    semester. I recently discovered that they support WebDAV for
    transferring files in and out of the ‘content collection’.
    Although WebDAV largely sucks, this was a revelation. It meant I
    could use real tools like rsync instead of
    clickety-clickety-uploading files one at a time. I pictured using
    Blackboard just as a shell, with its discussion fora and
    gradebook, but with most of my content (notes, assignments) in
    uploaded HTML. I don't want that kind of content managed directly
    by Blackboard, which makes it way too hard. There are plenty of
    great tools to generate HTML from simpler sources – with syntax
    highlighting for code – such
    as <a href="http://johnmacfarlane.net/pandoc/">pandoc</a>.
    </p><p>Of course, while experimenting today I found not one but two
      showstopping misfeatures. The first is that, once in a while,
      Blackboard decided not to display the HTML content within its
      frame, but rather to download it. I couldn't for the life of me
      figure out on what it based this decision. In one case I opened
      an editor over WebDAV, added one line, and thereafter it would
      switch from download to inline display.</p><div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/6029422233/" title="Screenshot-1 by chris league, on Flickr"><img src="http://farm7.static.flickr.com/6080/6029422233_a5337cc39a_m.jpg" width="240" height="156" alt="Screenshot-1" /></a>
    </div><p>The second problem was that, after an rsync, Blackboard would
      decide that, because the file I had linked into the content area
      had changed, it wouldn't link to it anymore, and instead display
      the title with the message “(Invalid File)”. Helpful.
      Clickety-clickety to fix them all again.</p><p>(It's conceivable that some of these issues are due partly to
      buggy WebDAV on either end, but I'm unwilling to investigate too
      far just to exonerate Blackboard.)</p><p>So I'm back to linking to the course web site (which I'll
      probably build
      with <a href="https://github.com/jgm/yst">yst</a>) on an
      external server. I think what I most need in an LMS is for it to
      be a (very) thin layer on top of static HTML that can be
      generated however I want. I'm inspired by how easily you can add
      something like Disqus to static
      HTML. An LMS could just be an integrated collection of similar
      tools to provide discussions, gradebooks, assignment drop boxes,
      student profiles, etc.</p><p>I started to hack
      on <a href="https://github.com/league/l3ms">something like
      that</a>, but I'm not happy enough with it to use it for Fall
      2011. (And if I resume hacking on it, I'll probably start over
      and scrap Python.)</p>]]></content:encoded>
    </item><item>
      <title>Adventures with Xmonad</title>
      <link>http://contrapunctus.net/blog/2011/xmonad</link>
      <guid>http://contrapunctus.net/blog/2011/xmonad</guid>
      <pubDate>Wed, 03 Aug 2011 00:08:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/6003035302/" title="Xmonad by chris league, on Flickr"><img src="http://farm7.static.flickr.com/6023/6003035302_835c6b88cf_m.jpg" width="240" height="150" alt="Xmonad" /></a>
    </div><p>I switched back to GNU/Linux full-time (Ubuntu on ThinkPad
    x201) almost a year ago, but it was just this week that I found
    the will to meander away from the default Gnome 2 desktop and
    window manager.
    </p><p>In the world of X-windows, the way your desktop looks and
      behaves is controlled by an independent program called a window
      manager, and there are <i>many</i> such programs. I burned my
      way through several in the old days before Mac OS X. The first
      one I remember explicitly was <b>twm</b>, the default on our DEC
      Ultrix setup at the time.</p><div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/6002584585/" title="Xmonad by chris league, on Flickr"><img src="http://farm7.static.flickr.com/6144/6002584585_d39274952a_m.jpg" width="240" height="150" alt="Xmonad" /></a>
    </div><p>A persistent, though minority, approach in some window managers
      has been <i>tiling</i>. This idea abandons the typical (and once
      revolutionary) desktop metaphor of overlapping windows, like
      pages on a desk. Instead, your windows fall into particular
      patterns called layouts, covering whatever screen space is
      available.</p><p>The upshot is that – in most cases, with many types of apps –
      you don't have to think much about moving and resizing windows
      to see what you want. You also use the mouse a lot less.</p><p>I tried a few tiling WMs over the years in my pre-Mac Linux
      days, but none ever stuck for more than a day. They were hard to
      configure and, at times, clunky and awkward to use. Recently,
      though, I had been hearing about Xmonad, a window manager
      written in and configurable with – get this – Haskell!</p><p>Having a full-blown programming language in which to configure
      things makes a huge difference. Previous WMs required heavily
      repetitive but unrefactorable configs. (I guess I'm lucky that I
      knew Haskell already – it can be somewhat impenetrable to the
      uninitiated.) What's really remarkable about writing your Xmonad
      config in Haskell is that it's a statically-typed, compiled
      language. Most configuration languages are dynamic,
      loosely-typed: Emacs Lisp, Guile, Lua. And yet Xmonad can reload
      your config at any time, seamlessly. (It's fast, and doesn't
      lose state.) Now I'm having fantasies that one day we could have
      an Emacs configured in Haskell. Blasphemy?</p><p>My <a href="https://github.com/league/dot-files/blob/master/xmonad.hs">Xmonad
        configuration</a> is available on github if anyone is
        interested, along with other ‘dot files’. I did end up writing
        my own layout. I wanted one with a centered master window, big
        enough for 960-pixel web pages, and tiled windows along the
        side margins that the master actually overlaps. The side
        windows can be brought forward when focused, without having to
        swap them with master. It's kind of a mashup of the
        CenteredMaster and the Circle layouts in contrib.</p><p>If you'd like to explore tiling and can spend some time on
      configuration, I definitely recommend Xmonad!</p>]]></content:encoded>
    </item><item>
      <title>RGB Demo using HTML 5 canvas</title>
      <link>http://contrapunctus.net/blog/2010/rgb-demo</link>
      <guid>http://contrapunctus.net/blog/2010/rgb-demo</guid>
      <pubDate>Tue, 21 Sep 2010 00:09:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="/rgb-demo/"><img src="/pix/2010/rgb-demo-sm.png" width="228" height="143" alt="RGB screenshot" /></a>
    </div><p>This morning I whipped up my first (tiny) hand-coded HTML5 app,
      using the canvas tag for 2D drawing. The first unit of my CS0
      course is about binary representations of data, including
      numbers, text, and graphics. The graphics are of course the most
      fun — see also <a href="/blog/2008/hex-nostalgia">hex
      nostalgia</a>.
    </p><p>There’s no shortage of color-choosing widgets on the web, but I
      wanted one that would clearly illustrate the <i>additive</i>
      color model used by computer video displays and projectors. Most
      of the students are not media arts majors, and so they’re still
      attached to the <i>subtractive</i> primary colors they learned
      in elementary school. Despite their familiarity with displays
      that rely on it, “red + green = yellow” is not natural to them.
    </p><p>With the HTML5 canvas, additive color is a simple matter
    of:</p><pygment lang="js">
      context.globalCompositeOperation = 'lighter';
    </pygment><p>Once I got it working with the three 8-bit RGB sliders, I
      decided to have some fun with 4-bit color — call it
      <a href="http://en.wikipedia.org/wiki/Color_Graphics_Adapter">CGA</a>
      nostalgia. I recall my early days with PC BASIC (did color on TI
      and Apple work this way too?) when I first understood the
      pattern to the mapping of colors to the numbers 0–15.</p><p>Intarweb, je vous présente: <a href="/rgb-demo/4bit.html">4-bit
        color</a>, <a href="/rgb-demo/">24-bit color</a>. Feel free
        to view source.</p>]]></content:encoded>
    </item><item>
      <title>Clustering to learn</title>
      <link>http://contrapunctus.net/blog/2010/clustering</link>
      <guid>http://contrapunctus.net/blog/2010/clustering</guid>
      <pubDate>Tue, 14 Sep 2010 00:09:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/3582688814/" title="Spice bazaar - 2 by chris league, on Flickr"><img src="http://farm4.static.flickr.com/3311/3582688814_647452ca8f_m.jpg" width="240" height="160" alt="Spice bazaar - 2" /></a>
    </div><p>Every semester I have about 22 brand new students in an intro
      course. I try pretty hard to learn their names quickly, without
      sacrificing significant class time to the endeavor. There are
      always some I get right away (the ones that are outspoken from
      the first lecture), and others that take weeks (usually the ones
      that tend to be quiet and/or absent).
    </p><p>Our classrooms are amazingly diverse, and I truly enjoy
      that. It means I personally have a hand in broadening
      participation in computing, to use the NSF phrase. Plus it’s
      just darned interesting to work with people with varied
      backgrounds and stories.
    </p><p>To learn names, I notice myself doing something that I believe
      is perfectly harmless, natural, and useful, but could seem
      somewhat dubious from the outside.  That is, I cluster the names
      and faces by perceived ethnicity, race, and gender.  It means I
      don’t really have to match 22 names to 22 faces; I just have to
      distinguish names <i>within</i> the perceived cluster. Not every
      face is an equally likely candidate for the name Mahesh or
      Mahmud, Matsumoto, Miguel, or… Alice.
    </p><p>The embarrassing consequence, however, is that as I’m still
      learning, my mistakes appear to be indicative of my hillbilly
      heritage, namely, “durr… all y’all [ETHNIC] folks look alike!”
      By week three, I’m specifically focusing on distinguishing
      between (for example) the three quiet Indian women or the two
      absent Turkish guys.
    </p><p>I don’t believe there are any clusters for which I’m
      particularly better or worse at learning names, though I could
      be wrong. There probably <i>are</i> clusters for which I can
      make finer distinctions than others: Bangladeshis vs. Pakistanis
      vs. Hindu South Indians; or Chinese, Japanese, Thai (certainly
      by name, sometimes by face or dress).  But I’m useless at the
      varieties of Caribbean Islanders or Eastern Europeans.
    </p><p>Also, once in a while, my perception doesn’t match reality,
      such as when I guess that Bob Smith is Angelo Santos. But as a
      result of such a mistake, I manage to learn Bob’s and Angelo’s
      names indelibly! So perhaps intentionally making cross-ethnic
      mistakes would be an even better learning strategy.
    </p>]]></content:encoded>
    </item><item>
      <title>Dogfood U.</title>
      <link>http://contrapunctus.net/blog/2010/dogfood-u</link>
      <guid>http://contrapunctus.net/blog/2010/dogfood-u</guid>
      <pubDate>Thu, 09 Sep 2010 00:09:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/3578948662/" title="Puppy by chris league, on Flickr"><img src="http://farm4.static.flickr.com/3379/3578948662_66477e70cd_m.jpg" width="240" height="240" alt="Puppy" /></a>
    </div><p>In general, I’m a believer in what is known in software
      development as “eating your own dog food.” That is, you use the
      product you create, as you create it. A project to build project
      management software is managed using that software. Bugs in the
      bug tracking system are tracked in that system. A new
      distributed version control system is eventually hosted in its
      own repository. And so on.</p><p>The principle is most obvious, of course, for tools related to
      software development, but conceivably it can be pushed further,
      as long as the developer is a member of the target audience for
      the system.</p><p>Recently I began thinking about ‘dogfooding’ in the context of
      my primary responsibility: not software development, but
      teaching. I noticed a troubling inconsistency. I truly love
      learning; my life is structured so that I can explore and
      experiment with new ideas and techniques just about every day.
      However, I no longer have any interest in learning <em>in the
      context of a formal course.</em> It seems I don’t like the taste
      of my own medicine!
    </p><p>This isn’t even about the much-maligned lecture format or the
      traditional classroom. I’m happy to attend independent lectures
      about topics that interest me. And a flexible environment
      doesn’t make a course any more tolerable for me as a student. I
      think I just rebel at the prospect of following
      someone <em>else’s</em> syllabus.</p><p>Maybe this, as much as anything, is what a Ph.D. is about. It
      signifies a dedication to life-long learning, but also endows
      the scholar with the ability (and responsibility) to construct
      her own curriculum. Can one stand on the shoulders of giants
      without having to sit through their classes?
    </p>]]></content:encoded>
    </item><item>
      <title>Aftermath: empathy</title>
      <link>http://contrapunctus.net/blog/2010/aftermath-empathy</link>
      <guid>http://contrapunctus.net/blog/2010/aftermath-empathy</guid>
      <pubDate>Mon, 30 Aug 2010 00:08:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4528303958/" title="Aquarium by chris league, on Flickr"><img src="http://farm5.static.flickr.com/4045/4528303958_8ac2c88fce_m.jpg" width="240" height="160" alt="Aquarium" /></a>
    </div><p>Naturally, I wouldn’t wish heart disease on anyone, but it is
      kind of nice to read accounts of others going through the same
      thing at approximately the same time. Especially when they have
      the wit and wherewithal of biology professor and noted skeptic
      blogger PZ Myers. His posts
      on <i>My
      lost weekend</i>
      and <i>A
      fistful of stents</i> were familiar echoes. The latter one,
      about
      his <a href="http://en.wikipedia.org/wiki/Percutaneous_transluminal_coronary_angioplasty">PTCA</a>,
      is hilarious.
    </p><p>I don’t believe I was nearly that out of it during mine. Sure
      there’s some kind of relaxing agent in that IV (not bothering to
      look up what exactly it was), but I recall talking lucidly to
      the interventionist before, during, and after. And watching the
      radiography monitors as best I could, from a poor angle. I’m
      pretty sure I didn’t nap.</p><p>Of course, it’s super annoying that I’m not just twenty-some
      days ahead of PZ on this matter, but more like 16 years — he’s
      53, I’m 37. And this wasn’t my first time.  The good news is
      that, 42 days out, I still feel great, I’m adjusting dietary
      habits effectively, and
      I’m <a href="http://www.flickr.com/photos/chrisleague/4941235989/">shedding
      weight</a> steadily. You never know what’s going to kill you, or
      when. If there’s one positive spin on chronic disease, it
      provides a clear, likely threat and thus something to manage.
    </p><p><i>Nothing is built on stone; all is built on sand, but we must
        build as if the sand were stone.</i><br />— Jorge Luis Borges</p><p>P.S., unlike PZ, I like cabbage. But I’m terrified
    of <a href="http://en.wikipedia.org/wiki/CABG">CABG</a>.</p>]]></content:encoded>
    </item><item>
      <title>Aftermath: food</title>
      <link>http://contrapunctus.net/blog/2010/aftermath-food</link>
      <guid>http://contrapunctus.net/blog/2010/aftermath-food</guid>
      <pubDate>Sun, 08 Aug 2010 00:08:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_180_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4823852446/" title="Untitled by chris league, on Flickr"><img src="http://farm5.static.flickr.com/4100/4823852446_84078f7f3e_m.jpg" width="180" height="240" alt="Untitled" /></a>
    </div><p>Yeah, so I spent some time in the hospital this summer. I’m not
    going to get into the gory details at the moment, but suffice to
    say that I’ve known I had premature heart disease for some time,
    and on 20th July, it struck again. For the moment, I’m feeling
    pretty much normal. I’m on a bunch of new medication. I’m walking
    every day. I’ll know a lot more after 3 months out (around
    Hallowe’en). For now I want to focus on one aspect of the
    aftermath: food. And because I’m such a nerd, I have plenty of
    data, and charts!</p><p>We love food. The tremendous number, quality, and variety of
    restaurants in NYC is really one of the top perks of living
    here, just as the average apartment kitchen size is not! So
    although I enjoy cooking, particularly for special occasions,
    lately we had been eating dinners out almost every day.</p><p>Thanks to my obsessive use
    of <a href="http://wiki.github.com/jwiegley/ledger/">ledger</a>, I
    can compute average dining and grocery expenditures over the past
    several months. In the graph below, the blue line indicates
    restaurant expenses per day, averaged over the preceding seven
    days. The red line is the same computation for grocery
    expenses. (For any chromatically challenged readers, the blue line
    is the one on top, for most of the graph.) You can clearly see the
    inverse relationship in several places; when there is a sharp drop
    in restaurant expenses, there is usually a corresponding hump in
    grocery. (The large blue spike corresponds to a several-day
    getaway at the Borgata Water Club, Atlantic City.)
    </p><p class="center">
    <img src="/pix/2010/restaurant-v-grocery.png" width="627" height="433" alt="Restaurant and grocery expenditures" />
    </p><div class="frame_130_2 right unlink">
      <a href="http://www.amazon.com/gp/product/0848727584?ie=UTF8&amp;tag=christopheleague&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0848727584"><img border="0" width="129" height="160" src="/pix/2010/5146TVFSFmL._SL160_.jpg" /></a><img src="http://www.assoc-amazon.com/e/ir?t=christopheleague&amp;l=as2&amp;o=1&amp;a=0848727584" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
    </div><p>The gray rectangle on the X axis indicates the days I spent in
    the hospital. Something remarkable happens after that: restaurant
    expenses drop to nearly zero, and grocery stays somewhat high. In
    short, I’ve been cooking up a storm since being home! I started
    working through the <cite>New Mayo Clinic Cookbook,</cite> which a
    good friend gave me several years back.  I like that it has
    complete nutrition facts for every recipe.
    </p><p>While munching on hospital food, I came to think of restaurant
    food as inherently unhealthy. Even if you make reasonable choices
    regarding cuisine and dishes – which, for the most part, I thought
    I did – restaurant food is always going to be saltier and fattier
    than what I would prepare at home. I imagine I’ll eventually find
    some balance, where I won’t see restaurant food as poison, but
    rather something to be enjoyed in strict moderation;
    i.e., <em>not</em> six nights a week.
    </p><p>I also started tracking my weight, and everything I consumed,
      using the <a href="http://loseit.com/">LoseIt</a> iPhone app. It
      actually doesn’t seem <em>that</em> hard to drop some weight
      just by honestly counting calories; the awareness alone helps
      with willpower, and seeing some results is motivating too. Below
      is a graph of my daily weight measurements (blue diamonds) and
      trend (red line) since hospital. It was produced with
      the <a href="http://www.fourmilab.ch/hackdiet/online/hdo.html">Hacker’s
      Diet</a> online tools. (LoseIt should incorporate the trend
      computation too – it’s very helpful.)</p><p class="center">
      <img src="/pix/2010/weight-trend-08-08.png" width="454" height="368" alt="weight trend" />
    </p><p>I started the trend at two pounds heavier than the first
    sample. That was the last measurement I took before hospital, and
    having the graph reflect that there had already been <em>some</em>
    loss there was more motivating! Of course, this is just the
    beginning. I’d like to periodically post these graphs here or on
    Flickr, to put the evidence of my progress out there in public.
    </p>]]></content:encoded>
    </item><item>
      <title>Monadologie</title>
      <link>http://contrapunctus.net/blog/2010/monadologie</link>
      <guid>http://contrapunctus.net/blog/2010/monadologie</guid>
      <pubDate>Wed, 14 Jul 2010 00:07:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<p>Earlier this week, I presented on programming with
      continuations and monads in the Scala language, for a group of
      40 or so developers at a meetup in NYC.  I'm tickled that it
      seems to be getting some attention from Scala enthusiasts around
      the world.  I'll embed the video and slides below.</p><object width="540" height="304"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=13304075&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=ff0179&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=13304075&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=ff0179&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="540" height="304"></embed></object><p><a href="http://vimeo.com/13304075">Monadologie: Professional Help for Type Anxiety</a> from <a href="http://vimeo.com/n8han">Nathan Hamblen</a> on <a href="http://vimeo.com">Vimeo</a>.</p><div style="width:425px" id="__ss_4744323"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/league/monadologie" title="Monadologie">Monadologie</a></strong><object id="__sse4744323" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-100713072026-phpapp01&amp;stripped_title=monadologie" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed name="__sse4744323" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-100713072026-phpapp01&amp;stripped_title=monadologie" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/league">league</a>.</div></div><p>The code is available at <a href="http://github.com/league/scala-type-anxiety">github.com/league/scala-type-anxiety</a></p>]]></content:encoded>
    </item><item>
      <title>Objectivity and blindness</title>
      <link>http://contrapunctus.net/blog/2010/objectivity</link>
      <guid>http://contrapunctus.net/blog/2010/objectivity</guid>
      <pubDate>Tue, 25 May 2010 00:05:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_160_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4508325395/" title="Me on prime meridian by chris league, on Flickr"><img src="http://farm5.static.flickr.com/4045/4508325395_c92a32a162_m.jpg" width="160" height="240" alt="Me on prime meridian" /></a>
    </div><p>I believe I’m a reasonably objective grader, but if I wasn’t,
      would I know? Most everyone thinks they’re an above-average
      driver too.</p><p>It helps that, in my field, many responses are right or wrong;
      programs work or they don’t. Of course, I award partial credit
      for programs that partly work, or responses that are “on the
      right track,” so then it becomes fuzzy. I often use what
      one could (charitably) call a <em>rubric,</em> to help keep track
      of criteria and standards. But still, is it fair?</p><p>I’d like to think so, but one thing raises alarms. I notice
      myself doing it from time to time. In the midst of grading an
      exam, I’ll encounter a response so mystifying (or so brilliant –
      it can happen!) that I’ll flip to the front page as I ask,
      “who <b>is</b> this?” Does the score I award depend at all on
      the answer to that query?</p><p>Maybe in the future I will try blinding exams and significant
      assignments in some course, to deny myself the answer.</p>]]></content:encoded>
    </item><item>
      <title>Linux on my MacBook Pro</title>
      <link>http://contrapunctus.net/blog/2010/mac-linux</link>
      <guid>http://contrapunctus.net/blog/2010/mac-linux</guid>
      <pubDate>Fri, 21 May 2010 00:05:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4597746098/" title="Untitled by chris league, on Flickr"><img src="http://farm2.static.flickr.com/1147/4597746098_3c8298776c_m.jpg" width="240" height="180" alt="Untitled" /></a>
    </div><div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4592060860/" title="img_0351.jpg by chris league, on Flickr"><img src="http://farm5.static.flickr.com/4011/4592060860_9d9b340d49_m.jpg" width="240" height="180" alt="img_0351.jpg" /></a>
    </div><p>So, in the midst of finals, I decided to install the new Ubuntu
      10.04 GNU/Linux OS on my MacBook Pro.  A wellspring for
      procrastination, no doubt, but also I was again becoming
      concerned about
      my <a href="/blog/2006/dependence-on-proprietary-software">dependence
      on proprietary software</a>.  Combine that general orientation
      with some of Apple's <a href="/blog/2010/section-3-3-1">recent
      policies</a> and I was looking to escape – or, at least, to map
      out a possible escape route.</p><p>The
        Ubuntu <a href="https://help.ubuntu.com/community/MactelSupportTeam/AppleIntelInstallation">Apple/Intel
        installation directions</a> were very helpful, although things
        didn't go exactly as advertised. First, neither of the Mac
        tools (Disk Utility or Boot Camp) were able to shrink my
        partition. The got about halfway and then gave up and said it
        couldn't be done. That means I'd have to nuke and reinstall
        MacOS to make this work. It's a testament to my resolve – and
        my trust
        in <a href="http://rdiff-backup.nongnu.org/">rdiff-backup</a>
        – that I did just that.
    </p><p>So after reinstalling Snow Leopard on a shrunken partition,
      installing rEFIt as the initial boot loader, the Ubuntu install
      went smoothly. The only other thing that went wrong was that
      grub (the secondary boot loader) did not configure itself
      properly. Fortunately, grub has a command line and it's possible
      to guess the right incantations to get it to boot anyway.
    </p><p>It has been years since I used any sort of GNU/Linux
      desktop. From 1996 to 2005, my office machine was always Linux –
      at three different offices. In 2001 I bought my first Mac laptop
      (an iBook) but I did not start using Mac exclusively (or nearly
      so) until 2005, with my beloved 12” PowerBook. Even then, my two
      most well-worn apps are definitely emacs and zsh.</p><p>Anyway, a lot evolves in five years, especially thanks to the
      hard-working and well-funded folks at Ubuntu/Canonical. It has
      been a learning experience, but mostly positive. I love having
      all software managed by apt, once again.  Still think the Mac
      platform could benefit from <b>this</b> kind of an app
      repository — as long as unsanctioned sources are permitted. The
      Mac apps that may be the hardest to replace are: Keynote
      (OpenOffice Presentations are fine compared to Powerpoint, but
      Keynote is a cut
      above), <a href="http://skim-app.sourceforge.net/">Skim</a>
      and <a href="http://bibdesk.sourceforge.net/">BibDesk</a> (PDF
      annotations and bibliography tracking that work well together —
      both open source, but reliant on Mac GUI),
      and <a href="http://www.telestream.net/screen-flow/overview.htm">ScreenFlow</a>
      (really great for capturing and editing screencasts).
    </p><p>The first thing I felt I had to get sorted, though, was the
    keyboard!  Mac apps specialize in the so-called ‘command’ key (⌘),
    with control and option as distant cousins. Linux/Gnome apps
    prefer the control key, with ‘alt’ as a close second. So I wanted
    two control keys, and in better positions than the existing
    one. Below is the layout I came up with. It has left and right
    control, left and right alt, a ‘super’ [win] key (which is great
    for mapping window and desktop management functionality so it
    doesn't conflict with emacs) and the ‘multi’ key (aka compose
    character) for typing accented and other “§peçìâł” characters.
    </p><div class="frame_500_8 unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4627140524/" title="MacBook pro keyboard, as remapped for X11/Dvorak by chris league, on Flickr"><img src="http://farm4.static.flickr.com/3336/4627140524_dc949e1da4.jpg" width="500" height="254" alt="MacBook pro keyboard, as remapped for X11/Dvorak" /></a>
    </div><p>I did <b>not</b> rearrange the alphabetic key-caps as shown in
      the picture
      (by <a href="http://www.flickr.com/photos/doommeer/3100619105/">doommeer
      on Flickr</a>, used with permission – CC:by-nc-sa) but I do use
      the layout shown. I've been typing Dvorak every day since 1994
      or so.</p><p>Below is the Xmodmap configuration that achieves this
      modifier-key layout on the MacBook Pro. X key configuration is a
      little wonky, to say the least. The key codes I explicitly unmap
      here (6c, cc, etc.) seemed to interfere with the ones I wanted;
      there can be only so many syms for each modifier. This still
      isn't perfect; the right control key auto-repeats unless I xset
      it not to, and I have to semi-manually switch to a different
      configuration (via a .Xmodmap symlink) when I dock the laptop
      with my Kinesis QD contoured keyboard.</p><p>More later on other applications and tricks, but for now I'm
      pretty happy. The machine dual-boots just fine with rEFIt, and
      although I have all my stuff (except for music – too big for a
      partitioned drive) synced on both sides, when that chooser
      screen pops up, I always go with the penguin.
    </p><pygment lang="text">
clear shift
clear lock
clear control
clear mod1
clear mod2
clear mod3
clear mod4
clear mod5

keycode 0x6c =
keycode 0xcc =
keycode 0x69 =
keycode 0xce =

keycode 0x42 = Control_L
keycode 0x68 = Control_R

keycode 0x85 = Alt_L
keycode 0x86 = Alt_R

keycode 0x25 = Super_L
keycode 0x40 = Multi_key

add shift   = Shift_L Shift_R
add lock    = Caps_Lock
add control = Control_L Control_R
add mod1    = Alt_L Alt_R
add mod3    = Super_L
    </pygment>]]></content:encoded>
    </item><item>
      <title>Quadratic</title>
      <link>http://contrapunctus.net/blog/2010/quadratic</link>
      <guid>http://contrapunctus.net/blog/2010/quadratic</guid>
      <pubDate>Sun, 25 Apr 2010 00:04:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/3582624288/" title="Manse - 3 by chris league, on Flickr"><img src="http://farm4.static.flickr.com/3299/3582624288_59786ffa2b_m.jpg" width="240" height="240" alt="Manse - 3" /></a>
    </div><div class="frame_240_3 right unlink">
      <a href="http://www.flickr.com/photos/chrisleague/4508999606/" title="Art on bench by chris league, on Flickr"><img src="http://farm3.static.flickr.com/2047/4508999606_419091a5b7_m.jpg" width="240" height="240" alt="Art on bench" /></a>
    </div><p>So we’ve started more seriously looking into the housing market in Queens, New York, the most diverse county in the nation. So far, it’s mainly about orienting ourselves to the styles, conditions, and neighborhoods here, as we struggle with the concept of becoming slaves to that mortgage payment.</p><p>One thing I’ve noticed wandering around is that you can pass along the perimeter of a neighborhood thousands of times without ever noticing the treasures (and, to be fair, the dumps) within. Partly this is just because of geometry. The number of lots, blocks, and houses is proportional to the <b>square</b> of the length of the edge. To visit every meter of curb makes for a considerable journey!</p><p>To honor the quadratic, I illustrated this post with two square-cropped photos – though neither from New York!</p>]]></content:encoded>
    </item><item>
      <title>Section 3.3.1</title>
      <link>http://contrapunctus.net/blog/2010/section-3-3-1</link>
      <guid>http://contrapunctus.net/blog/2010/section-3-3-1</guid>
      <pubDate>Mon, 12 Apr 2010 00:04:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<p>Apple may
    have <a href="http://www.urbandictionary.com/define.php?term=jump%20the%20shark">jumped
    the shark</a> with the revision
    to section
    3.3.1 of the license agreement for the iPhone 4.0 software
    development kit. It reads:
    </p><blockquote>
      Applications must be originally written in Objective-C, C, C++, or
      JavaScript as executed by the iPhone OS WebKit engine, and only
      code written in C, C++, and Objective-C may compile and directly
      link against the Documented APIs.
    </blockquote><p>Not good news for programming language enthusiasts.  Presumably
      the purpose of this measure is
      to <a href="http://apple.slashdot.org/story/10/04/10/2142245/Adobe-Evangelist-Lashes-Out-Over-Apples-Original-Language-Policy">combat
      Adobe</a>. I have no love for Adobe either these days, but as a
      software developer I don't want to be a pawn in some corporate
      feud. Why should Apple care what languages and tools we use?
      Publish the API spec and we'll follow it.
    </p><p>Annoying developers is no way to promote your platform. There's
      a certain class of developers that will build for whatever
      platforms are dominant – in order to reach the most
      users. There's another class that will primarily target
      platforms they themselves use and love. Which class produces the
      most compelling, innovative, game-changing applications? We
      leave that as an exercise for the reader.</p>]]></content:encoded>
    </item><item>
      <title>The art of undo</title>
      <link>http://contrapunctus.net/blog/2010/art-of-undo</link>
      <guid>http://contrapunctus.net/blog/2010/art-of-undo</guid>
      <pubDate>Thu, 08 Apr 2010 00:04:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<p>So is emacs the only software in the world that
      gets <em>undo</em> right? In which undo actions themselves can
      be undone? Or have my expectations been so completely molded by
      emacs that its behavior is, by definition, <strong>the right
      thing?</strong>
    </p><p>Here's an experiment you can try at home, in your favorite
      editor, browser text box, etc.</p><ol>
      <li>Type “one”</li>
      <li>Do some backward cursor motion – this forces a separate
        action in the undo list</li>
      <li>Type “two”</li>
      <li>More cursor motion</li>
      <li>Hit undo, to remove “two”</li>
      <li>Type “three”</li>
      <li>Fiddle in vain for a combination of undo/redo that will
      bring back “two”</li>
      <li>Curse <em>redo</em> as the most useless concept in user
        interface design – <strong>evar!!!</strong></li>
      <li>Start searching for ways to do every last bit of text editing
        in emacs.</li>
    </ol>]]></content:encoded>
    </item><item>
      <title>Re-re-relaunch</title>
      <link>http://contrapunctus.net/blog/2010/re-re-relaunch</link>
      <guid>http://contrapunctus.net/blog/2010/re-re-relaunch</guid>
      <pubDate>Wed, 07 Apr 2010 00:04:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<p>Here we go again… another relaunch and redesign of my web
    site. I'm ditching wordpress and MySQL in favor of git and a
    static framework of my own creation, which I'm calling ‘gauz’
    (pronounced like ‘gauze’ or ‘gauss’ – your choice). The idea is
    very much
    like <a href="http://wiki.github.com/mojombo/jekyll/">Jekyll</a>,
    but it's written in Python and
    uses <a href="http://genshi.edgewall.org/">Genshi</a> XML
    templates. I plan to release the code to github shortly.
    </p><p>The design of the site is my own hand-coded CSS creation, but
    based on the very helpful <a href="http://960.gs/">960 grid
    system</a>. I'm very curious to hear feedback. I'm pretty
    confident in my coding ability, but less so with design.
    </p><p>It seems like I go through this relaunch process every
      <a href="/blog/2006/new-site-launch">couple</a> of
      <a href="/blog/2008/reboot">years</a>. Each time the goal is to
      make it easier to maintain. But then within two years I declare
      it unmaintainable and try something different.  Either I'm not
      good at making something that <em>is</em> actually maintainable,
      or else I change my mind every couple of years about what that
      concept means.  ;)
    </p>]]></content:encoded>
    </item><item>
      <title>Algorithmic intelligence</title>
      <link>http://contrapunctus.net/blog/2009/algorithmic-intelligence</link>
      <guid>http://contrapunctus.net/blog/2009/algorithmic-intelligence</guid>
      <pubDate>Fri, 24 Jul 2009 00:07:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<div class="frame_240_3 right unlink">
<a href="http://www.flickr.com/photos/chrisleague/3582651188/" title="Inlay by chris league, on Flickr"><img src="http://farm3.static.flickr.com/2443/3582651188_dc5f0edb27_m.jpg" width="240" height="184" alt="Inlay" /></a>
</div><p>When I wrote last October <a href="/blog/2008/in-defense-of-strong-ai">in defense of strong AI</a>, I promised to take on the ‘uncharitably narrow’ notion of <em>algorithmic</em> used by Ian Tattersall to argue that machines will never achieve consciousness.</p><p>In <em>The Monkey in the Mirror</em> (2002), he writes “Computers by their nature are algorithmic, rapidly applying a fixed set of rules to the solution of well-defined questions” [page 71]. He refers here to IBM's Deep Blue playing chess, the canonical example of a machine accomplishment that, while impressive, is surely not conscious. From this example, he extrapolates:
<blockquote>Human consciousness is very clearly non-algorithmic. Even if we have to conclude [...] that subjective awareness in ourselves and our relatives is due ultimately to a mass of electrochemical events in the brain [...] it is equally clearly not the product of a mechanism that dutifully clicks through a listing of tasks and ‘if-then’ choices.</blockquote>
I bristle a bit at this formulation, and I imagine it must annoy most software developers. It's too narrow, in at least two dimensions. First, it seems to exclude non-determinism and parallelism: a genetic algorithm is still an algorithm. But more crucially – even if we assume deterministic sequential code – Tattersall appears to underestimate the <em>complexity</em> of everyday computer programs.</p><p>It doesn't take very much code to produce a system whose precise behavior is practically unpredictable, even by the person who wrote it. We may use strategies such as functional decomposition to design a system to target specific requirements, but as the system evolves complex behaviors emerge. If they didn't then debugging would be easy.</p><p>Yes, ultimately any deterministic program is expressed as a list of simple instructions and branches – millions of them, coupled with sophisticated data structures in an infinite number of configurations! Tattersall makes it sound like little more than a flowchart you could hang on the wall.</p><p>I don't claim that our current programs are conscious, or intelligent in any strong sense. But don't rely on a naïve notion of algorithmic to argue that machines <em>cannot</em> be conscious.</p>]]></content:encoded>
    </item><item>
      <title>Growl upon job completion in zsh</title>
      <link>http://contrapunctus.net/blog/2009/growl-upon-completion</link>
      <guid>http://contrapunctus.net/blog/2009/growl-upon-completion</guid>
      <pubDate>Fri, 10 Jul 2009 00:07:00 EDT</pubDate>
      <description>[CDATA[ ]]</description>
      <content:encoded><![CDATA[<p><a href="http://growl.info/">Growl</a> is a pretty classy system for notifications among Mac applications; there are similar notifications in other desktop environments. Whenever I run a shell command that is going to take a while to complete, it's natural to switch to something else in the meantime. So I would like a notification as soon as the original command completes.</p><p>Growl comes with a script, ‘<code>growlnotify</code>’, that can trigger notifications from the command-line. You could, for example, type something like ‘<code>make; growlnotify done</code>’ – the problem is that I never remember that I would like the notification until <em>after</em> the command is already running.</p><p>So here is an alternative: this bit of <a href="http://zsh.sourceforge.net/">zsh</a> code will notify me upon completion of any job that takes longer than 5 seconds.</p><pygment lang="sh">
## zsh/growl integration: any command that takes longer than 5 seconds
## will trigger a growl notification when it completes.

if growlnotify -h &>/dev/null; then
    preexec() {
        zsh_growl_cmd=$$1
        zsh_growl_time=`date +%s`
    }

    precmd() {
        if (( $$? == 0 )); then
            zsh_growl_status=done
        else
            zsh_growl_status=fail
        fi
        if [[ "$${zsh_growl_cmd}" != "" ]]; then
            if (( `date +%s` - $${zsh_growl_time} > 5 )); then
                growlnotify -m $${zsh_growl_cmd} $${zsh_growl_status}
            fi
        fi
        zsh_growl_cmd=
    }
fi
</pygment><p>Note that this <strong>is</strong> specific to zsh, which is not the default shell on OS X, although it is supplied with the system. Possibly it can be made to work with other shells; I really don't care. :)</p><p>Ideas for improvements: filter out commands that are obviously going to be long, interactive jobs, such as ssh sessions, vi, command-line emacs, etc. Also, is there some way not to rely on ‘<code>/bin/date</code>’?</p>]]></content:encoded>
    </item>
  </channel>
</rss>
