<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Random Hacks: Tag Hacks</title>
    <link>http://www.randomhacks.net/articles/tag/Hacks?tag=Hacks</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>Haskell: What happens when you divide infinity by 2?</title>
      <description>&lt;p&gt;Sometime back in elementary school, I first asked teachers, &amp;#8220;What happens when you divide infinity by 2?&amp;#8221; Some teachers couldn&amp;#8217;t answer, and others told me, &amp;#8220;It&amp;#8217;s still infinity!&amp;#8221;&lt;/p&gt;

&lt;p&gt;More recently, a couple of friends were discussing a similar question at lunch: &amp;#8220;What happens when you add 1 to infinity?&amp;#8221;&lt;/p&gt;

&lt;p&gt;Of course I said, &amp;#8220;It&amp;#8217;s still infinity!&amp;#8221;, but I couldn&amp;#8217;t explain it much better than my school teachers (at least not without using the word &lt;a href="http://en.wikipedia.org/wiki/Denumerable"&gt;denumerable&lt;/a&gt;, which is a good way to ruin a lunch conversation).&lt;/p&gt;

&lt;p&gt;And then tonight, while reading a &lt;a title="Fast and Loose Reasoning is Morally Correct" href="http://citeseer.ist.psu.edu/danielsson06fast.html"&gt;paper about Haskell&lt;/a&gt;, I was hit by an evil idea: When in doubt, ask the Haskell interpreter!&lt;/p&gt;

&lt;h2&gt;Step 1: Counting&lt;/h2&gt;

