<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
	<title>Blog.from.bz</title>
	<link>http://from.bz/</link>
	
	<language>en-us</language>
	<copyright>Copyright 2010, from.bz</copyright>
	<pubDate>Tue, 07 Sep 2010 10:30:04 -0400</pubDate>
	<lastBuildDate>Tue, 07 Sep 2010 10:30:04 -0400</lastBuildDate>
	<category>any</category>
	<generator />
	<description>Blog posts from bill zeller</description>
	<docs>http://www.rssboard.org/rss-specification</docs>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/frombz" /><feedburner:info uri="frombz" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>jLambda: A jQuery plugin for succinct anonymous functions</title>
		<description>&lt;p&gt;&lt;a href="http://github.com/billzeller/jLambda/"&gt;jLambda on Github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Download&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://cloud.github.com/downloads/billzeller/jLambda/jquery.lambda.0.6.min.js"&gt;Production&lt;/a&gt; (YUI compressed, 448 bytes)&lt;br /&gt;
&lt;a href="http://github.com/billzeller/jLambda/raw/master/jquery.lambda.js"&gt;Development&lt;/a&gt; (1.3kb)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Demo&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://projects.from.bz/jLambda/demo.php"&gt;View a demo here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Motivation&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; has an elegant chaining syntax that allows much of its API to be expressed in a clear, succinct way.  For example, the following code from the jQuery homepage code finds all &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements with the class &lt;code&gt;neat&lt;/code&gt;. The class "ohmy" is added to each matching element and then &lt;code&gt;show()&lt;/code&gt; is called, which causes each element to be displayed. &lt;/p&gt;
&lt;pre class="brush: js"&gt;
$("p.neat").addClass("ohmy").show("slow");
&lt;/pre&gt;
&lt;p&gt;Many jQuery functions accept a function as a argument which is called after some action is performed. For example, the following code finds all elements with the class "foo" and tells jQuery to call the function 'clkCallback' each time such an element is clicked. &lt;/p&gt;
&lt;pre class="brush: js"&gt;

function clkCallback() {
    $(this).hide();
}

$('.foo').click(clkCallback);
&lt;/pre&gt;
&lt;p&gt;These functions are often written anonymously:&lt;/p&gt;
&lt;pre class="brush: js"&gt;
$('.foo').click(
            function() {
                $(this).hide();
            });
&lt;/pre&gt;
&lt;p&gt;Often one wants to register a callback function that calls another jQuery function (like in the above, where the goal is to call &lt;code&gt;hide()&lt;/code&gt; on the clicked element). Javascript's verbose anonymous function syntax makes this difficult to do succinctly. Can we do better?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Plugin: jquery.lambda.js&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I've written a jQuery plugin which adds the succinctness of jQuery chaining to callback functions. Generally, the plugin adds the global function &lt;code&gt;$l&lt;/code&gt; (lowercase L, for "lambda"), which "wraps up" a jQuery expression into a function that can be executed later. For example, instead of writing:&lt;/p&gt;
&lt;pre class="brush: js"&gt;
function() {
    $(this).hide().addClass('foo').css('color', '#fff')..;
}
&lt;/pre&gt;
&lt;p&gt;The plugin allows you to write:&lt;/p&gt;
&lt;pre class="brush: js"&gt;
$l.hide().addClass('foo').css('color', '#fff')..;
&lt;/pre&gt;
&lt;p&gt;This allows succinct expression of callback functions. &lt;/p&gt;
&lt;pre class="brush: js"&gt;
// Without plugin:
$('.foo').click(
            function() {
                $(this).hide();
            });

// With plugin:
$('.foo').click($l.hide());
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By default, any expressions following &lt;code&gt;$l&lt;/code&gt; are called with &lt;code&gt;$(this)&lt;/code&gt; as the argument. The plugin also makes the jQuery &lt;code&gt;$()&lt;/code&gt; function available. For example:&lt;/p&gt;
&lt;pre class="brush: js"&gt;

// Without plugin:
$('.foo').click(
            function() {
                $(this).hide();
                $('p').show();
                $('a').width(20);
            });

