samhuri.net/wayback/@done/sjs ElSchemo Boolean logic and branching.html

806 lines
35 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>sjs: ElSchemo: Boolean logic and branching</title>
<link rel="openid.server" href="http://www.myopenid.com/server" />
<link rel="openid.delegate" href="http://sami-samhuri.myopenid.com/" />
<meta http-equiv="X-XRDS-Location" content="http://sami-samhuri.myopenid.com/xrds" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="http://feeds.feedburner.com/sjs" />
<script src="http://web.archive.org/web/20081006064142js_/http://sami.samhuri.net/javascripts/prototype.js" type="text/javascript"></script>
<link href="http://web.archive.org/web/20081006064142cs_/http://sami.samhuri.net/stylesheets/application.css" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- BEGIN WAYBACK TOOLBAR INSERT -->
<script type="text/javascript" src="http://staticweb.archive.org/js/disclaim-element.js" ></script>
<script type="text/javascript" src="http://staticweb.archive.org/js/graph-calc.js" ></script>
<script type="text/javascript" src="http://staticweb.archive.org/jflot/jquery.min.js" ></script>
<script type="text/javascript">
//<![CDATA[
var firstDate = 820454400000;
var lastDate = 1325375999999;
var wbPrefix = "http://web.archive.org/web/";
var wbCurrentUrl = "http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching";
var curYear = -1;
var curMonth = -1;
var yearCount = 16;
var firstYear = 1996;
var imgWidth=400;
var yearImgWidth = 25;
var monthImgWidth = 2;
var trackerVal = "none";
var displayDay = "6";
var displayMonth = "Oct";
var displayYear = "2008";
var prettyMonths = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function showTrackers(val) {
if(val == trackerVal) {
return;
}
if(val == "inline") {
document.getElementById("displayYearEl").style.color = "#ec008c";
document.getElementById("displayMonthEl").style.color = "#ec008c";
document.getElementById("displayDayEl").style.color = "#ec008c";
} else {
document.getElementById("displayYearEl").innerHTML = displayYear;
document.getElementById("displayYearEl").style.color = "#ff0";
document.getElementById("displayMonthEl").innerHTML = displayMonth;
document.getElementById("displayMonthEl").style.color = "#ff0";
document.getElementById("displayDayEl").innerHTML = displayDay;
document.getElementById("displayDayEl").style.color = "#ff0";
}
document.getElementById("wbMouseTrackYearImg").style.display = val;
document.getElementById("wbMouseTrackMonthImg").style.display = val;
trackerVal = val;
}
function getElementX2(obj) {
var thing = jQuery(obj);
if((thing == undefined)
|| (typeof thing == "undefined")
|| (typeof thing.offset == "undefined")) {
return getElementX(obj);
}
return Math.round(thing.offset().left);
}
function trackMouseMove(event,element) {
var eventX = getEventX(event);
var elementX = getElementX2(element);
var xOff = eventX - elementX;
if(xOff < 0) {
xOff = 0;
} else if(xOff > imgWidth) {
xOff = imgWidth;
}
var monthOff = xOff % yearImgWidth;
var year = Math.floor(xOff / yearImgWidth);
var yearStart = year * yearImgWidth;
var monthOfYear = Math.floor(monthOff / monthImgWidth);
if(monthOfYear > 11) {
monthOfYear = 11;
}
// 1 extra border pixel at the left edge of the year:
var month = (year * 12) + monthOfYear;
var day = 1;
if(monthOff % 2 == 1) {
day = 15;
}
var dateString =
zeroPad(year + firstYear) +
zeroPad(monthOfYear+1,2) +
zeroPad(day,2) + "000000";
var monthString = prettyMonths[monthOfYear];
document.getElementById("displayYearEl").innerHTML = year + 1996;
document.getElementById("displayMonthEl").innerHTML = monthString;
// looks too jarring when it changes..
//document.getElementById("displayDayEl").innerHTML = zeroPad(day,2);
var url = wbPrefix + dateString + '/' + wbCurrentUrl;
document.getElementById('wm-graph-anchor').href = url;
//document.getElementById("wmtbURL").value="evX("+eventX+") elX("+elementX+") xO("+xOff+") y("+year+") m("+month+") monthOff("+monthOff+") DS("+dateString+") Moy("+monthOfYear+") ms("+monthString+")";
if(curYear != year) {
var yrOff = year * yearImgWidth;
document.getElementById("wbMouseTrackYearImg").style.left = yrOff + "px";
curYear = year;
}
if(curMonth != month) {
var mtOff = year + (month * monthImgWidth) + 1;
document.getElementById("wbMouseTrackMonthImg").style.left = mtOff + "px";
curMonth = month;
}
}
//]]>
</script>
<style type="text/css">body{margin-top:0!important;padding-top:0!important;min-width:800px!important;}#wm-ipp a:hover{text-decoration:underline!important;}</style>
<div id="wm-ipp" style="display:none; position:relative;padding:0 5px;min-height:70px;min-width:800px; z-index:9000;">
<div id="wm-ipp-inside" style="position:fixed;padding:0!important;margin:0!important;width:97%;min-width:780px;border:5px solid #000;border-top:none;background-image:url(http://staticweb.archive.org/images/toolbar/wm_tb_bk_trns.png);text-align:center;-moz-box-shadow:1px 1px 3px #333;-webkit-box-shadow:1px 1px 3px #333;box-shadow:1px 1px 3px #333;font-size:11px!important;font-family:'Lucida Grande','Arial',sans-serif!important;">
<table style="border-collapse:collapse;margin:0;padding:0;width:100%;"><tbody><tr>
<td style="padding:10px;vertical-align:top;min-width:110px;">
<a href="http://wayback.archive.org/web/" title="Wayback Machine home page" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wayback-toolbar-logo.png" alt="Wayback Machine" width="110" height="39" border="0"/></a>
</td>
<td style="padding:0!important;text-align:center;vertical-align:top;width:100%;">
<table style="border-collapse:collapse;margin:0 auto;padding:0;width:570px;"><tbody><tr>
<td style="padding:3px 0;" colspan="2">
<form target="_top" method="get" action="http://wayback.archive.org/web/form-submit.jsp" name="wmtb" id="wmtb" style="margin:0!important;padding:0!important;"><input type="text" name="url" id="wmtbURL" value="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching" style="width:400px;font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;" onfocus="javascript:this.focus();this.select();" /><input type="hidden" name="type" value="replay" /><input type="hidden" name="date" value="20081006064142" /><input type="submit" value="Go" style="font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;margin-left:5px;" /><span id="wm_tb_options" style="display:block;"></span></form>
</td>
<td style="vertical-align:bottom;padding:5px 0 0 0!important;" rowspan="2">
<table style="border-collapse:collapse;width:110px;color:#99a;font-family:'Helvetica','Lucida Grande','Arial',sans-serif;"><tbody>
<!-- NEXT/PREV MONTH NAV AND MONTH INDICATOR -->
<tr style="width:110px;height:16px;font-size:10px!important;">
<td style="padding-right:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
Sep
</td>
<td id="displayMonthEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight:bold;text-transform:uppercase;width:34px;height:15px;padding-top:1px;text-align:center;" title="You are here: 6:41:42 Oct 6, 2008">OCT</td>
<td style="padding-left:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;white-space:nowrap;overflow:visible;" nowrap="nowrap">
<a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching" style="text-decoration:none;color:#33f;font-weight:bold;background-color:transparent;border:none;" title="30 Apr 2009"><strong>APR</strong></a>
</td>
</tr>
<!-- NEXT/PREV CAPTURE NAV AND DAY OF MONTH INDICATOR -->
<tr>
<td style="padding-right:9px;white-space:nowrap;overflow:visible;text-align:right!important;vertical-align:middle!important;" nowrap="nowrap">
<img src="http://staticweb.archive.org/images/toolbar/wm_tb_prv_off.png" alt="Previous capture" width="14" height="16" border="0" />
</td>
<td id="displayDayEl" style="background:#000;color:#ff0;width:34px;height:24px;padding:2px 0 0 0;text-align:center;font-size:24px;font-weight: bold;" title="You are here: 6:41:42 Oct 6, 2008">6</td>
<td style="padding-left:9px;white-space:nowrap;overflow:visible;text-align:left!important;vertical-align:middle!important;" nowrap="nowrap">
<a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching" title="13:08:33 Apr 30, 2009" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wm_tb_nxt_on.png" alt="Next capture" width="14" height="16" border="0"/></a>
</td>
</tr>
<!-- NEXT/PREV YEAR NAV AND YEAR INDICATOR -->
<tr style="width:110px;height:13px;font-size:9px!important;">
<td style="padding-right:9px;font-size:11px!important;font-weight: bold;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
2007
</td>
<td id="displayYearEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight: bold;padding-top:1px;width:34px;height:13px;text-align:center;" title="You are here: 6:41:42 Oct 6, 2008">2008</td>
<td style="padding-left:9px;font-size:11px!important;font-weight: bold;white-space:nowrap;overflow:visible;" nowrap="nowrap">
2009
</td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td style="vertical-align:middle;padding:0!important;">
<a href="http://wayback.archive.org/web/20081006064142*/http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching" style="color:#33f;font-size:11px;font-weight:bold;background-color:transparent;border:none;" title="See a list of every capture for this URL"><strong>2 captures</strong></a>
<div style="margin:0!important;padding:0!important;color:#666;font-size:9px;padding-top:2px!important;white-space:nowrap;" title="Timespan for captures of this URL">6 Oct 08 - 30 Apr 09</div>
</td>
<td style="padding:0!important;">
<a style="position:relative; white-space:nowrap; width:400px;height:27px;" href="" id="wm-graph-anchor">
<div id="wm-ipp-sparkline" style="position:relative; white-space:nowrap; width:400px;height:27px;background-color:#fff;cursor:pointer;border-right:1px solid #ccc;" title="Explore captures for this URL">
<img id="sparklineImgId" style="position:absolute; z-index:9012; top:0px; left:0px;"
onmouseover="showTrackers('inline');"
onmouseout="showTrackers('none');"
onmousemove="trackMouseMove(event,this)"
alt="sparklines"
width="400"
height="27"
border="0"
src="http://wayback.archive.org/jsp/graph.jsp?graphdata=400_27_1996:-1:000000000000_1997:-1:000000000000_1998:-1:000000000000_1999:-1:000000000000_2000:-1:000000000000_2001:-1:000000000000_2002:-1:000000000000_2003:-1:000000000000_2004:-1:000000000000_2005:-1:000000000000_2006:-1:000000000000_2007:-1:000000000000_2008:9:000000000100_2009:-1:000100000000_2010:-1:000000000000_2011:-1:000000000000"></img>
<img id="wbMouseTrackYearImg"
style="display:none; position:absolute; z-index:9010;"
width="25"
height="27"
border="0"
src="http://staticweb.archive.org/images/toolbar/transp-yellow-pixel.png"></img>
<img id="wbMouseTrackMonthImg"
style="display:none; position:absolute; z-index:9011; "
width="2"
height="27"
border="0"
src="http://staticweb.archive.org/images/toolbar/transp-red-pixel.png"></img>
</div>
</a>
</td>
</tr></tbody></table>
</td>
<td style="text-align:right;padding:5px;width:65px;font-size:11px!important;">
<a href="javascript:;" onclick="document.getElementById('wm-ipp').style.display='none';" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_close.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;margin-bottom:23px;background-color:transparent;border:none;" title="Close the toolbar">Close</a>
<a href="http://faq.web.archive.org/" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_help.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;background-color:transparent;border:none;" title="Get some help using the Wayback Machine">Help</a>
</td>
</tr></tbody></table>
</div>
</div>
<script type="text/javascript">
var wmDisclaimBanner = document.getElementById("wm-ipp");
if(wmDisclaimBanner != null) {
disclaimElement(wmDisclaimBanner);
}
</script>
<!-- END WAYBACK TOOLBAR INSERT -->
<div id="container">
<div id="header">
<h1><span><a href="http://sami.samhuri.net/">sjs</a></span></h1>
<h2>geeky ramblings</h2>
</div>
<div id="page">
<div id="content">
<!--
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<rdf:Description
rdf:about=""
trackback:ping=""
dc:title="ElSchemo: Boolean logic and branching"
dc:identifier="/2007/8/2/elschemo-boolean-logic-and-branching"
dc:description="<p>I've been developing a Scheme
interpreter in Haskell called
<a href="http://sami.samhuri.net/2007/6/25/floating-point-in-elschemo">ElSchemo</a>.
It started from <a href="http://halogen.note.amherst.edu/~jdtang/scheme_in_48/tutorial/overvi..."
dc:creator="sjs"
dc:date="August 02, 2007 16:59" />
</rdf:RDF>
-->
<div class="hentry" id="article-210">
<h2 class="entry-title">
<a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching">ElSchemo: Boolean logic and branching</a>
</h2>
<div class="vcard">
Posted by <span class="fn">sjs</span>
</div>
<abbr class="published" title="2007-08-02T16:59:00+00:00">on Thursday, August 02</abbr>
<br class="clear" />
<div class="entry-content">
<p>I've been developing a Scheme
interpreter in Haskell called
<a href="http://sami.samhuri.net/2007/6/25/floating-point-in-elschemo">ElSchemo</a>.
It started from <a href="http://halogen.note.amherst.edu/~jdtang/scheme_in_48/tutorial/overview.html">Jonathan's excellent Haskell
tutorial</a>
which I followed in order to learn both Haskell and Scheme. Basically
that means the code here is for me to get some feedback as much
as to show others how to do this kind of stuff. This may not be too
interesting if you haven't at least browsed the tutorial.</p>
<p>I'm going to cover 3 new special forms: <code>and</code>, <code>or</code>, and <code>cond</code>. I
promised to cover the <code>let</code> family of special forms this time around
but methinks this is long enough as it is. My sincere apologies if
you've been waiting for those.</p>
<h2>Short-circuiting Boolean logic</h2>
<p>Two functions from the tutorial which may irk you immediately are
<code>and</code> and <code>or</code>, defined in Scheme in the given standard library. If
your code is free of side-effects then it may not bother you so
much. It bothered me. The problem with the implementation in
stdlib.scm is that all the arguments are evaluated before control
enters the function. Besides being inefficient by doing unnecessary work,
if any of the arguments have side-effects you can make use of short-circuiting
by using <code>and</code> to sequence actions, bailing out if any fail (by returning <code>nil</code>),
and using <code>or</code> to define a set of alternative actions which will bail out when the first in the list succeeds (by returning anything but <code>nil</code>). Had we macros then we could implement them as
macros. We don't, so we'll write them as special forms in Haskell.</p>
<p>Unlike the special forms defined in the tutorial I'm going to
implement these as separate functions for clarity, rather than lump
them all in <code>eval</code>. However, they will be invoked directly from
<code>eval</code> so their type is easy; it's the same as <code>eval</code>'s.</p>
<p>Code first, ask questions later. Haskell is a pretty clear and
concise language. My explanations may be redundant because of this.</p>
<h3>lispAnd</h3>
<table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">lispAnd :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal<tt>
</tt>lispAnd env [] = return $ Bool True<tt>
</tt>lispAnd env [pred] = eval env pred<tt>
</tt>lispAnd env (pred:rest) = do<tt>
</tt> result &lt;- eval env pred<tt>
</tt> case result of<tt>
</tt> Bool False -&gt; return result<tt>
</tt> _ -&gt; lispAnd env rest</pre></td>
</tr></table>
<p>Starting with the trivial case, <code>and</code> returns <code>#t</code> with zero
arguments.</p>
<p>With one argument, a single predicate, simply evaluate and
return that argument.</p>
<p>Given a list of predicates, evaluate the first and inspect its value.
If the argument evaluated to <code>#f</code> then our work is done and we return
<code>#f</code>, otherwise we keep plugging along by making a recursive call with
the first argument stripped off. Eventually we will reach our base
case with only one predicate.</p>
<p>It's possible to eliminate the case of one predicate. I think that
just complicates things but it's a viable solution.</p>
<h3>lispOr</h3>
<p>Predictably this is quite similar to <code>lispAnd</code>.</p>
<table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">lispOr :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal<tt>
</tt>lispOr env [] = return $ Bool False<tt>
</tt>lispOr env [pred] = eval env pred<tt>
</tt>lispOr env (pred:rest) = do<tt>
</tt> result &lt;- eval env pred<tt>
</tt> case result of<tt>
</tt> Bool False -&gt; lispOr env rest<tt>
</tt> _ -&gt; return result</pre></td>
</tr></table>
<p>With no arguments <code>lispOr</code> returns <code>#f</code>, and with one argument it
evaluates and returns the result.</p>
<p>With 2 or more arguments the first is evaluated, but this time if the
result is <code>#f</code> then we continue looking for a truthy value. If the
result is anything else at all then it's returned and we are done.</p>
<h2>A new branching construct</h2>
<p>First let me define a convenience function that I have added to
ElSchemo. It maps a list of expressions to their values by evaluating
each one in the given environment.</p>
<table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">evalExprs :: Env -&gt; [LispVal] -&gt; IOThrowsError [LispVal]<tt>
</tt>evalExprs env exprs = mapM (eval env) exprs</pre></td>
</tr></table>
<h3>lispCond</h3>
<p>Again, <code>lispCond</code> has the same type as <code>eval</code>.</p>
<table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">lispCond :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal<tt>
</tt>lispCond env (List (pred:conseq) : rest) = do<tt>
</tt> result &lt;- eval env pred<tt>
</tt> case result of<tt>
</tt> Bool False -&gt; if null rest then return result else lispCond env rest<tt>
</tt> _ -&gt; liftM last $ evalExprs env conseq</pre></td>
</tr></table>
<p>Unlike Lisp - which uses a predicate of <code>T</code> (true) - Scheme uses a
predicate of <code>else</code> to trigger the default branch. When the pattern
matching on <code>Atom "else"</code> succeeds, we evaluate the default
expressions and return the value of the last one. This is one
possible base case. <code>Atom "else"</code> could be defined to evaluate to
<code>#t</code>, but we don't want <code>else</code> to be evaluated as <code>#t</code> anywhere except
in a <code>cond</code> so I have chosen this solution.</p>
<p>If the first predicate is not <code>else</code> then we evaluate it and check the
resulting value. If we get <code>#f</code> then we look at the rest of the
statement, if it's empty then we return <code>#f</code>, otherwise we recurse on
the rest of the parameters. If the predicate evaluates to a truthy
value - that is, anything but <code>#f</code> - then we evaluate the consequent
expressions and return the value of the last one.</p>
<h2>Plumbing</h2>
<p>Now all that's left is to hook up the new functions in <code>eval</code>.</p>
<table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">eval env (List (Atom &quot;and&quot; : params)) = lispAnd env params<tt>
</tt>eval env (List (Atom &quot;or&quot; : params)) = lispOr env params<tt>
</tt>eval env (List (Atom &quot;cond&quot; : params)) = lispCond env params</pre></td>
</tr></table>
<p>You could, of course, throw the entire definitions in <code>eval</code> itself but <code>eval</code> is big
enough for me as it is. YMMV.</p>
<h2>Done!</h2>
<p>So, that's a wrap. It only took 20 lines of code for the 3 new
special forms, and it could easily be done with less code. Next time
I will show you how to implement the various <code>let</code> functions. Really!</p>
<p><em>Do you like me describing ElSchemo piece by piece as I have been? I
plan on posting the Haskell code and my stdlib.scm in their entirety
sometime, and I could do that before or after I finish writing about
the features I've developed beyond the tutorial. Just let me know in
the comments.</em></p>
<div class="extended">
<p><a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching">Continue reading...</a></p>
</div>
</div>
<ul class="meta">
<li>
Tags: <a href="http://sami.samhuri.net/tags/elschemo">elschemo</a>&nbsp;<a href="http://sami.samhuri.net/tags/haskell">haskell</a>&nbsp;<a href="http://sami.samhuri.net/tags/scheme">scheme</a>&nbsp;
</li>
<li>
Meta:
<a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching">permalink</a>
</li>
</ul>
</div>
<h5><a name="comments">Comments</a></h5>
<p><a href="http://sami.samhuri.net/2007/8/2/elschemo-boolean-logic-and-branching#comment-form">Leave a response</a></p>
<div id="comments_div">
<ol id="comments" class="comments">
</ol>
</div>
</div>
<div id="sidebar">
<div class="sidebar-node">
<div id="search" class="search">
<form action="http://sami.samhuri.net/search" id="sform" method="get" name="sform">
<p><input type="text" id="q" name="q" value="" /></p>
</form>
</div>
</div>
<div class="sidebar-node">
<h3>Sections</h3>
<ul>
<li><a href="http://sami.samhuri.net/">geeky ramblings</a> (15)</li>
<li><a href="http://sami.samhuri.net/emacs">Emacs</a> (3)</li>
</ul>
</div>
<div class="sidebar-node">
<h3>Tags</h3>
<ul>
<li><a href="http://sami.samhuri.net/tags/activerecord">activerecord</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/alsa">alsa</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/amusement">amusement</a> (6)</li>
<li><a href="http://sami.samhuri.net/tags/apple">apple</a> (6)</li>
<li><a href="http://sami.samhuri.net/tags/arc">arc</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/bdd">bdd</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/broken">broken</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/browsers">browsers</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/buffalo">buffalo</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/bundle">bundle</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/cheat">cheat</a> (3)</li>
<li><a href="http://sami.samhuri.net/tags/coding">coding</a> (22)</li>
<li><a href="http://sami.samhuri.net/tags/cool">cool</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/coverflow">coverflow</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/crazy">crazy</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/digg">digg</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/drm">drm</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/dtrace">dtrace</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/dubai">dubai</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/elschemo">elschemo</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/emacs">emacs</a> (11)</li>
<li><a href="http://sami.samhuri.net/tags/english">english</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/extensions">extensions</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/firefox">firefox</a> (3)</li>
<li><a href="http://sami.samhuri.net/tags/framework">framework</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/funny">funny</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/fuse">fuse</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/games">games</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/gentoo">gentoo</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/german">german</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/gtkpod">gtkpod</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/haskell">haskell</a> (7)</li>
<li><a href="http://sami.samhuri.net/tags/humans">humans</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/injury">injury</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/inspirado">inspirado</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/iphone">iphone</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/itunes">itunes</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/i_laughed_i_cried">i_laughed_i_cried</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/keyboard">keyboard</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/keyboard%20shortcuts">keyboard shortcuts</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/lemmings">lemmings</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/life">life</a> (13)</li>
<li><a href="http://sami.samhuri.net/tags/linux">linux</a> (8)</li>
<li><a href="http://sami.samhuri.net/tags/lisp">lisp</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/lisp%20arc">lisp arc</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/mac%20os%20x">mac os x</a> (6)</li>
<li><a href="http://sami.samhuri.net/tags/mediawiki">mediawiki</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/mephisto">mephisto</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/migrations">migrations</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/munich">munich</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/mysql">mysql</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/networking">networking</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/opera">opera</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/pedantry">pedantry</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/people">people</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/photo">photo</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/php">php</a> (4)</li>
<li><a href="http://sami.samhuri.net/tags/programming">programming</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/project%20euler">project euler</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/propaganda">propaganda</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/python">python</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/quickcheck">quickcheck</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/rails">rails</a> (18)</li>
<li><a href="http://sami.samhuri.net/tags/rails%20on%20rules">rails on rules</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/regex">regex</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/regular%20expressions">regular expressions</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/rest">rest</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/rtfm">rtfm</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/ruby">ruby</a> (14)</li>
<li><a href="http://sami.samhuri.net/tags/rushcheck">rushcheck</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/sake">sake</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/scheme">scheme</a> (4)</li>
<li><a href="http://sami.samhuri.net/tags/school">school</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/seaside">seaside</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/secure%20associations">secure associations</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/seekport">seekport</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/snippets">snippets</a> (3)</li>
<li><a href="http://sami.samhuri.net/tags/ssh">ssh</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/tagify">tagify</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/technology">technology</a> (6)</li>
<li><a href="http://sami.samhuri.net/tags/test/spec">test/spec</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/textmate">textmate</a> (7)</li>
<li><a href="http://sami.samhuri.net/tags/tips">tips</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/typo">typo</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/ubuntu">ubuntu</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/usability">usability</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/userscript">userscript</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/vacation">vacation</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/vim">vim</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/volume">volume</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/web">web</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/web%20objects">web objects</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/wikipediafs">wikipediafs</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/windows">windows</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/work">work</a> (1)</li>
<li><a href="http://sami.samhuri.net/tags/zend">zend</a> (2)</li>
<li><a href="http://sami.samhuri.net/tags/zsh">zsh</a> (1)</li>
</ul>
</div>
<div class="sidebar-node">
<h3>Friends &amp; cool blogs</h3>
<ul>
<li><a href="http://jim.roepcke.com/">have browser, will travel</a></li>
<li><a href="http://cassandrahill.blogspot.com/">cj's chatter</a></li>
</ul>
</div>
<div class="sidebar-node">
<p><a href="http://twitter.com/_sjs">
<img src="http://web.archive.org/web/20081006064142im_/http://sami.samhuri.net/assets/2007/6/26/icon_twitter.png" alt="[t]" /> twitter</a></p>
</div>
<div class="sidebar-node">
<p><a href="http://mephistoblog.com/" class="powered"><img alt="mephisto-badge-tiny" src="http://web.archive.org/web/20081006064142im_/http://sami.samhuri.net/images/mephisto-badge-tiny.png" /></a></p>
</div>
</div>
<br style="clear:both;" />
</div>
<div id="footer">
<hr />
<p><a href="http://sami.samhuri.net/">sjs</a></p>
<ul>
<li>powered by <a href="http://mephistoblog.com/">Mephisto</a> /
styled with <a href="http://quotedprintable.com/pages/scribbish">scribbish</a></li>
</ul>
</div>
</div>
<script src="http://web.archive.org/web/20081006064142js_/http://www.google-analytics.com/urchin.js" type="text/javascript"> </script>
<script type="text/javascript"> _uacct = "UA-214054-3"; urchinTracker(); </script>
<script src="http://web.archive.org/web/20081006064142js_/http://feeds.feedburner.com/~s/sjs" type="text/javascript" charset="utf-8"></script>
</body>
</html>
<!--
FILE ARCHIVED ON 6:41:42 Oct 6, 2008 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 2:59:51 Aug 21, 2011.
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
SECTION 108(a)(3)).
-->