&lt;p&gt;First, we need to teach Haskell about the natural numbers. (Why not use Haskell&amp;#8217;s built-in integers? Just humor the crazy programmer for a moment, OK?)&lt;/p&gt;

&lt;p&gt;A number is either zero, or the successor of another number. We can write that in Haskell as:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;Nat&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Zero&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='conid'&gt;Succ&lt;/span&gt; &lt;span class='conid'&gt;Nat&lt;/span&gt;
  &lt;span class='keyword'&gt;deriving&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Show&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Eq&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Ord&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Math geeks in the audience will recognize this as the &lt;a href="http://mathworld.wolfram.com/PeanosAxioms.html"&gt;Peano arithmetic&lt;/a&gt;. The &amp;#8220;deriving&amp;#8221; keyword tells Haskell to define &lt;code&gt;show&lt;/code&gt; and the comparison operators for us.&lt;/p&gt;

&lt;p&gt;Using this definition of Nat, we can now define some numbers:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;one&lt;/span&gt;   &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Succ&lt;/span&gt; &lt;span class='conid'&gt;Zero&lt;/span&gt;
&lt;span class='varid'&gt;two&lt;/span&gt;   &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Succ&lt;/span&gt; &lt;span class='varid'&gt;one&lt;/span&gt;
&lt;span class='varid'&gt;three&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Succ&lt;/span&gt; &lt;span class='varid'&gt;two&lt;/span&gt;
&lt;span class='varid'&gt;four&lt;/span&gt;  &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Succ&lt;/span&gt; &lt;span class='varid'&gt;three&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These work the way you&amp;#8217;d expect:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;*Main&amp;gt; three
Succ (Succ (Succ Zero))
*Main&amp;gt; two &amp;lt; three
True&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;OK, I threw in that last example just for fun.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/02/02/divide-infinity-by-2"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 02 Feb 2007 22:00:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:49c4f02e-74eb-430a-9b49-bfd623f3f586</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/02/02/divide-infinity-by-2</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Hacks</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/259</trackback:ping>
    </item>
    <item>
      <title>Some useful closures, in Ruby</title>
      <description>&lt;p&gt;Reginald Braithwaite has just posted &lt;a href="http://weblog.raganwald.com/2007/01/closures-and-higher-order-functions.html"&gt;a short introduction to closures in Ruby&lt;/a&gt;. Closures allow you to pass functions around your program, and build new functions from old ones.&lt;/p&gt;

&lt;p&gt;Programming languages that support closures include Perl, Ruby, Python (sorta), Lisp, Haskell, Dylan, Javascript and many others.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/Dylan_programming_language"&gt;Dylan programming language&lt;/a&gt; included four very useful functions built using closures: &lt;strong&gt;complement&lt;/strong&gt;, &lt;strong&gt;conjoin&lt;/strong&gt;, &lt;strong&gt;disjoin&lt;/strong&gt; and &lt;strong&gt;compose&lt;/strong&gt;.  The names are a bit obscure, but they can each be written in a few lines of Ruby.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start with &lt;strong&gt;complement&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# Builds a function that returns true&lt;/span&gt;
&lt;span class="comment"&gt;# when 'f' returns false, and vice versa.&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;complement&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt;
  &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use this to build the &amp;#8220;opposite&amp;#8221; of a function:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;is_even&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;is_odd&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;complement&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;is_even&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;is_odd&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# true&lt;/span&gt;
&lt;span class="ident"&gt;is_odd&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;compose&lt;/strong&gt; is another useful function:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# Builds a function which calls 'f' with&lt;/span&gt;
&lt;span class="comment"&gt;# the return value of 'g'.&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;compose&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;g&lt;/span&gt;
  &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;g&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use this to pass the output of one function to the input of another:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;mult2&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;add1&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;+&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;mult2_add1&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;compose&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;add1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;mult2&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;mult2_add1&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# 7&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;conjoin&lt;/strong&gt; function is a bit more complicated, but still very useful:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# Builds a function which returns true&lt;/span&gt;
&lt;span class="comment"&gt;# whenever _every_ function in 'predicates'&lt;/span&gt;
&lt;span class="comment"&gt;# returns true.&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;conjoin&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;predicates&lt;/span&gt;
  &lt;span class="ident"&gt;base&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;predicates&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;inject&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;base&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;built&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pred&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;built&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="ident"&gt;pred&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can use it to construct the logical &amp;#8220;and&amp;#8221; of a list of functions:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;is_number&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;kind_of?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Numeric&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;is_even_number&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;conjoin&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;is_number&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;is_even&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;is_even_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="comment"&gt;# false&lt;/span&gt;
&lt;span class="ident"&gt;is_even_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;   &lt;span class="comment"&gt;# false&lt;/span&gt;
&lt;span class="ident"&gt;is_even_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;   &lt;span class="comment"&gt;# true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The opposite of &lt;strong&gt;conjoin&lt;/strong&gt; is &lt;strong&gt;disjoin&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# Builds a function which returns true&lt;/span&gt;
&lt;span class="comment"&gt;# whenever _any_ function in 'predicates'&lt;/span&gt;
&lt;span class="comment"&gt;# returns true.&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;disjoin&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;&lt;span class="ident"&gt;predicates&lt;/span&gt;
  &lt;span class="ident"&gt;base&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;predicates&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;inject&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;base&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;built&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pred&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;built&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;pred&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(*&lt;/span&gt;&lt;span class="ident"&gt;args&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This allows us to construct the logical &amp;#8220;or&amp;#8221; of a list of functions:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;is_string&lt;/span&gt;  &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;kind_of?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;is_string_or_number&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt;
  &lt;span class="ident"&gt;disjoin&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;is_string&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;is_number&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;is_string_or_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="comment"&gt;# true&lt;/span&gt;
&lt;span class="ident"&gt;is_string_or_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;   &lt;span class="comment"&gt;# true&lt;/span&gt;
&lt;span class="ident"&gt;is_string_or_number&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:a&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;  &lt;span class="comment"&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These were four of the first closure-related functions I ever used, and they&amp;#8217;re still favorites today.&lt;/p&gt;

&lt;p&gt;Feel free to post versions in other languages below!&lt;/p&gt;</description>
      <pubDate>Thu, 01 Feb 2007 18:36:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:662731c8-031a-46e3-97bc-02668e09b272</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/02/01/some-useful-closures-in-ruby</link>
      <category>Ruby</category>
      <category>Hacks</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/245</trackback:ping>
    </item>
    <item>
      <title>Selenium on Rails, Reloaded: Client-Side Tests in Ruby</title>
      <description>&lt;p&gt;Like most &lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; developers, I write lots of test cases for
my models and controllers.  This lets me add new features quickly, without
worrying about breakage: My test cases act as a safety net, warning me
whenever existing code fails.&lt;/p&gt;

&lt;p&gt;Sadly, it&amp;#8217;s much harder to test client-side behavior.  Sure, you know your
controllers work, but what actually &lt;em&gt;happens&lt;/em&gt; if a user clicks the Submit
button?  We need a better way to test the system end-to-end, including the actual JavaScript and
web browsers.&lt;/p&gt;

&lt;p&gt;This article shows how to combine &lt;a href="http://www.openqa.org/selenium/"&gt;Selenium&lt;/a&gt;, &lt;a href="http://andthennothing.net/archives/2006/02/05/selenium-on-rails"&gt;Selenium on Rails&lt;/a&gt;, and a
&lt;a href="/files/rselenese.diff"&gt;custom patch&lt;/a&gt; to write client-side test cases in Ruby:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setup&lt;/span&gt; &lt;span class="comment"&gt;# Load fixtures&lt;/span&gt;
&lt;span class="ident"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt; &lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;customer&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
          &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;list&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_title&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Customers&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;click&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;myLink&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:wait&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
&lt;span class="ident"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_title&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Customer: *&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These test cases actually run in your browser, loading pages and clicking links just as a user would.  As the above example shows, you have full access to the Rails environment, including URL routing and configuration data.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2006/02/15/selenium-on-rails-reloaded"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 15 Feb 2006 08:06:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:55cb00a4-1da9-4bc4-9273-ca919579c458</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2006/02/15/selenium-on-rails-reloaded</link>
      <category>Rails</category>
      <category>Hacks</category>
      <category>Selenium</category>
      <category>testing</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/171</trackback:ping>
    </item>
    <item>
      <title>Typo sidebars: Recent Comments and Tagged Articles</title>
      <description>&lt;p&gt;Here's two new plugins for &lt;a href="http://typo.leetsoft.com/trac/"&gt;Typo&lt;/a&gt;, the cool Rails-based blogging software. The first shows a &lt;a href="/files/recent_comments_sidebar.zip" title="Recent Comments Plugin"&gt;list of recent comments&lt;/a&gt;. The second shows &lt;a href="/files/tagged_articles_sidebar.zip" title="Tagged Articles Plugin"&gt;articles with a specific tag&lt;/a&gt;. (I use it to implement the "Recommended Reading" list in my sidebar.)&lt;/p&gt;

&lt;p&gt;To install the plugins, simply unzip them in your Typo root directory, restart Typo, and take a look at the "Sidebar" tab in the admin screen.&lt;/p&gt;

&lt;p&gt;These plugins were unbelievably simple to write. If you'd like to see how they work, keep reading.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2005/11/13/typo-sidebars-recent-comments-and-tagged-articles"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 13 Nov 2005 21:04:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:67f6b627-8a35-4c65-a1e2-1a0350e347aa</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2005/11/13/typo-sidebars-recent-comments-and-tagged-articles</link>
      <category>Typo</category>
      <category>Rails</category>
      <category>Hacks</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/74</trackback:ping>
    </item>
    <item>
      <title>McCarthy's Ambiguous Operator</title>
      <description>    &lt;p&gt;Back in 1961, John McCarthy (the inventor of LISP) &lt;a href='http://citeseer.ist.psu.edu/mccarthy63basis.html'&gt;described&lt;/a&gt;
    an interesting mathematical operator called &lt;code&gt;amb&lt;/code&gt;.  Essentially,
    &lt;code&gt;amb&lt;/code&gt; &lt;i&gt;hates&lt;/i&gt; to be called with no arguments, and can look
    into the future to keep that from happening.  Here's how it might look
    in Ruby.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2005/10/11/amb-operator"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 11 Oct 2005 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:8d29ae6d-81d0-4f48-a6cb-80187e1821a7</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2005/10/11/amb-operator</link>
      <category>Ruby</category>
      <category>Continuations</category>
      <category>Hacks</category>
      <category>Recommended</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/70</trackback:ping>
    </item>
    <item>
      <title>15 Minutes and 150MB of RAM to Compare Unix and Linux</title>
      <description>    &lt;p&gt;SCO has recently made &lt;a href='http://www.linuxjournal.com/article.php?sid=6956'&gt;two
    accusations&lt;/a&gt;: (1) IBM has contributed IBM employees' code to Linux
    in violation of certain SCO/IBM contracts, and (2) some proprietary
    Unix code has somehow been illegally contributed to Linux.  I'm not
    qualified to comment on whether or not IBM owns the code IBM
    wrote--though on behalf of software authors everywhere, I hope IBM
    does.  However, I've written a tool which will allow SCO to find any
    code shared between Linux and Unix in about 15 minutes.  What SCO does
    with this tool is up to them.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2003/06/20/srcdupchk-release"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 20 Jun 2003 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:898e9618-c937-4667-9c5c-522985af0f9a</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2003/06/20/srcdupchk-release</link>
      <category>Hacks</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/59</trackback:ping>
    </item>
    <item>
      <title>Bayesian Whitelisting: Finding the Good Mail Among the Spam</title>
      <description>    &lt;p&gt;The biggest challenge with spam filtering is reducing false
    positives--that is, finding the good mail among the spam.  Even the
    best spam filters occasionally mistake legitimate e-mail for spam.  For
    example, in some &lt;a href='/stories/2002/09/22/trainable-spam-filter-testing' title='How To Test a Trainable Spam Filter'&gt;recent
    tests&lt;/a&gt;, &lt;a href='http://bogofilter.sourceforge.net/'&gt;&lt;code&gt;bogofilter&lt;/code&gt;&lt;/a&gt;
    processed 18,000 e-mails with only 34 false positives.  Unfortunately,
    several of these false positives were urgent e-mails from former
    clients.  This unpleasant mistake wasn't necessary--the most important
    of these false positives could have been avoided with an automatic
    whitelisting system.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2002/09/29/bayesian-whitelisting"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 29 Sep 2002 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4e3b83e6-1f2a-48d4-9f65-5e691ab45838</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2002/09/29/bayesian-whitelisting</link>
      <category>Spam</category>
      <category>Hacks</category>
      <category>Python</category>
      <category>Recommended</category>
      <category>Probability</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/38</trackback:ping>
    </item>
    <item>
      <title>How To Test a Trainable Spam Filter</title>
      <description>    &lt;p&gt;Ever since Paul Graham published &lt;a href='http://www.paulgraham.com/spam.html'&gt;A Plan for Spam&lt;/a&gt;,
    "trainable" spam filters have become the latest fashion.  These filters
    train themselves to know the characteristics of your personal e-mail.
    Supposedly, this extra knowledge allows them to make fewer mistakes,
    and makes them harder to fool.  But do these filters actually work?  In
    this article, I try out Eric Raymond's &lt;a href='/stories/2002/09/13/bogofilter' title='Bogofilter: A New Spam Filter'&gt;bogofilter&lt;/a&gt;, a trainable Bayesian spam filter,
    and describe the steps required to evaluate such a filter
    accurately.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2002/09/22/trainable-spam-filter-testing"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 22 Sep 2002 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:c227afc7-6562-4fc5-8b77-7624df1aed2e</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2002/09/22/trainable-spam-filter-testing</link>
      <category>Spam</category>
      <category>Hacks</category>
      <category>Recommended</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/31</trackback:ping>
    </item>
    <item>
      <title>Why Hygienic Macros Rock</title>
      <description>    &lt;p&gt;I've recently been reading a lot of &lt;a href='http://www.paulgraham.com/articles.html'&gt;excellent essays on
    programming language design&lt;/a&gt; by Paul Graham.  Paul and I agree about
    a number of things: (1) LISP is beautiful and powerful family of
    languages, even by modern standards, (2) all existing dialects of LISP
    are lacking a certain something, and (3) programmatic macros are a Good
    Idea.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2002/09/13/hygienic-macros"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 13 Sep 2002 00:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:213d6f83-48bd-4661-a3eb-98fb3784f7da</guid>
      <author>Eric</author>
      <link>http://www.randomhacks.net/articles/2002/09/13/hygienic-macros</link>
      <category>Macros</category>
      <category>LISP</category>
      <category>Hacks</category>
      <category>Recommended</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/24</trackback:ping>
    </item>
  </channel>
</rss>