// With plugin:
$('.foo').click($l.hide().$('p').show().$('a').width(20));
&lt;/pre&gt;
&lt;p&gt;More generally, calling:&lt;/p&gt;
&lt;pre class="brush: js"&gt;
$l.a().b().$('x').c().$('y').d().$('z').e().f().g();
&lt;/pre&gt;
&lt;p&gt;is functionally equivalent to:&lt;/p&gt;
&lt;pre class="brush: js"&gt;
function() {
    $(this).a().b();
    $('x').c();
    $('y').d();
    $('z').e().f().g();
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Supported Methods&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All properties of jQuery.fn are available, as are some additional ajax methods (&lt;a href="http://docs.jquery.com/Ajax/jQuery.ajax"&gt;ajax&lt;/a&gt;, &lt;a href="http://docs.jquery.com/Ajax/jQuery.get"&gt;get&lt;/a&gt;, &lt;a href="http://docs.jquery.com/Ajax/jQuery.getJSON"&gt;getJSON&lt;/a&gt;, &lt;a href="http://docs.jquery.com/Ajax/jQuery.getScript"&gt;getScript&lt;/a&gt;, and &lt;a href="http://docs.jquery.com/Ajax/jQuery.post"&gt;post&lt;/a&gt;). These ajax methods can be called with, i.e., &lt;code&gt;$l.$.ajax()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The plugin also supports a special function called &lt;code&gt;ret()&lt;/code&gt;, which controls the value returned from the generated function. &lt;/p&gt;
&lt;pre class="brush: js"&gt;
// returns 5 when called.
$l.addClass('x').ret(3).css('color', '#f00').ret(5).show();
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From a size/download perspective, the plugin is only 448 bytes (when compressed with the &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI Compressor&lt;/a&gt;). &lt;/p&gt;
&lt;p&gt;From a performance perspective, the cost of using jLambda will be proportional to the number of chained calls made to &lt;code&gt;$l&lt;/code&gt; (but &lt;em&gt;not&lt;/em&gt; the size of the document or the DOM tree). Since Javascript doesn't support dynamic getters (see PHP's &lt;a href="http://php.net/manual/en/language.oop5.overloading.php"&gt;__get&lt;/a&gt; or Python's &lt;a href="http://docs.python.org/reference/datamodel.html#object.__getattr__"&gt;__getattr__&lt;/a&gt;), the values from the &lt;code&gt;jQuery.fn&lt;/code&gt; need to copied after each called to a "placeholder" function, to allow that function to at as a dictionary to be called. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;jLambda has been tested with Firefox 3.0.14, Firefox 3.5.3, Google Chrome 3.0.195.27, Safari 4.0.3 (5531.9), IE 8.0.7600.16385&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/HrpgkeecfO0" height="1" width="1"/&gt;</description>
		<pubDate>Tue, 27 Oct 2009 00:00:00 -0400</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/HrpgkeecfO0/jlambda-a-jquery-plugin-for-succinct-anonymous-functions</link>
		<guid isPermaLink="false">http://blog.from.bz/2009/10/27/jlambda-a-jquery-plugin-for-succinct-anonymous-functions</guid>
	<feedburner:origLink>http://blog.from.bz/2009/10/27/jlambda-a-jquery-plugin-for-succinct-anonymous-functions</feedburner:origLink></item>
        <item>
		<title>Announcing XMLegant for Python</title>
		<description>&lt;p&gt;I've written a Python version of XMLegant, which &lt;a href="http://www.from.bz/blog/2009/03/28/announcing-xmlegant-for-php/"&gt;I released earlier this morning for PHP&lt;/a&gt;. The Python version was designed to be as compatible as possible with the PHP version, without unnecessarily abusing the language. &lt;/p&gt;
&lt;p&gt;XMLegant (&lt;a href="http://github.com/billzeller/xmlegant-for-python/tree/master"&gt;github&lt;/a&gt;, &lt;a href="http://github.com/billzeller/xmlegant-for-python/zipball/master"&gt;download latest as zip&lt;/a&gt;) is a tool designed to allow easy generation of XML.&lt;/p&gt;
&lt;p&gt;To see how XMLegant works, let's take a simple example. Suppose we want to generate the following document:
&lt;pre class="brush: xml"&gt;
&amp;lt;books&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 1&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 1&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 1&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 2&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 2&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 2&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 3&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 3&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 3&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
&amp;lt;/books&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We can use the following code:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
x = XMLegant()

for i in xrange(5):
    x.books.book().title("Title %d" % i) \
                     .author("Author %d" % i) \
                     .isbn("isbn %d" % i)
&lt;/pre&gt;
&lt;p&gt;And to generate this document:
&lt;pre class="brush: xml"&gt;
&amp;lt;a&amp;gt;
    &amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;
    &amp;lt;b&amp;gt;d&amp;lt;/b&amp;gt;
    &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;
    &amp;lt;b&amp;gt;g&amp;lt;/b&amp;gt;
    &amp;lt;h&amp;gt;
        &amp;lt;i j="k"/&amp;gt;
        &amp;lt;l&amp;gt;
            &amp;lt;m/&amp;gt;
        &amp;lt;/l&amp;gt;
        &amp;lt;n&amp;gt;o&amp;lt;/n&amp;gt;
    &amp;lt;/h&amp;gt;
&amp;lt;a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We can use either:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
x = XMLegant()

x.a.b('c')
x.a.b('d')
x.a.e('f')
x.a.b('g')
x.a.h.i['j'] = 'k'
x.a.h.l.m
x.a.h.n = 'o'
&lt;/pre&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
x = XMLegant()

x.a() \
    .b('c') \
    .b('d') \
    .e('f') \
    .b('g') \
    .h() \
      .i('j', 'k') \
      .l() \
        .m('') \
        .getParent() \
      .n('o')
&lt;/pre&gt;
&lt;p&gt;A walkthrough of a short example is available in the &lt;a href="http://www.from.bz/2009/03/28/announcing-xmlegant-for-php/"&gt;XMLegant for PHP post&lt;/a&gt;. Many more examples are available in &lt;a href="http://github.com/billzeller/xmlegant-for-python/blob/df29e0cadae8633caca75efe85efc64343f76564/demo.py"&gt;demo.py&lt;/a&gt;. Also, &lt;a href="http://github.com/billzeller/xmlegant-for-python/blob/df29e0cadae8633caca75efe85efc64343f76564/XMLegant_Tests.py"&gt;XMLegant_Tests.py&lt;/a&gt; consists of a number of unit tests that may be useful as a guide.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/yVlifRQfit0" height="1" width="1"/&gt;</description>
		<pubDate>Sat, 28 Mar 2009 12:10:48 -0400</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/yVlifRQfit0/announcing-xmlegant-for-python</link>
		<guid isPermaLink="false">http://blog.from.bz/2009/03/28/announcing-xmlegant-for-python</guid>
	<feedburner:origLink>http://blog.from.bz/2009/03/28/announcing-xmlegant-for-python</feedburner:origLink></item>
        <item>
		<title>Announcing XMLegant for PHP</title>
		<description>&lt;p&gt;&lt;strong&gt;Update: I've also written &lt;a href="http://www.from.bz/2009/03/28/announcing-xmlegant-for-python/"&gt;a Python version of XMLegant&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While &lt;a href="http://php.net/simplexml"&gt;SimpleXML&lt;/a&gt; has made reading XML relatively painless, no analogous tool exists for generating XML from scratch. To fill this need, I've created XMLegant (&lt;a href="http://github.com/billzeller/xmlegant-for-php/tree/master"&gt;github&lt;/a&gt;, &lt;a href="http://github.com/billzeller/xmlegant-for-php/zipball/master"&gt;download latest as zip&lt;/a&gt;). &lt;/p&gt;
&lt;p&gt;To see how XMLegant works, let's take a simple example. Suppose we want to generate the following document:
&lt;pre class="brush: xml"&gt;
&amp;lt;books&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 1&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 1&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 1&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 2&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 2&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 2&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
    &amp;lt;book&amp;gt;
        &amp;lt;title&amp;gt;Title 3&amp;lt;/title&amp;gt;
        &amp;lt;author&amp;gt;Author 3&amp;lt;/author&amp;gt;
        &amp;lt;isbn&amp;gt;isbn 3&amp;lt;/isbn&amp;gt;
    &amp;lt;/book&amp;gt;
&amp;lt;/books&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We can use the following code:&lt;/p&gt;
&lt;pre class="brush: php"&gt;
$x = new XMLegant();

for($i=0;$i&amp;lt;5;$i++)
    $x-&amp;gt;books-&amp;gt;book()-&amp;gt;title("Title $i")
                     -&amp;gt;author("Author $i")
                     -&amp;gt;isbn("isbn $i");

echo $x-&amp;gt;toXML();
&lt;/pre&gt;
&lt;p&gt;And to generate this document:
&lt;pre class="brush: xml"&gt;
&amp;lt;a&amp;gt;
    &amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;
    &amp;lt;b&amp;gt;d&amp;lt;/b&amp;gt;
    &amp;lt;e&amp;gt;f&amp;lt;/e&amp;gt;
    &amp;lt;b&amp;gt;g&amp;lt;/b&amp;gt;
    &amp;lt;h&amp;gt;
        &amp;lt;i j="k"/&amp;gt;
        &amp;lt;l&amp;gt;
            &amp;lt;m/&amp;gt;
        &amp;lt;/l&amp;gt;
        &amp;lt;n&amp;gt;o&amp;lt;/n&amp;gt;
    &amp;lt;/h&amp;gt;
&amp;lt;a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We can use either:&lt;/p&gt;
&lt;pre class="brush: php"&gt;
$x = new XMLegant();

$x-&amp;gt;a-&amp;gt;b = 'c';
$x-&amp;gt;a-&amp;gt;b[] = 'd';
$x-&amp;gt;a-&amp;gt;e = 'f';
$x-&amp;gt;a-&amp;gt;b[] = 'g';
$x-&amp;gt;a-&amp;gt;h-&amp;gt;i['j'] = 'k';
$x-&amp;gt;a-&amp;gt;h-&amp;gt;l-&amp;gt;m;
$x-&amp;gt;a-&amp;gt;h-&amp;gt;n = 'o';
&lt;/pre&gt;
&lt;p&gt;or:&lt;/p&gt;
&lt;pre class="brush: php"&gt;
$x = new XMLegant();

$x-&amp;gt;a()
    -&amp;gt;b('c')
    -&amp;gt;b('d')
    -&amp;gt;e('f')
    -&amp;gt;b('g')
    -&amp;gt;h()
      -&amp;gt;i('j', 'k')
      -&amp;gt;l()
        -&amp;gt;m('')
        -&amp;gt;getParent()
      -&amp;gt;n('o');
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;How does this work?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;XMLegant uses PHP's &lt;a href="http://www.php.net/manual/en/language.oop5.overloading.php"&gt;overloading&lt;/a&gt; and the SPL ArrayAccess interface. This allows interception of calls to unnamed functions or member variables as well as subscript access to the object. Using this, we can construct an XML access through manipulation of these anonymous calls.&lt;/p&gt;
&lt;p&gt;Take this code:
&lt;pre class="brush: php"&gt;
$x = new XMLegant();
$x-&amp;gt;a-&amp;gt;b-&amp;gt;c-&amp;gt;d = 'e';
$x-&amp;gt;a-&amp;gt;b['f'] = 'g';
$x-&amp;gt;toXML();
&lt;/pre&gt;
&lt;p&gt;Which produces this:
&lt;pre class="brush: xml"&gt;
&amp;lt;a&amp;gt;
    &amp;lt;b f="g"&amp;gt;
        &amp;lt;c&amp;gt;
            &amp;lt;d&amp;gt;e&amp;lt;/d&amp;gt;
        &amp;lt;/c&amp;gt;
    &amp;lt;/b&amp;gt;
&amp;lt;/a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This code first starts with the root object &lt;code&gt;$x&lt;/code&gt;.
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;$x-&gt;a&lt;/code&gt; is called, which looks for the most recently created &lt;code&gt;a&lt;/code&gt; child. Since none exists, an &lt;code&gt;a&lt;/code&gt; element is created and added as a child of &lt;code&gt;$x&lt;/code&gt;.&lt;/p&gt;
&lt;li&gt;&lt;code&gt;-&gt;b&lt;/code&gt; is called, which looks for the most recently created &lt;code&gt;b&lt;/code&gt; child of &lt;code&gt;a&lt;/code&gt;. Since none exists, a &lt;code&gt;b&lt;/code&gt; element is created and added as a child of &lt;code&gt;a&lt;/code&gt;.
&lt;li&gt;&lt;code&gt;-&gt;c&lt;/code&gt; is called, which looks for the most recently created &lt;code&gt;c&lt;/code&gt; child of &lt;code&gt;b&lt;/code&gt;. Since none exists, a &lt;code&gt;c&lt;/code&gt; element is created and added as a child of &lt;code&gt;b&lt;/code&gt;.
&lt;li&gt;&lt;code&gt;-&gt;d&lt;/code&gt; is called, which looks for the most recently created &lt;code&gt;d&lt;/code&gt; child of &lt;code&gt;c&lt;/code&gt;. Since none exists, a &lt;code&gt;d&lt;/code&gt; element is created and added as a child of &lt;code&gt;c&lt;/code&gt;.
&lt;li&gt;&lt;code&gt;d = 'e'&lt;/code&gt; is called, which assigns &lt;code&gt;'e'&lt;/code&gt; as a text node of &lt;code&gt;d&lt;/code&gt;.
&lt;/ol&gt;
&lt;p&gt;The second line finds the already created &lt;code&gt;a&lt;/code&gt; element, finds the already created &lt;code&gt;b&lt;/code&gt; child of &lt;code&gt;a&lt;/code&gt;, and then sets the attribute &lt;code&gt;f&lt;/code&gt; of &lt;code&gt;b&lt;/code&gt; to &lt;code&gt;'g'&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Many more examples are available in &lt;a href="http://github.com/billzeller/xmlegant-for-php/blob/0f713029f2061c4fe66c028d56ae618bb4b065dc/demo.php"&gt;demo.php&lt;/a&gt;. Also, &lt;a href="http://github.com/billzeller/xmlegant-for-php/blob/0f713029f2061c4fe66c028d56ae618bb4b065dc/XMLegant_Tests.php"&gt;XMLegant_Tests.php&lt;/a&gt; consists of a number of unit tests that may be useful as a guide.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/JjipCs2oRe0" height="1" width="1"/&gt;</description>
		<pubDate>Sat, 28 Mar 2009 00:18:00 -0400</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/JjipCs2oRe0/announcing-xmlegant-for-php</link>
		<guid isPermaLink="false">http://blog.from.bz/2009/03/28/announcing-xmlegant-for-php</guid>
	<feedburner:origLink>http://blog.from.bz/2009/03/28/announcing-xmlegant-for-php</feedburner:origLink></item>
        <item>
		<title>Sudo make me a sandwich stub code</title>
		<description>&lt;p&gt;&lt;a href="http://xkcd.com/149/"&gt;&lt;img src="http://imgs.xkcd.com/comics/sandwich.png"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On linux-based machines, save this as the file &lt;strong&gt;Makefile&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="brush: bash"&gt;
.SILENT: 

me:

a:

sandwich:
ifeq ($(shell id -u), 0)
	echo "Okay"
	# Ordering code goes here
else
	echo "What? Make it yourself."
endif
&lt;/pre&gt;
&lt;p&gt;From the directory in which that file exists, you can now type&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make me a sandwich&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(which does not work) and&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo make me a sandwich&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(which does). Actually making the sandwich is an exercise left to the reader (although &lt;a href="http://www.beigerecords.com/cory/Things_I_Made/PizzaParty"&gt;Dominos&lt;/a&gt; now makes sandwiches).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/ElAMrD7sg4g" height="1" width="1"/&gt;</description>
		<pubDate>Sun, 01 Mar 2009 12:14:30 -0500</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/ElAMrD7sg4g/sudo-make-me-a-sandwich-stub-code</link>
		<guid isPermaLink="false">http://blog.from.bz/2009/03/01/sudo-make-me-a-sandwich-stub-code</guid>
	<feedburner:origLink>http://blog.from.bz/2009/03/01/sudo-make-me-a-sandwich-stub-code</feedburner:origLink></item>
        <item>
		<title>Using Python and CSPs to Solve Sudoku</title>
		<description>&lt;p&gt;&lt;em&gt;This post introduces Constraint Satisfaction Problems (CSPs) and shows how to use a CSP solver to easily solve instances of Sudoku problems. It assumes familiarity with Sudoku and Python.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Constraint_satisfaction_problem"&gt;Constraint Satisfaction Problems&lt;/a&gt; (or CSPs) are problems that involve a set of variables that can each take on some number of values. The possible values of each variable may depend on other variables in the set. A well-written overview of CSPs &lt;a href="http://4c.ucc.ie/web/outreach/tutorial.html"&gt;is available here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A CSP can be represented as:
&lt;ol&gt;&lt;li&gt;A set of variables&lt;/li&gt;
&lt;li&gt;For each variable, a set of possible values that the variable can taken on (also called the &lt;em&gt;domain&lt;/em&gt;) &lt;/li&gt;
&lt;li&gt;A set of constraints. Each constraints limits the values some subset of the variables can taken on.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;A CSP &lt;em&gt;solver&lt;/em&gt; searches over the variables' possible values and produces a mapping from variables to values that satisfy the constraints of the problem. &lt;/p&gt;
&lt;p&gt;Certain programming languages, like &lt;a href="http://en.wikipedia.org/wiki/Prolog"&gt;Prolog&lt;/a&gt;, naturally lend themselves to solving CSPs (&lt;a href="http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_11.html"&gt;here's an example&lt;/a&gt; of a Prolog program that solves the N-Queens problem). We could use Prolog to solve CSPs, but that would require learning Prolog (which can be difficult for those not familiar with declarative langauges) and would possibly make other integration difficult (for example, a Sudoku solver may be part of a larger web site, not written in Prolog).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solving Sudoku (and other CSPs) with Python&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To solve Sudoku we're going to use the &lt;a href="http://labix.org/python-constraint"&gt;python-constraint&lt;/a&gt; library. (Note for Debian/Ubuntu users: This is not the library installed when typing &lt;code&gt;apt-get install python-constraint&lt;/code&gt;. You will need to download and install this package manually.)&lt;/p&gt;
&lt;p&gt;We will be creating a function called &lt;code&gt;SolveSudoku&lt;/code&gt;. It will be called as follows:
&lt;pre class="brush: python"&gt;
m = [
[0,2,0,0,3,0,9,0,7],
[0,1,0,0,0,0,0,0,0],
[4,0,7,0,0,0,2,0,8],
[0,0,5,2,0,0,0,9,0],
[0,0,0,1,8,0,7,0,0],
[0,4,0,0,0,3,0,0,0],
[0,0,0,0,6,0,0,7,1],
[0,7,0,0,0,0,0,0,0],
[9,0,3,0,2,0,6,0,5],
]

print SolveSudoku(m)
&lt;/pre&gt;
&lt;p&gt;...which represents the puzzle:&lt;/p&gt;
&lt;p&gt;&lt;img src='http://www.from.bz/wp-content/uploads/2009/02/sudoku1.png' alt='' class='aligncenter' /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let's define the function:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
def SolveSudoku(m, N = 9):
    p = Problem()
    ...
    # TODO: setup variables and constraints
    ...
    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Problem()&lt;/code&gt; defines a new constraint problem. &lt;code&gt;p.getSolution()&lt;/code&gt; searches for a solution. Since we haven't added any variables yet, it returns None.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now we need to define the CSP variables. I've decided to name the variables 0 through 81, where the top-left box is 0 and the bottom right box is 1. The first row consists of the variables [0,1,2,3,4,5,6,7,8], etc. To help with manipulation, we "flatten" the Sudoku board &lt;code&gt;m&lt;/code&gt;. &lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)
   ...
    # TODO: setup variables and constraints
    ...
    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;Given the above example problem, mList becomes:
&lt;pre class="brush: python"&gt;
[0, 2, 0, 0, 3, 0, 9, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 7, 0, 0, 0, 2, 0, 8, 0, 0, 5, 2, 0, 0, 0, 9, 0, 0, 0, 0, 1, 8, 0, 7, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 7, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 9, 0, 3, 0, 2, 0, 6, 0, 5]
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To setup the variables, we loop over each item in &lt;code&gt;mList&lt;/code&gt;. If the value is 0 (our placeholder for an unknown value), we call &lt;code&gt;p.addVariable(i, range(1, N+1))&lt;/code&gt;, which says "The variable i can be any value from 1 through 10". If the value isn't 0, we add a variable whose only value can be the value specified. &lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)

    # add variables
    for i in xrange(N*N):
        if mList[i] == 0:
            p.addVariable(i, range(1, N+1))
        else:
            p.addVariable(i, [mList[i]])

    # TODO: setup  constraints
    ...
    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To add the row constraints, we can loop over each row and for each row, generate a list of numbers representing the variables in that row and then add the constraint to that list of variables. To add a constraint, we call &lt;code&gt;p.addConstraint(constraint, variableList)&lt;/code&gt;, where &lt;code&gt;constraint&lt;/code&gt; is the constraint placed on the list of variables &lt;code&gt;variableList&lt;/code&gt;. Conveniently, python-constraint provides the constraint &lt;code&gt;AllDifferentConstraint&lt;/code&gt; for us, which simply says that every value in the list variables we provide must be different. &lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)

    # add variables
    for i in xrange(N*N):
        if mList[i] == 0:
            p.addVariable(i, range(1, N+1))
        else:
            p.addVariable(i, [mList[i]])

    # row constraints
    for r in xrange(N):
        l = list(xrange(r*N,(r+1)*N))
        p.addConstraint(AllDifferentConstraint(),l)

    # TODO: setup  constraints
    ...
    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;At each iteration of the loop, l is:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[9, 10, 11, 12, 13, 14, 15, 16, 17]
[18, 19, 20, 21, 22, 23, 24, 25, 26]
...
&lt;/pre&gt;
&lt;p&gt;Running this code will produce a solution that has our initial values and unique values for each row. All that's left is adding the column constraints.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Similarly, we add column constraints by generating a list of numbers representing each column:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)

    # add variables
    for i in xrange(N*N):
        if mList[i] == 0:
            p.addVariable(i, range(1, N+1))
        else:
            p.addVariable(i, [mList[i]])

    # row constraints
    for r in xrange(N):
        l = list(xrange(r*N,(r+1)*N))
        p.addConstraint(AllDifferentConstraint(),l)

    # column constraints
    for c in xrange(N):
        l = list(xrange(c,N*N, N))
        p.addConstraint(AllDifferentConstraint(), l)

    # TODO: setup  constraints
    ...
    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Adding constraints for the 3x3 grids is slightly more complicated, but still involves generating 9 lists representing the variables in each grid:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)

    # add variables
    for i in xrange(N*N):
        if mList[i] == 0:
            p.addVariable(i, range(1, N+1))
        else:
            p.addVariable(i, [mList[i]])

    # row constraints
    for r in xrange(N):
        l = list(xrange(r*N,(r+1)*N))
        p.addConstraint(AllDifferentConstraint(),l)

    # column constraints
    for c in xrange(N):
        l = list(xrange(c,N*N, N))
        p.addConstraint(AllDifferentConstraint(), l)

    # grid constraints
    for i in xrange(9):
        grid = []
        startingRow = (i%3)*3
        startingCol = i/3*3
        for r in xrange(3):
            for c in xrange(3):
                grid.append((startingRow+r)*N+startingCol+c)
        p.addConstraint(AllDifferentConstraint(),grid)

    solution = p.getSolution()
    ...
    # TODO: format and return solution
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And finally, we can format the solution nicely by putting each row on its own line:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *

def SolveSudoku(m, N = 9):
    p = Problem()

    # flatten list
    mList = []
    for r in m:
        for c in r:
            mList.append(c)

    # add variables
    for i in xrange(N*N):
        if mList[i] == 0:
            p.addVariable(i, range(1, N+1))
        else:
            p.addVariable(i, [mList[i]])

    # row constraints
    for r in xrange(N):
        l = list(xrange(r*N,(r+1)*N))
        p.addConstraint(AllDifferentConstraint(),l)

    # column constraints
    for c in xrange(N):
        l = list(xrange(c,N*N, N))
        p.addConstraint(AllDifferentConstraint(), l)

    # grid constraints
    for i in xrange(9):
        grid = []
        startingRow = (i%3)*3
        startingCol = i/3*3
        for r in xrange(3):
            for c in xrange(3):
                grid.append((startingRow+r)*N+startingCol+c)
        p.addConstraint(AllDifferentConstraint(),grid)

    solution = p.getSolution()

    if solution is not None:
        m = []
        i = 0
        for r in xrange(N):
            row = []
            for c in xrange(N):
                row.append(str(solution[i]))
                i+=1
            rowStr = ' '.join(row)
            m.append(rowStr)

        return '\n'.join(m)

    else:
        return None
&lt;/pre&gt;
&lt;p&gt;And we have a Sudoku solver! The example program outputs:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
6 2 8 5 3 4 9 1 7
5 1 9 8 7 2 4 3 6
4 3 7 9 1 6 2 5 8
8 6 5 2 4 7 1 9 3
3 9 2 1 8 5 7 6 4
7 4 1 6 9 3 5 8 2
2 5 4 3 6 9 8 7 1
1 7 6 4 5 8 3 2 9
9 8 3 7 2 1 6 4 5
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Making it Succinct&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We can make this program shorter by abusing both Python's syntax and readability:&lt;/p&gt;
&lt;pre class="brush: python"&gt;
from constraint import *
def SolveSudoku(m, N = 9):
    p = Problem()
    l = sum(m,[]) # flatten list
    [p.addVariable(i, [l[i]] if l[i] &amp;gt; 0 else range(1,N+1)) for i in xrange(N*N)] # load variables
    [p.addConstraint(AllDifferentConstraint(),list(xrange(r*N,(r+1)*N))) for r in xrange(N)] # row constraints
    [p.addConstraint(AllDifferentConstraint(),list(xrange(c,N*N, N))) for c in xrange(N)] # column constraints
    [p.addConstraint(AllDifferentConstraint(),filter(lambda x: (i%3)*3 &amp;lt;= x/N &amp;lt; (i%3+1)*3 and (i/3)*3 &amp;lt;= x%N &amp;lt; (i/3+1)*3, xrange(N*N))) for i in xrange(N)] # grid constraints
    s = p.getSolution()
    return '\n'.join([' '.join([str(s[j]) for j in list(xrange(i*N,i*N+N))]) for i in xrange(N)]) if s is not None else None
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While we could have solved Sudoku directly, transforming Sudoku into a CSP allowed us to use an existing CSP solver to do the difficult work for us. If you come across problems in your work that appear to be CSPs, give a CSP solver a chance before reinventing the wheel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coming Soon:&lt;/strong&gt; Sudoku's constraints can all be described using the built in &lt;code&gt;AllDifferentConstraint()&lt;/code&gt;. A future post will describe how to define your own constraint classes in order to solve the logic puzzle &lt;a href="http://en.wikipedia.org/wiki/KenKen"&gt;KenKen&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/65WwFU5RGMs" height="1" width="1"/&gt;</description>
		<pubDate>Sun, 15 Feb 2009 12:21:17 -0500</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/65WwFU5RGMs/using-python-and-csps-to-solve-sudoku</link>
		<guid isPermaLink="false">http://blog.from.bz/2009/02/15/using-python-and-csps-to-solve-sudoku</guid>
	<feedburner:origLink>http://blog.from.bz/2009/02/15/using-python-and-csps-to-solve-sudoku</feedburner:origLink></item>
        <item>
		<title>Run command when saving file on Linux</title>
		<description>&lt;p&gt;I'm working on a LaTeX project and like to continually monitor the PDF output. Normally this requires saving the .tex file, typing "make" in the terminal and refreshing the PDF viewer. The "dnotify" command allows you to specify an action to perform when a directory changes. I'm using this to run "make" whenever I save the my .tex file. &lt;/p&gt;
&lt;pre class="brush: bash"&gt;
dnotify /directory/to/monitor -e make -C /directory/in/which/to/run/make
&lt;/pre&gt;
&lt;p&gt;It appears that the directory to monitor can be the same as the directory that make modifies (I had assumed if make modified the directory monitored by dnotify, dnotify would be called again, which would call make, which would activate dnotify, etc).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/frombz/~4/b-PkrCMGlE8" height="1" width="1"/&gt;</description>
		<pubDate>Wed, 05 Sep 2007 14:25:50 -0400</pubDate>
		<link>http://feedproxy.google.com/~r/frombz/~3/b-PkrCMGlE8/run-command-when-saving-file</link>
		<guid isPermaLink="false">http://blog.from.bz/2007/09/05/run-command-when-saving-file</guid>
	<feedburner:origLink>http://blog.from.bz/2007/09/05/run-command-when-saving-file</feedburner:origLink></item>

</channel>
</rss>
