<?xml version='1.0' encoding='utf-8' ?>
<!--  If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/  -->
<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:media='http://search.yahoo.com/mrss/' xmlns:atom10='http://www.w3.org/2005/Atom'>
<channel>
  <title>Brian Jaress&apos;s Blog</title>
  <link>http://brian-jaress.livejournal.com/</link>
  <description>Brian Jaress&apos;s Blog - LiveJournal.com</description>
  <lastBuildDate>Wed, 23 Dec 2009 08:02:51 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <lj:journal>brian_jaress</lj:journal>
  <lj:journalid>12325700</lj:journalid>
  <lj:journaltype>personal</lj:journaltype>
  <atom10:link rel='hub' href='http://pubsubhubbub.appspot.com/' />
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/9382.html</guid>
  <pubDate>Wed, 23 Dec 2009 08:02:51 GMT</pubDate>
  <title>Jest 2.0 is in Beta</title>
  <link>http://brian-jaress.livejournal.com/9382.html</link>
  <description>&lt;p&gt;The 2.0 beta of &lt;a href=&quot;http://home.gna.org/jest/&quot; title=&quot;Brian Jaress&amp;#39;s Software Estimator&quot;&gt;jest&lt;/a&gt; is available for &lt;a href=&quot;http://download.gna.org/jest/?M=D&quot; title=&quot;Download jest&quot;&gt;download&lt;/a&gt;. I removed a bunch of lesser features, for the sake of both simplicity and adding a unique and powerful feature:&lt;/p&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;p&gt;Jest will now, by default, estimate how much software can be written in a given amount of time, rather than estimating how long it will take to write a given amount of software.&lt;a name=&quot;fnref1&quot;&gt;&lt;a href=&quot;#fn1&quot; class=&quot;footnoteRef&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Estimating time based on size is what &lt;a href=&quot;http://csse.usc.edu/csse/research/COCOMOII/cocomo_downloads.htm&quot;&gt;every&lt;/a&gt; &lt;a href=&quot;http://www.construx.com/Page.aspx?nid=68&quot;&gt;other&lt;/a&gt; &lt;a href=&quot;http://csse.usc.edu/tools/COCOMOII.php&quot;&gt;estimator&lt;/a&gt; &lt;a href=&quot;http://www.laatuk.com/tools/effort_estimation_tools.html&quot;&gt;does&lt;/a&gt; (as far as I know) so why am I doing it differently?&lt;/p&gt;&lt;p&gt;Because those other estimators are designed to help you write proposals and pick deadlines, while jest is designed to help you write code and meet deadlines.&lt;/p&gt;&lt;p&gt;For example, suppose you have six months to write a piece of software:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;$ jest 6
lines: 1.5E+03    (from 3.8E+02 to 6.1E+03)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tell jest you have six months, and jest tells you that you can probably write, test, debug, and document about 380 to 6,100 lines of code, with 1,500 being typical.&lt;a name=&quot;fnref2&quot;&gt;&lt;a href=&quot;#fn2&quot; class=&quot;footnoteRef&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; This will, in theory, help you budget your code and avoid a situation where you&amp;rsquo;ve written 8,000 lines of code, don&amp;rsquo;t have enough time to test it, and still haven&amp;rsquo;t produced something releasable.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m hoping this will make jest a helpful tool for people who actually write code. Even people who like the idea of estimation tend to avoid it on projects where they are personally coding. Part of the reason may be that, from a coder&amp;rsquo;s perspective, estimating time based on size just tells you what you already know: you&amp;rsquo;ve been given a feature list and a deadline that don&amp;rsquo;t match. By suggesting what you can do instead of repeating what you can&amp;rsquo;t, jest should be more of an aid and less of a drag.&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;&lt;hr /&gt;&lt;ol&gt;&lt;a name=&quot;fn1&quot;&gt;&lt;li&gt;&lt;p&gt;Jest has a bunch of other features, including more typical time-based-on-size estimates, but I&amp;rsquo;m focusing on the biggest feature that you won&amp;rsquo;t find elsewhere. Oddly enough, another feature you won&amp;rsquo;t find in other estimators is that it runs from the command line. &lt;a href=&quot;#fnref1&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1&quot;&gt;&amp;#x21a9;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;a name=&quot;fn2&quot;&gt;&lt;li&gt;&lt;p&gt;Jest uses &lt;a href=&quot;http://en.wikipedia.org/wiki/Scientific_notation&quot;&gt;E notation&lt;/a&gt; in its output, in part to avoid confusion over the number of zeros and in part to make it clearer that the numbers have been rounded to a certain number of significant figures. &lt;a href=&quot;#fnref2&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2&quot;&gt;&amp;#x21a9;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;</description>
  <comments>http://brian-jaress.livejournal.com/9382.html</comments>
  <category>jest</category>
  <lj:mood>hopeful</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/8720.html</guid>
  <pubDate>Sun, 15 Mar 2009 04:02:51 GMT</pubDate>
  <title>Making a Choice on Haskell</title>
  <link>http://brian-jaress.livejournal.com/8720.html</link>
  <description>&lt;p&gt;I&apos;ve finally decided whether I want to keep using &lt;a href=&quot;http://www.haskell.org/&quot;&gt;Haskell&lt;/a&gt;.  I&apos;ve
   updated the small program I wrote in the language and included my
   updated thoughts in the comments.  You can read them in &lt;a href=&quot;http://www2.hawaii.edu/~jaress/threadPool/0.2/threadPool.lhs.html&quot;&gt;HTML&lt;/a&gt; or
   &lt;a href=&quot;http://www2.hawaii.edu/~jaress/threadPool/0.2/threadPool.pdf&quot;&gt;PDF&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;You can also, of course, download the &lt;a href=&quot;http://hackage.haskell.org/cgi-bin/hackage-scripts/package/threadPool&quot;&gt;source code&lt;/a&gt;.
&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/8720.html</comments>
  <category>haskell</category>
  <category>threadpool</category>
  <lj:mood>satisfied</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/8484.html</guid>
  <pubDate>Mon, 19 Jan 2009 09:44:05 GMT</pubDate>
  <title>Taking a Second Look at Haskell: A Thread Pool for the Command Line</title>
  <link>http://brian-jaress.livejournal.com/8484.html</link>
  <description>&lt;p&gt;Every now and then I do something just to try it out.  I wrote a little
   program in &lt;a href=&quot;http://haskell.org&quot;&gt;Haskell&lt;/a&gt; and turned into a mini-essay using Haskell&apos;s
   &lt;a href=&quot;http://www.haskell.org/haskellwiki/Literate_programming&quot;&gt;literate programming&lt;/a&gt; support.
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;a href=&quot;http://www2.hawaii.edu/~jaress/threadPool/threadPool.pdf&quot;&gt;The PDF&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www2.hawaii.edu/~jaress/threadPool/threadPool.lhs&quot;&gt;The source code&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.gnu.org/licenses/gpl.txt&quot;&gt;The license&lt;/a&gt;
 &lt;/li&gt;
&lt;/ul&gt;</description>
  <comments>http://brian-jaress.livejournal.com/8484.html</comments>
  <lj:mood>satisfied</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/8391.html</guid>
  <pubDate>Mon, 17 Nov 2008 01:53:14 GMT</pubDate>
  <title>Defining &quot;Less Than&quot;</title>
  <link>http://brian-jaress.livejournal.com/8391.html</link>
  <description>&lt;p&gt;Sudden changes of opinion are funny.
&lt;/p&gt;
&lt;p&gt;Everyone knows that more information can change your mind, but when it
   happens all at once it&apos;s like opening a door that doesn&apos;t lead where you
   expected.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Recently, there was a &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003566.html&quot; title=&quot;It all began with a question . . .&quot;&gt;controversy&lt;/a&gt; on the &lt;a href=&quot;http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss&quot; title=&quot;Discussion of the Revised^6 Report on the Algorithmic Language Scheme&quot;&gt;r6rs-discuss&lt;/a&gt; mailing
   list about comparisons.&lt;sup&gt;&lt;a name=&quot;fnr1-116863557&quot; href=&quot;#fn1-116863557&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;  So far, everyone I&apos;ve told about
   it in person offers the same opinion--then switches when they hear the
   reasons.  The original mailing list discussion seemed to abruptly trail
   off as the initially obvious position lost its critical mass of
   supporters.
&lt;/p&gt;

&lt;h2&gt;Comparisons&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://schemers.org&quot; title=&quot;The Scheme Programming Language&quot;&gt;Scheme&lt;/a&gt; has several comparison procedures.  For example&lt;sup&gt;&lt;a name=&quot;fnr2-116863557&quot; href=&quot;#fn2-116863557&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, if
   you want to know whether &lt;code&gt;x&lt;/code&gt; is strictly less than &lt;code&gt;y&lt;/code&gt;, you can write
   &lt;code&gt;(&amp;lt; x y)&lt;/code&gt;.  That gives you &lt;code&gt;#t&lt;/code&gt; (true) if &lt;code&gt;x&lt;/code&gt; is indeed strictly less
   than &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;#f&lt;/code&gt; (false) if &lt;code&gt;x&lt;/code&gt; is greater than or equal to &lt;code&gt;y&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;You can also compare more than two numbers at a time. &lt;code&gt;(&amp;lt; 1 2 3)&lt;/code&gt; is
   true, but &lt;code&gt;(&amp;lt; 1 2 0)&lt;/code&gt; is false because two is not strictly less than
   zero.
&lt;/p&gt;
&lt;p&gt;But what about &lt;code&gt;(&amp;lt; x)&lt;/code&gt; and &lt;code&gt;(&amp;lt;)&lt;/code&gt;? How should the &lt;code&gt;&amp;lt;&lt;/code&gt; operator respond
   to one or zero arguments?
&lt;/p&gt;

&lt;h2&gt;Options&lt;/h2&gt;
&lt;p&gt;The discussion focused on two major&lt;sup&gt;&lt;a name=&quot;fnr3-116863557&quot; href=&quot;#fn3-116863557&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; options:
&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.r6rs.org/&quot; title=&quot;R6RS&quot;&gt;current standard&lt;/a&gt; says that a comparison applied to fewer than
   two arguments produces an error.  Supporters of keeping it that way
   &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003625.html&quot;&gt;pointed out&lt;/a&gt; that you are not actually making a comparison unless you
   have two things.
&lt;/p&gt;
&lt;p&gt;The other option is for comparisons to produce &lt;code&gt;#t&lt;/code&gt;, representing true,
   when given fewer than two arguments.
&lt;/p&gt;

&lt;h2&gt;Why&lt;/h2&gt;
&lt;p&gt;Why would you want that?
&lt;/p&gt;
&lt;p&gt;Consider this: We already allow more than two arguments, so the
   purpose of a &quot;comparison operator&quot; is &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003575.html&quot;&gt;not to compare two things&lt;/a&gt;.
   It can take up to two comparisons to decide whether &lt;code&gt;(&amp;lt; x y z)&lt;/code&gt; is true
   or false, let alone &lt;code&gt;(&amp;lt; x y z a b)&lt;/code&gt;.  The maximum number of comparisons
   we are making grows and shrinks with the number of arguments, so why not
   let them both shrink to zero?
&lt;/p&gt;
&lt;p&gt;One &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003581.html&quot;&gt;way&lt;/a&gt; to think of the &lt;code&gt;&amp;lt;&lt;/code&gt; operator is that it checks
   whether the sequence of arguments is &lt;a href=&quot;http://planetmath.org/encyclopedia/MonotonicallyIncreasing.html&quot; title=&quot;Definition on PlanetMath&quot;&gt;strictly increasing&lt;/a&gt;.  You can
   define that using a rule: A sequence is increasing if it has no
   non-increasing pairs.  Under that definition, sequences of one or zero
   elements are strictly increasing.  (They are also strictly decreasing,
   and a whole bunch of other things, under analogous definitions.)
&lt;/p&gt;
&lt;p&gt;Practically speaking, that&apos;s what we want.
&lt;/p&gt;
&lt;p&gt;It&apos;s easier to think of the operator as always working on single list of
   numbers, with the list being allowed to vary in length.
   There &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003661.html&quot;&gt;are&lt;/a&gt; &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003673.html&quot;&gt;ways&lt;/a&gt; of invoking the operator that make this
   explicit, by giving it arguments from a list whose contents (and length)
   are determined after the program is written.
&lt;/p&gt;
&lt;p&gt;Also, we&apos;ll usually already need separate code to detect that the list
   is out of elements because we generally process it one or a few elements
   at a time, and we need to detect that we are finished.  When we ask
   whether the list is &lt;code&gt;&amp;lt;&lt;/code&gt;, we generally want to know whether we can count
   on the rule for strictly increasing sequences.  Letting &lt;code&gt;(&amp;lt; x)&lt;/code&gt; and
   &lt;code&gt;(&amp;lt;)&lt;/code&gt; be true makes it easier, in the more common cases, to separate
   &quot;nothing needs to be done&quot; from &quot;you can&apos;t do it that way.&quot;
&lt;/p&gt;

&lt;h2&gt;Moral and Code&lt;/h2&gt;
&lt;p&gt;So far, everyone I&apos;ve asked in person has started out favoring &lt;code&gt;error&lt;/code&gt;
   and switched to &lt;code&gt;#t&lt;/code&gt; after hearing the reasons.  This being the
   Internet, I&apos;m sure a few die-hards will continue to support &lt;code&gt;error&lt;/code&gt; or
   &lt;code&gt;#f&lt;/code&gt; or who-knows-what, but I expect that most people who read this will
   go through the same switch, unless they start off favoring &lt;code&gt;#t&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;If you switched, laugh.  It&apos;s funny, and you&apos;re not the only one
   who walked into a closet&lt;sup&gt;&lt;a name=&quot;fnr4-116863557&quot; href=&quot;#fn4-116863557&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;
&lt;p&gt;If you&apos;re using an &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2008-October/003712.html&quot;&gt;actual&lt;/a&gt; Scheme, here&apos;s a procedure that turns a
   two-argument comparison (whether or not it also takes other numbers of
   arguments) into a zero-or-more-argument comparison:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define (generalize two-comp?)
  (define (gen-comp? . args)
    (if (or (null? args) (null? (cdr args)))
      #t
      (and (two-comp? (car args) (cadr args))
           (apply gen-comp? (cdr args)))))
  gen-comp?)
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-116863557&quot;&gt; &lt;/a&gt;&lt;p&gt;I was too wrapped up in other things to follow it as it
   happened, but the effect on my inbox was impressive.  I don&apos;t
   subscribe to any high-volume lists, so it&apos;s very noticeable when one
   of the low-volume lists picks up.&lt;a href=&quot;#fnr1-116863557&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-116863557&quot;&gt; &lt;/a&gt;&lt;p&gt;The issue applies to all the comparison procedures, but almost
   everyone seemed to use &lt;code&gt;&amp;lt;&lt;/code&gt; in their examples without any prior
   agreement.&lt;a href=&quot;#fnr2-116863557&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-116863557&quot;&gt; &lt;/a&gt;&lt;p&gt;Others were suggested, of course.  Someone wanted a false
   value, and a couple people supported restricting it to exactly two
   arguments (producing an error on three or more a well as one or
   zero).  Feel free to make your own suggestions in the comments.&lt;a href=&quot;#fnr3-116863557&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn4-116863557&quot;&gt; &lt;/a&gt;&lt;p&gt;I&apos;ve actually made the classic mistake of &quot;exiting&quot; into a
   closet a few times, including the janitors&apos; closet at a public
   restroom.&lt;a href=&quot;#fnr4-116863557&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/8391.html</comments>
  <category>humor</category>
  <category>r6rs</category>
  <category>scheme</category>
  <category>programming</category>
  <lj:mood>amused</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/8064.html</guid>
  <pubDate>Thu, 17 Jul 2008 07:55:57 GMT</pubDate>
  <title>A Trivial Un-Object System for Scheme</title>
  <link>http://brian-jaress.livejournal.com/8064.html</link>
  <description>&lt;p&gt;You could say I&apos;m a casual user of &lt;a href=&quot;http://schemers.org/&quot; title=&quot;The Scheme Programming Language&quot;&gt;Scheme&lt;/a&gt;.  At least, I&apos;ve mostly
   used it for prototyping and system scripts.  But I decided, to use it
   and to learn from it, that I&apos;d make something a little different: an
   un-object system.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;What I Wanted&lt;/h2&gt;
&lt;p&gt;There are a lot of &lt;a href=&quot;http://www.cs.indiana.edu/scheme-repository/code.oop.html&quot;&gt;object systems&lt;/a&gt; for Scheme, but they mostly help
   you create objects.  I wanted an easy way to retrofit existing
   structures with &lt;a href=&quot;http://en.wikipedia.org/wiki/Encapsulation_%28classes_-_computers%29#Uses&quot;&gt;encapsulation&lt;/a&gt; and &lt;a href=&quot;http://c2.com/cgi/wiki?LateBinding&quot;&gt;late binding&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Some might say that late binding plus encapsulation is
   &lt;a href=&quot;http://c2.com/cgi/wiki?DefinitionsForOo&quot;&gt;object oriented&lt;/a&gt;, but pretty much everyone expects more from anything
   claiming to be OO.  Putting that aside, there&apos;s an assumption that when
   you define an object using an object system, your main job is to write
   the internals of the object.  That&apos;s the opposite of what I wanted.
&lt;/p&gt;
&lt;p&gt;The typical way of creating a reusable data structure in Scheme is to
   represent it using nested lists and write a bunch of procedures that
   operate on that representation.  Then those procedures can be used like
   so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define tasks (make-queue))
(queue-add! tasks &apos;clean-garage)
(queue-get! tasks)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;code&gt;tasks&lt;/code&gt; is really some kind of list structure storing your data.
   You might add several tasks to the queue and have &lt;code&gt;tasks =&amp;gt;
&apos;((clean-garage paint-roof) (sweep-steps))&lt;/code&gt;.  Even libraries that &lt;a href=&quot;http://swissnet.ai.mit.edu/~jaffer/slib_3.html#SEC44&quot;&gt;come
with&lt;/a&gt; an object system will often also &lt;a href=&quot;http://swissnet.ai.mit.edu/~jaffer/slib_7.html#SEC212&quot;&gt;come with&lt;/a&gt;
   such non-object data structures.
&lt;/p&gt;
&lt;p&gt;Encapsulation and late binding are, I think, the main advantages over
   the typical way for the &lt;em&gt;consumer&lt;/em&gt; of the objects. &lt;a href=&quot;http://en.wikipedia.org/wiki/Inheritance_%28computer_science%29&quot;&gt;Inheritance&lt;/a&gt; is
   mostly a convenience for the creator (except for its late binding aspect).  So I
   wanted an easy way to add encapsulation and late binding to a typical
   data structure.
&lt;/p&gt;

&lt;h2&gt;How to Use It&lt;/h2&gt;
&lt;p&gt;To set up the encapsulation, you use the &lt;code&gt;hide&lt;/code&gt; macro.  Like so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define make-hidden-queue
 (hide
  (queue make-queue)
  (unwrapped
   (add! queue-add!)
   (get! queue-get!))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The result is a procedure that works like &lt;code&gt;make-queue&lt;/code&gt;, except it makes an
   encapsulated queue.  Then you can do:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define tasks (make-hidden-queue))

 (let-access (add! get!)
  (add! tasks &apos;clean-garage)
  (get! tasks))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;let-access&lt;/code&gt; macro sets up some access procedures.  The procedures
   have late binding, so you could also do:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define make-bag
 (hide
  (bag make-tree-multiset)
  (unwrapped
   (add! tree-multiset-add!)
   (get! tree-multiset-extract-any!))))

(define other-tasks (make-bag))

(let-access (add! get!)
 (add! tasks &apos;clean-garage)
 (add! other-tasks (get! tasks))
 (get! other-tasks))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are a couple things that might not be obvious about the queue and
   bag examples.  The part right near the beginning that says simply &lt;code&gt;bag&lt;/code&gt;
   or &lt;code&gt;queue&lt;/code&gt; is just a label.  It&apos;s included in the error message if you
   try to late-bind something that isn&apos;t listed in &lt;code&gt;hide&lt;/code&gt;.  The &lt;code&gt;unwrapped&lt;/code&gt;
   means that the procedures do not return another data structure of the
   same type.
&lt;/p&gt;
&lt;p&gt;Here&apos;s a toy example that has both wrapped and unwrapped procedures:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(hide
 (immutable-stack list)
 (unwrapped
  (peek car)
  (size length))
 (wrapped
  (push (lambda (stack item) (cons item stack)))
  (pop cdr)))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is an immutable stack.  Unlike a regular stack, it&apos;s pushed and
   popped by creating a new stack with one more or one fewer items, leaving
   the original stack intact.  There&apos;s no practical way to make the items
   themselves immutable&lt;sup&gt;&lt;a name=&quot;fnr1-305835567&quot; href=&quot;#fn1-305835567&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, but the structure of the stack itself is
   never changed.
&lt;/p&gt;
&lt;p&gt;On the inside, this toy is implemented as a list.  The &lt;code&gt;wrapped&lt;/code&gt;
   procedures each take a naked stack-as-list as their first argument and
   return another.  The &lt;code&gt;hide&lt;/code&gt; macro takes care of exposing the input list
   and wrapping up the output list, just as it wraps the output of
   &lt;code&gt;make-queue&lt;/code&gt;, &lt;code&gt;make-tree-multiset&lt;/code&gt;, or in this case &lt;code&gt;list&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;unwrapped&lt;/code&gt; procedures still take a naked structure as their first
   argument, but their result is not wrapped by &lt;code&gt;hide&lt;/code&gt;.
&lt;/p&gt;

&lt;h2&gt;How it Works&lt;/h2&gt;
&lt;p&gt;After all that explaining, the implementation is stupidly simple.  In
   fact, it&apos;s the same &lt;a href=&quot;http://prael.wordpress.com/2008/06/28/trivial-single-dispatch-oop-with-r5rs-closures/&quot;&gt;closure-based&lt;/a&gt; &lt;a href=&quot;http://c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent&quot;&gt;idea&lt;/a&gt; that everyone
   mentions when they talk about building an object system.  If I&apos;ve
   contributed anything new (and I likely have not) it&apos;s the purpose of
   wrapping existing structures.
&lt;/p&gt;
&lt;p&gt;The procedures created by &lt;code&gt;let-access&lt;/code&gt; just pass the appropriate symbol
   to their first argument, then apply that result to the remaining
   arguments:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define-syntax let-access
 ;Create a lexical scope in which certain names are bound to
 ;interface procedures, e.g.
 ;(let-access (add empty?) (if (empty? x) (add x val)))
 (syntax-rules ()
  ((let-access (symbol ...) body ...)
   (let ((symbol (lambda (x . args) (apply (x (quote symbol)) args))) ...)
    body ...))))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also make the access procedures one at a time:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define (make-accessor symbol)
 ;Create an accessor procedure.
 ;Useful when the symbol won&apos;t be known until runtime or the name
 ;is taken by an existing procedure
 (lambda (x . args) (apply (x symbol) args)))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, you can also do it &quot;by hand&quot; with something like &lt;code&gt;((tasks
&apos;add!) &apos;clean-garage)&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;hide&lt;/code&gt; macro is a little less trivial because the &lt;code&gt;wrapped&lt;/code&gt; and
   &lt;code&gt;unwrapped&lt;/code&gt; sections both needed to be optional, and I wanted to allow
   multiple sections of each type in any order.&lt;sup&gt;&lt;a name=&quot;fnr2-305835567&quot; href=&quot;#fn2-305835567&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(define-syntax hide
 ;Encapsulate a set of procedures over a &quot;naked&quot; data structure.
 ;The first subform is (interface-name constructor), and after that
 ;you can have any number of (type (name naked-accessor) ...) where the
 ;type is wrapped or unwrapped, e.g.
 ;(define make-heap (hide
 ; (heap make-reverse-garfinkle-heap)
 ; (unwrapped
 ;  (empty? rgh-empty?)
 ;  (insert! rgh-insert!)
 ;  (next! rgh-extract-next!))
 ; (wrapped (copy rgh-make-copy))))
 (syntax-rules (unwrapped wrapped)
  ((hide (interface-name constructor) subform ...)
   ;create wrapper that turns naked structure into encapsulated
   ;structure
   (letrec ((wrapper
    (lambda (naked)
     (lambda (symbol)
       (hide &quot;subforms&quot;
        (interface-name wrapper naked symbol) ;a.k.a. metadata
        subform ...)))))
    ;use the wrapper to return a modified constructor
    (lambda args (wrapper (apply constructor args)))))

  ((hide &quot;subforms&quot; metadata subform rest ...)
   ;recurse on subforms, passing each to the type-group processing
   (hide &quot;type-group&quot; metadata subform
    (hide &quot;subforms&quot; metadata rest ...)))

  ((hide &quot;type-group&quot; (interface-name wrapper naked symbol)
                      (type (name proc) ...)
                      subforms)
   ;each type-group becomes a case switch with the remaining subforms
   ;in the else clause
   (case symbol (&apos;name (hide &quot;procedure&quot;
                        (interface-name wrapper naked symbol)
                        type proc)) ...
    (else subforms)))

  ((hide &quot;subforms&quot; (interface-name wrapper naked symbol))
    ;base case of recursion on subforms, fill in the right side of the
    ;final else clause
    (error &quot;unknown interface symbol, no such accessor&quot; symbol &apos;interface-name))

  ;The right sides of the case tests should be procedures that take a
  ;naked structure as the first argument.  The type (wrapped vs unwrapped)
  ;controlls whether the output of the provided procedure is wrapped in
  ;the same encapsulation before being returned.
  ((hide &quot;procedure&quot; (interface-name wrapper naked symbol)
                               wrapped proc)
   (lambda args (wrapper (apply proc (cons naked args)))))
  ((hide &quot;procedure&quot; (interface-name wrapper naked symbol)
                               unwrapped proc)
   (lambda args (apply proc (cons naked args))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-305835567&quot;&gt; &lt;/a&gt;&lt;p&gt;None as far as I know, anyway, unless you count switching to
   another language.&lt;a href=&quot;#fnr1-305835567&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-305835567&quot;&gt; &lt;/a&gt;&lt;p&gt;And because I&apos;m using &lt;code&gt;syntax-rules&lt;/code&gt;, which is like untying a
   knot with a toothpick.&lt;a href=&quot;#fnr2-305835567&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/8064.html</comments>
  <lj:mood>mellow</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/7706.html</guid>
  <pubDate>Fri, 20 Jun 2008 11:27:47 GMT</pubDate>
  <title>How It Works vs How to Work With It</title>
  <link>http://brian-jaress.livejournal.com/7706.html</link>
  <description>&lt;p&gt;There was, by my modest standards, a huge response to my &lt;a href=&quot;http://brian-jaress.livejournal.com/7595.html&quot;&gt;last post&lt;/a&gt;.  I
   noticed two things about the comments here and &lt;a href=&quot;http://www.reddit.com/r/programming/info/6jx98/comments/&quot;&gt;on reddit&lt;/a&gt;:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     My guess about what &lt;a href=&quot;http://gcc.gnu.org&quot;&gt;gcc&lt;/a&gt; does when you declare a return type but don&apos;t
   return anything &lt;a href=&quot;http://brian-jaress.livejournal.com/7595.html?thread=10411#t10411&quot;&gt;was&lt;/a&gt; &lt;a href=&quot;http://www.reddit.com/r/programming/info/6jx98/comments/c0427qk&quot;&gt;wrong&lt;/a&gt;.
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://brian-jaress.livejournal.com/7595.html?thread=12971#t12971&quot;&gt;Some&lt;/a&gt; &lt;a href=&quot;http://www.reddit.com/r/programming/info/6jx98/comments/c042fv8&quot;&gt;readers&lt;/a&gt; thought I was saying that UH
   doesn&apos;t teach undergraduates anything
   about &lt;a href=&quot;http://en.wikipedia.org/wiki/C_%28programming_language%29&quot;&gt;C&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/Pointer_%28computing%29&quot;&gt;pointers&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/Assembly_language&quot;&gt;assembly&lt;/a&gt;.
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Number one wasn&apos;t much of a surprise, but number two had me scratching
   my head.  I decided to do another post explaining the difference between
   what I meant and what came across to some readers.
&lt;/p&gt;
&lt;p&gt;The short version is in the title: There&apos;s a difference between knowing
   how something works and knowing how you should work with it.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Undergraduate C at UH&lt;/h2&gt;
&lt;p&gt;UH does teach undergrads about C, though I don&apos;t claim to have learned
   everything they were teaching.  When I said I had used C but not
   heavily, I was mostly referring to UH.
&lt;/p&gt;
&lt;p&gt;There&apos;s an undergraduate class that covers assembly, C, and &lt;a href=&quot;http://en.wikipedia.org/wiki/C%2B%2B&quot;&gt;C++&lt;/a&gt;.  It&apos;s
   about a third of a semester each, but it tries to build each topic on the
   previous one.  For example, using assembly to help explain C pointers.
&lt;/p&gt;
&lt;p&gt;The focus is on low-level concepts.  What&apos;s a pointer, and how does it
   work?  How are &lt;a href=&quot;http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29&quot;&gt;references&lt;/a&gt; different?  How do all the bit-twiddling
   operators work?  Casting pointers?  That sort of thing.  I can&apos;t
   remember if it was half the final or all of it, but we had to trace a
   wad of obfuscated C++ and write out the output&lt;sup&gt;&lt;a name=&quot;fnr1-132323364&quot; href=&quot;#fn1-132323364&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;
&lt;p&gt;In fact, the class was probably designed by someone who&apos;s appalled at
   the thought of programmers not knowing how low-level code works.
&lt;/p&gt;

&lt;h2&gt;So what else do you need?&lt;/h2&gt;
&lt;p&gt;OK, I basically know how a pointer works.  On that undergrad final I
   showed that I can sit down and trace out the path of the bullet as it
   enters my foot.  But how do I avoid shooting myself there in the first
   place?
&lt;/p&gt;
&lt;p&gt;One of the professors has a technique of always allocating global,
   fixed-sized arrays and using indexes into them instead of pointers.  He
   knows how pointers work.  In fact he&apos;s an expert on compilers, x86
   machine code, and DOS object files&lt;sup&gt;&lt;a name=&quot;fnr2-132323364&quot; href=&quot;#fn2-132323364&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.  He just looked at C pointers
   and said, &quot;Not worth it.&quot; He made an informed decision about how to work
   with the language.
&lt;/p&gt;
&lt;p&gt;I made a different decision (and maybe you should take his advice
   instead of mine).  I still use pointers in C because I felt that going so
   far out of the way to avoid them was cutting against the grain of the
   language and making it hard, for me at least, to build things on top of
   it.
&lt;/p&gt;
&lt;p&gt;Instead, I found other ways to cut down my foot-shooting.  I didn&apos;t need
   them when I was writing tiny programs to learn how C works.  I did need
   them to work with C and create a not-so-tiny program that actually did
   something significant.
&lt;/p&gt;

&lt;h2&gt;Controversy&lt;/h2&gt;
&lt;p&gt;I should have been clearer about that.  There&apos;s a debate over whether
   you should know how C works even if you aren&apos;t going to use C, and I
   accidentally got too close to it.&lt;sup&gt;&lt;a name=&quot;fnr3-132323364&quot; href=&quot;#fn3-132323364&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;Knowing how to work with C is less controversial.  I think pretty much
   everyone would agree that you need it if you&apos;re using C for something
   serious and otherwise you don&apos;t&lt;sup&gt;&lt;a name=&quot;fnr4-132323364&quot; href=&quot;#fn4-132323364&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.  Of course, working with C will
   involve applying general concepts like encapsulation, but I doubt that&apos;s
   what people are referring to when they get disgusted that not everyone
   &quot;knows C.&quot;
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-132323364&quot;&gt; &lt;/a&gt;&lt;p&gt;The correct answer wasn&apos;t anything sensible or following a
   pattern, either.  It was some arbitrary junk like &lt;code&gt;frog\n\n4 ;\n=&lt;/code&gt;.&lt;a href=&quot;#fnr1-132323364&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-132323364&quot;&gt; &lt;/a&gt;&lt;p&gt;If you are feeling macho because you&apos;re comfortable with
   pointers and assembly, I invite you to create a program by writing
   object files in a hex editor.&lt;a href=&quot;#fnr2-132323364&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-132323364&quot;&gt; &lt;/a&gt;&lt;p&gt;But it&apos;s probably a big reason so (relatively) many people
   paid attention.&lt;a href=&quot;#fnr3-132323364&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn4-132323364&quot;&gt; &lt;/a&gt;&lt;p&gt;Then there&apos;s another debate over whether you should be using C
   for something serious.  Such is life.&lt;a href=&quot;#fnr4-132323364&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/7706.html</comments>
  <lj:mood>restless</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/7595.html</guid>
  <pubDate>Sun, 18 May 2008 08:33:50 GMT</pubDate>
  <title>Two Semesters of C</title>
  <link>http://brian-jaress.livejournal.com/7595.html</link>
  <description>&lt;p&gt;When I was an undergraduate at UH, they made a big deal about &lt;a href=&quot;http://java.sun.com/&quot;&gt;Java&lt;/a&gt;
   being the default language of the department.  Unless the class had to
   have some other language, we used Java.
&lt;/p&gt;
&lt;p&gt;But so far I&apos;ve only had one graduate class with Java.  The rest have
   let me use whatever I want&lt;sup&gt;&lt;a name=&quot;fnr1-546060980&quot; href=&quot;#fn1-546060980&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, or told me to use &lt;a href=&quot;http://en.wikipedia.org/wiki/C_%28programming_language%29&quot;&gt;C&lt;/a&gt;.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Lessons Learned&lt;/h2&gt;
&lt;p&gt;I&apos;d used it before, but I&apos;d never used it very heavily.  Wrestling with
   the language for a couple of semesters made me realize a few things.
   I&apos;m not trying to criticize C here.  Every language has pitfalls, and
   this is really a list of things I wish I had been more aware of.
&lt;/p&gt;

&lt;h3&gt;Valgrind&lt;/h3&gt;
&lt;p&gt;The good things you&apos;ve heard about &lt;a href=&quot;http://valgrind.org/&quot;&gt;Valgrind&lt;/a&gt; are true.  It found
   bugs I had no clue existed.  Once I understood and fixed them, I started
   using Valgrind all the time.  Be sure to use it responsibly&lt;sup&gt;&lt;a name=&quot;fnr2-546060980&quot; href=&quot;#fn2-546060980&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;h3&gt;-Wall&lt;/h3&gt;
&lt;p&gt;Everyone says to compile with &lt;code&gt;-Wall&lt;/code&gt;, and they&apos;re right.  But they
   rarely tell you the real reason you need it.
&lt;/p&gt;
&lt;p&gt;Here&apos;s a fragment of code that &lt;a href=&quot;http://gcc.gnu.org&quot;&gt;gcc&lt;/a&gt; compiles silently without
   &lt;code&gt;-Wall&lt;/code&gt;, assuming it has the supporting code it needs:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;buffer *
new_buffer ()
{
  buffer *buf = malloc (sizeof (buffer));
  buf-&amp;gt;capacity = 100;
  buf-&amp;gt;used = 0;
  buf-&amp;gt;bytes = malloc (buf-&amp;gt;capacity);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you compile it with &lt;code&gt;-Wall&lt;/code&gt;, it&apos;ll say &lt;code&gt;warning: control reaches end of
non-void function&lt;/code&gt;.  That&apos;s because the function is declared as
   returning a &lt;code&gt;buffer *&lt;/code&gt;, but it has no return statement.  You can fix it
   by adding &lt;code&gt;return buf;&lt;/code&gt; right before the closing curly brace.
&lt;/p&gt;
&lt;p&gt;There are languages where you don&apos;t declare a return type at all -- you
   either return something or you don&apos;t, and if you forget to do it then it
   won&apos;t happen.  That&apos;s not surprising.  But if you declare ahead of time
   that you will return a &lt;code&gt;buffer *&lt;/code&gt;, you sort of expect the compiler to
   complain if you don&apos;t actually do it.
&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;-Wall&lt;/code&gt; because it adds the checks you probably assumed you
   already had.  A lot of things suddenly start doing what they look like
   they&apos;re supposed to do.
&lt;/p&gt;

&lt;h3&gt;C Turns Almost Every Error into a Memory Error&lt;/h3&gt;
&lt;p&gt;If you ran that buggy buffer code, you would have a memory leak.  You
   would also probably have a &lt;a href=&quot;http://en.wikipedia.org/wiki/Segmentation_fault&quot;&gt;segfault&lt;/a&gt; when you tried to use the buffer.
&lt;/p&gt;
&lt;p&gt;What happens, as far as I can tell, is that if you call the function you
   get the value of the last expression.  In this case, &lt;code&gt;buf-&amp;gt;bytes&lt;/code&gt;
   coerced into a &lt;code&gt;buffer *&lt;/code&gt;.  So you think you have a buffer, but you
   really have 100 bytes.  The capacity and number of bytes used are now
   inaccessible.  When you think you&apos;re accessing the capacity or the
   number of bytes used, you&apos;re actually looking at two values in the 100
   bytes.  When you think you&apos;re looking in the 100 bytes . . . you&apos;re
   probably segfaulting.
&lt;/p&gt;
&lt;p&gt;When I make an equivalent mistake in most other languages, I get a
   message telling me I forgot to return something or that I&apos;m trying to
   check the capacity of something I don&apos;t have.  In C it&apos;s a memory error.
&lt;/p&gt;
&lt;p&gt;In C, almost everything is a memory error&lt;sup&gt;&lt;a name=&quot;fnr3-546060980&quot; href=&quot;#fn3-546060980&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.  I&apos;m actually happy
   to see wrong output because it&apos;s not a segfault.  Thank goodness we have
   Valgrind.
&lt;/p&gt;

&lt;h3&gt;Software Engineering&lt;/h3&gt;
&lt;p&gt;Software engineering was quite helpful.  Especially helpful were
   &lt;a href=&quot;http://en.wikipedia.org/wiki/Abstract_data_type&quot;&gt;ADT&lt;/a&gt;s, &lt;a href=&quot;http://en.wikipedia.org/wiki/Information_hiding#Uses&quot;&gt;encapsulation&lt;/a&gt;, &lt;a href=&quot;http://codeulate.com/?p=13&quot;&gt;unit tests&lt;/a&gt;, and &lt;a href=&quot;http://www.c2.com/cgi/wiki?WhatAreAssertions&quot;&gt;assertions&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;C actually comes with assertions in a header called &lt;code&gt;assert.h&lt;/code&gt;.  I
   highly recommend it (to people already using C).  C programs tend to be
   full of assertion opportunities.
&lt;/p&gt;
&lt;p&gt;For the unit tests, I just had a test module with its own &lt;code&gt;main&lt;/code&gt;
   function and compiled two different programs (through two different
   &lt;a href=&quot;http://www.gnu.org/software/make/&quot;&gt;make&lt;/a&gt; targets) one using the real &lt;code&gt;main&lt;/code&gt; and one using the test.  I&apos;m
   not sure if that&apos;s the typical way.
&lt;/p&gt;

&lt;h2&gt;Next Semester&lt;/h2&gt;
&lt;p&gt;More C?  I don&apos;t know.  It&apos;s sometimes hard to tell whether a class is
   going to have any coding at all.
&lt;/p&gt;
&lt;p&gt;But it&apos;s not a bad little language.  If you&apos;re a real C programmer, any
   helpful pointers are welcome.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-546060980&quot;&gt; &lt;/a&gt;&lt;p&gt;Usually &lt;a href=&quot;http://www.python.org&quot;&gt;Python&lt;/a&gt;.  I spent a long time thinking I didn&apos;t
   have a favorite language, and then one day I realized I did and it was
   Python.&lt;a href=&quot;#fnr1-546060980&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-546060980&quot;&gt; &lt;/a&gt;&lt;p&gt;This should go without saying but apparently
   &lt;a href=&quot;http://reddit.com/r/programming/info/6j7a9/comments/&quot;&gt;doesn&apos;t&lt;/a&gt;: Only fix bugs detected by Valgrind, or in any other
   way, after you have confirmed the bug and &lt;a href=&quot;http://www.links.org/?p=327&quot;&gt;understand&lt;/a&gt;
   &lt;a href=&quot;http://www.links.org/?p=328&quot;&gt;it&lt;/a&gt;. You could easily &lt;a href=&quot;http://lwn.net/Articles/281901/rss&quot;&gt;screw&lt;/a&gt; &lt;a href=&quot;http://metasploit.com/users/hdm/tools/debian-openssl/&quot;&gt;things&lt;/a&gt;
   &lt;a href=&quot;http://xkcd.net/424/&quot;&gt;up&lt;/a&gt;.&lt;a href=&quot;#fnr2-546060980&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-546060980&quot;&gt; &lt;/a&gt;&lt;p&gt;On the flip side, I&apos;ve had almost no trouble with &lt;code&gt;malloc&lt;/code&gt; and
   &lt;code&gt;free&lt;/code&gt;.  The problem (for me) is not manual memory management, it&apos;s
   the memory model.&lt;a href=&quot;#fnr3-546060980&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/7595.html</comments>
  <category>c</category>
  <category>uh</category>
  <category>programming</category>
  <lj:mood>thankful</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>22</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/7301.html</guid>
  <pubDate>Sat, 05 Apr 2008 01:01:30 GMT</pubDate>
  <title>Website Concepts</title>
  <link>http://brian-jaress.livejournal.com/7301.html</link>
  <description>&lt;p&gt;When a nontechnical friend asks for technical advice because they have a
   concept for a website, should I warn them about nontechnical
   difficulties?
&lt;/p&gt;
&lt;p&gt;By &quot;concept,&quot; I mean a very short description of what they want to
   create.  &quot;YouTube for orthodontists&quot; is a concept.  &quot;Like Google, but
   you can vote on the links&quot; is a concept.&lt;sup&gt;&lt;a name=&quot;fnr1-178149201&quot; href=&quot;#fn1-178149201&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;When they come to me, I explain the technical side as best I can and try
   to avoid saying what I think of the concept (though sometimes it slips
   out) but I&apos;m left wondering if I should have explained that the
   particular concept doesn&apos;t make much difference.  You need to have a
   concept or there will be no purpose to the site, but it doesn&apos;t make all
   that much difference what particular concept you have.&lt;sup&gt;&lt;a name=&quot;fnr2-178149201&quot; href=&quot;#fn2-178149201&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;I&apos;m not sure what makes a site successful, but I&apos;m pretty sure the
   concept plays a very small role.  I call that a &quot;nontechnical
   difficulty&quot; because people tend to think the concept is going to take
   care of nontechnical things that it won&apos;t.  In particular, they think
   the concept will make people like and use the site.&lt;sup&gt;&lt;a name=&quot;fnr3-178149201&quot; href=&quot;#fn3-178149201&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;Of course, people don&apos;t want to hear that it isn&apos;t so.  They&apos;re asking
   me for technical advice.  If I say anything about the concept, or the
   overall chance of success, they&apos;re expecting enthusiasm and support.
&lt;/p&gt;
&lt;p&gt;I&apos;m not an expert on concepts or success, either.  Anything I say is
   likely to be brushed off.  But I do have some familiarity with the
   industry, and I think they ought to hear it from someone.
&lt;/p&gt;
&lt;p&gt;So, what to say?  For now, I&apos;ll continue to say little or nothing about
   it.  Just answer their technical questions and let them handle the rest.
   But I&apos;ll have this up for people to read, and if anyone asks about the
   importance of a website concept or the chances of success, I&apos;ll tell
   them what I think.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-178149201&quot;&gt; &lt;/a&gt;&lt;p&gt;I&apos;m not sure when we first started using &quot;concept&quot; this way
   when talking about websites, but I&apos;ve seen it tossed around quite a bit.
   I think we got it from the movie industry.&lt;a href=&quot;#fnr1-178149201&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-178149201&quot;&gt; &lt;/a&gt;&lt;p&gt;Unless, of course, the concept is truly terrible.  &quot;YouTube for
   the comatose&quot; is a stinker.&lt;a href=&quot;#fnr2-178149201&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-178149201&quot;&gt; &lt;/a&gt;&lt;p&gt;It&apos;s actually sort of true that a movie can be successful
   because of its concept.  Variations on &quot;Two dumb guys get in
   trouble&quot; work pretty well, and my brother liked &quot;Snakes on a Plane.&quot;
&lt;/p&gt;
&lt;p&gt;Websites aren&apos;t like that.  They&apos;re more like restaurants.  A
   restaurant isn&apos;t going to succeed or fail merely because the food is
   Italian.&lt;a href=&quot;#fnr3-178149201&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/7301.html</comments>
  <category>web</category>
  <category>life</category>
  <category>advice</category>
  <lj:mood>discontent</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/6967.html</guid>
  <pubDate>Wed, 20 Feb 2008 11:11:30 GMT</pubDate>
  <title>Caucus</title>
  <link>http://brian-jaress.livejournal.com/6967.html</link>
  <description>&lt;p&gt;I went to the Democratic caucus tonight.
&lt;/p&gt;
&lt;p&gt;I&apos;m glad I went.  It was a lot of fun, and it&apos;s probably the only time a
   national race will be close enough for long enough that Hawaii matters.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;I went with my mom, dad, and brother, who all live a couple of blocks
   from me but turned out to be in a different precinct (though we still
   had the same caucus site).
&lt;/p&gt;
&lt;p&gt;It was very crowded.  We were lucky to even find a parking space.  The
   roadsides were full for blocks, and I saw a lot of cars parked in
   illegal and weird places.  After we&apos;d spent a few minutes in line
   and moved a few car lengths, my mom tapped me on the shoulder and
   pointed to the line behind us.  What had been a long walk from the
   car was filling up with people.
&lt;/p&gt;
&lt;p&gt;There were people walking up and down the line giving out forms to
   register with the party or register to vote.  They had run out of forms
   and printed more on several different sizes and colors of paper.
&lt;/p&gt;
&lt;p&gt;Amazingly, we ran into someone we know who lives near the site.  He was
   surprised that people from our area were caucusing there.
&lt;/p&gt;
&lt;p&gt;My dad also met someone he knew while going up to check that we were in
   the right line.
&lt;/p&gt;
&lt;p&gt;&amp;quot;A guy just came up to me and said he knew me but couldn&apos;t remember my
   name.&amp;quot;
&lt;/p&gt;
&lt;p&gt;&amp;quot;What&apos;s &lt;em&gt;his&lt;/em&gt; name?&amp;quot;
&lt;/p&gt;
&lt;p&gt;&amp;quot;I don&apos;t remember.&amp;quot;
&lt;/p&gt;
&lt;p&gt;While I was standing in the part of the line that doubled back twice in
   the parking lot, they announced that they were out of preprinted
   ballots.  I ended up voting by writing a candidate&apos;s name on a post-it
   that advertised Celebrex.
&lt;/p&gt;
&lt;p&gt;The caucus was held in an elementary school cafeteria/theater, though
   some precincts moved outside to the basketball courts.  Right by the
   door was a desk for people to register with the party, register to vote,
   and find out their precinct.&lt;sup&gt;&lt;a name=&quot;fnr1-386446129&quot; href=&quot;#fn1-386446129&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;Around the cafeteria there were tables with signs that had precinct
   numbers on them.  You would go to the table for your precinct and sign
   in with your name, address, and phone number.&lt;sup&gt;&lt;a name=&quot;fnr2-386446129&quot; href=&quot;#fn2-386446129&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;As people were signing in, the &amp;quot;precinct leader&amp;quot; for each precinct was
   calling out names from full sign-sheets.  When your name was called, you
   raised your hand and they gave you a ballot.  Then you filled it out and
   gave it back.
&lt;/p&gt;
&lt;p&gt;&amp;quot;Please do not give people more than one ballot,&amp;quot; the woman on the stage
   announced.  &amp;quot;We&apos;re already getting complaints about this, and I don&apos;t
   know what to do.&amp;quot;
&lt;/p&gt;
&lt;p&gt;I managed to get a seat at one of the tables while I was waiting for my
   name to be called.  Unfortunately, a lady standing right by my ear was
   loudly critical of everything the precinct leader did.
&lt;/p&gt;
&lt;p&gt;&amp;quot;Where&apos;s the sheet I signed?&amp;quot; she shouted.  &amp;quot;You took one of the sign-in
   sheets and put it in that stack of other papers!  Make sure he knows to
   check the back of the sheet.  Don&apos;t stop calling names to answer
   questions!&amp;quot;
&lt;/p&gt;
&lt;p&gt;Some of what she said was helpful, and some was not.  All was loud.
&lt;/p&gt;
&lt;p&gt;It was actually over very quickly, considering how many people were
   there and how much general bedlam was going on.  On the way to the exit,
   we passed a guy who was asking the woman on the stage, &amp;quot;Would it make
   any kind of sense to contact headquarters?&amp;quot;
&lt;/p&gt;
&lt;p&gt;&amp;quot;No,&amp;quot; she said.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-386446129&quot;&gt; &lt;/a&gt;&lt;p&gt;They sent people a yellow card in the mail telling them, among
   other things, their precinct number.  But the card didn&apos;t say that
   you would need to know your precinct or that you should bring the
   card.  Someone was standing in the parking lot near the door waving
   a card and saying, &amp;quot;Yellow card?  Anyone have their yellow card?  If
   you have it, it&apos;ll tell you your precinct.&amp;quot;  I didn&apos;t hear anyone
   say they had their yellow card.&lt;a href=&quot;#fnr1-386446129&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-386446129&quot;&gt; &lt;/a&gt;&lt;p&gt;Yes, they also ran out of sign-in sheets.&lt;a href=&quot;#fnr2-386446129&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/6967.html</comments>
  <category>life</category>
  <category>local</category>
  <category>politics</category>
  <lj:mood>tired</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/6721.html</guid>
  <pubDate>Mon, 18 Feb 2008 01:37:44 GMT</pubDate>
  <title>Number Sequence Zendo</title>
  <link>http://brian-jaress.livejournal.com/6721.html</link>
  <description>&lt;p&gt;I saw the &lt;a href=&quot;http://okasaki.blogspot.com/2008/02/games-for-programmers-zendo.html&quot;&gt;Zendo&lt;/a&gt; board game &lt;a href=&quot;http://reddit.com/r/programming/info/68zbl/comments/&quot;&gt;on reddit&lt;/a&gt;, as well as a link in
   the comments to a list of &lt;a href=&quot;http://www.wunderland.com/WTS/Kory/Games/Zendo/OtherVariations.html&quot;&gt;variants&lt;/a&gt;, and it gave me an idea.
&lt;/p&gt;
&lt;p&gt;The basic idea behind Zendo is:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;p&gt;One person is the &amp;quot;master&amp;quot; who makes up a secret rule.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;The master starts by showing the players one example that follows the
      rule and one that doesn&apos;t (telling them which is which).
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Players try to figure out the rule by
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;p&gt;Giving examples to the master who tells them whether or not the
   example follows the rule
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Guessing the rule.  If the guess is wrong, the master either gives
   an example that follows the guessed rule but not the actual rule or
   gives an example that follows the actual rule but not the guessed
   rule.
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Exchanges between the master and a player are seen by all players.
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Regular Zendo uses arrangements of colored pyramids as the things being
   tested against the rule, so a rule might be, &amp;quot;Exactly two red
   pyramids.&amp;quot;&lt;sup&gt;&lt;a name=&quot;fnr1-279573217&quot; href=&quot;#fn1-279573217&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;  Bongard Zendo, the variant suggested in the reddit
   comments, uses simple drawings, so a rule might be, &amp;quot;at least one
   straight line.&amp;quot;
&lt;/p&gt;
&lt;p&gt;So I had the idea to use number sequences.  A rule might be, &amp;quot;The
   numbers get bigger,&amp;quot; or, &amp;quot;Every odd number has an odd number of digits.&amp;quot;
&lt;/p&gt;
&lt;p&gt;A game might start like this (using &amp;quot;true&amp;quot; to mean something follows the
   rule and &amp;quot;false&amp;quot; to mean it doesn&apos;t):
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Master: 4, 6, 8 is true.  27, 2 is false.
&lt;/p&gt;
&lt;p&gt;Player: 4, 6.
&lt;/p&gt;
&lt;p&gt;Master: True.
&lt;/p&gt;
&lt;p&gt;Player: 4, 6, 8, 10.
&lt;/p&gt;
&lt;p&gt;Master: True.
&lt;/p&gt;
&lt;p&gt;Player: The numbers increase by two.
&lt;/p&gt;
&lt;p&gt;Master: No.  2, 6, 10 is true.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;And so on.
&lt;/p&gt;
&lt;p&gt;Someone must have had this idea before, but I can&apos;t find it.  I had it
   because Zendo reminded me of something called the &lt;a href=&quot;http://www.overcomingbias.com/2007/08/positive-bias-l.html&quot;&gt;2-4-6&lt;/a&gt; test, which
   I&apos;d heard about recently.
&lt;/p&gt;
&lt;p&gt;I found two games that are sort of similar.  In one, you make up an
   arithmetic process, and people try to figure it out by giving you
   numbers and getting the result.  In the other, you start a sequence, and
   they try to guess the next number.
&lt;/p&gt;
&lt;p&gt;Neither sounds like it would have the same sort of strategy as Zendo.
   In the example game I gave above, the master is trying to send the
   players in the wrong direction, and the players are trying (without much
   success) to pin the master down.&lt;sup&gt;&lt;a name=&quot;fnr2-279573217&quot; href=&quot;#fn2-279573217&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;Compared to the other types of Zendo, this one should be easy to play on
   the Internet.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-279573217&quot;&gt; &lt;/a&gt;&lt;p&gt;Wikipedia has a nice &lt;a href=&quot;http://en.wikipedia.org/wiki/Zendo_%28game%29&quot;&gt;article&lt;/a&gt; on Zendo, including example
   rules.&lt;a href=&quot;#fnr1-279573217&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-279573217&quot;&gt; &lt;/a&gt;&lt;p&gt;The rule in this example might be, &amp;quot;The numbers increase by a
   multiple of two,&amp;quot; but there are a lot of other things it could be.
   For example, it could be either of the two rules I mentioned
   earlier.&lt;a href=&quot;#fnr2-279573217&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/6721.html</comments>
  <category>games</category>
  <category>zendo</category>
  <category>numbers</category>
  <lj:mood>hungry</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/6605.html</guid>
  <pubDate>Mon, 28 Jan 2008 11:56:21 GMT</pubDate>
  <title>Artificial Evil</title>
  <link>http://brian-jaress.livejournal.com/6605.html</link>
  <description>&lt;p&gt;I recently came across a very odd attempt to justify torture:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I asked what was the least bad, bad thing that could happen, and
   suggested that it was getting a dust speck in your eye that irritated
   you for a fraction of a second, barely long enough to notice, before it
   got blinked away.  And conversely, a very bad thing to happen, if not
   the worst thing, would be getting &lt;a href=&quot;http://en.wikipedia.org/wiki/Torture&quot;&gt;tortured&lt;/a&gt; for 50 years.
&lt;/p&gt;
&lt;p&gt;Now, would you rather that a &lt;a href=&quot;http://en.wikipedia.org/wiki/Googolplex&quot;&gt;googolplex&lt;/a&gt; people got dust specks in
   their eyes, or that one person was tortured for 50 years? . . .
&lt;/p&gt;
&lt;p&gt;Most people chose the dust specks over the torture.  Many were proud of
   this choice, and indignant that anyone should choose otherwise:  &amp;quot;How
   dare you condone torture!&amp;quot;
&lt;/p&gt;
&lt;p&gt;-- &lt;a href=&quot;http://en.wikipedia.org/wiki/Eliezer_Yudkowsky&quot;&gt;Eliezer Yudkowsky&lt;/a&gt;, &amp;quot;&lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html&quot;&gt;Circular Altruism&lt;/a&gt;&amp;quot; (links added)
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Yudkowsky is an &lt;a href=&quot;http://en.wikipedia.org/wiki/Artificial_intelligence&quot;&gt;artificial intelligence&lt;/a&gt; researcher for the
   &lt;a href=&quot;http://www.singinst.org/&quot;&gt;Singularity Institute&lt;/a&gt; writing on a blog run by &lt;a href=&quot;http://www.fhi.ox.ac.uk/&quot;&gt;Oxford&lt;/a&gt;.  He&apos;s
   not just advocating torture on the Internet -- he&apos;s trying to help
   create a &amp;quot;&lt;a href=&quot;http://www.sfgate.com/cgi-bin/article.cgi?f=/c/a/2006/05/12/BUG9IIMG1V197.DTL&quot;&gt;superintelligence&lt;/a&gt;&amp;quot; that will, if it works the way
   he hopes, choose the torture over the dust.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Morality by Multiplication&lt;/h2&gt;
&lt;p&gt;Of course you&apos;re never going to have that many people, much less a way
   of keeping dust out of their eyes via torture.  It&apos;s more likely that
   his AI would face a choice between torture and, say, social unrest.
&lt;/p&gt;
&lt;p&gt;The dust specks just illustrate Yudkowsky&apos;s approach to moral
   decisions:&lt;sup&gt;&lt;a name=&quot;fnr1-296952762&quot; href=&quot;#fn1-296952762&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;He assigns a number to everything that could happen to a person, then
   multiplies by the number of people and compares the totals.  Under that
   system, a dust speck gets a number close to zero and fifty years of
   torture gets a number far from zero.  Then the torture number is
   multiplied by one person and the dust number is multiplied by an
   enormous number of people, giving a higher total.
&lt;/p&gt;
&lt;p&gt;You&apos;d think the dust speck vs torture example would come from someone
   trying to debunk Yudkowsky&apos;s method.  Nope.  He thinks it shows how
   sensible he&apos;s being.
&lt;/p&gt;

&lt;h2&gt;Rebuttal Roundup&lt;/h2&gt;
&lt;p&gt;There were plenty of negative responses.  Here&apos;s a sample:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html#comment-98129978&quot;&gt;Roland&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html#comment-98152190&quot;&gt;Ben Jones&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html#comment-98186428&quot;&gt;Caledonian&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html#comment-98601464&quot;&gt;tcpkac&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/circular-altrui.html#comment-98653394&quot;&gt;Salutator&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href=&quot;http://www.overcomingbias.com/2008/01/knowing-your-ar.html&quot;&gt;Paul Gowder&lt;/a&gt;
(an excellent full-length counterpost on the same site)
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yudkowsky hasn&apos;t yet really responded to the challenges against his morality
   by multiplication.  He&apos;s explained a few times how it leads to torture,
   but not why the method itself is any good.&lt;sup&gt;&lt;a name=&quot;fnr2-296952762&quot; href=&quot;#fn2-296952762&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;There were also, sadly, plenty of positive responses.
&lt;/p&gt;
&lt;p&gt;UPDATE 2008-01-28: Yudkowsky has &lt;a href=&quot;http://www.overcomingbias.com/2008/01/the-intuitions.html&quot;&gt;responded&lt;/a&gt; to Paul Gowder.  I also
   found an excellent &lt;a href=&quot;http://www.overcomingbias.com/2007/10/who-told-you-mo.html&quot;&gt;earlier post&lt;/a&gt; by Gowder which looks at the issues
   I tried raise below from a philosophical perspective.
&lt;/p&gt;

&lt;h2&gt;Open the Pod Bay Doors, HAL&lt;/h2&gt;
&lt;p&gt;I wasn&apos;t sure whether to take this idea seriously and try to rebut it
   or just point and laugh.
&lt;/p&gt;
&lt;p&gt;The whole thing is like a science fiction movie, except in the movies
   the artificial intelligence&apos;s evil is usually an unintended consequence.
   Here, the designer is preemptively telling us the torture is a feature,
   not a bug.
&lt;/p&gt;
&lt;p&gt;From a computer science perspective, it&apos;s kind of sad to hear this from
   an AI researcher connected to places like Oxford and Stanford.  His
   favored approach to creating a moral AI, and his apparent reasons for
   favoring it, go against some of our basic working knowledge of
   computation:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Don&apos;t think like a machine.  The machine already does that -- your job
       is something else.
 &lt;/li&gt;

 &lt;li&gt;
     Consistency does not equal correctness.
 &lt;/li&gt;

 &lt;li&gt;
     Correctness of the system is judged outside the system.
 &lt;/li&gt;

 &lt;li&gt;
     A perfect solution is quite often impossible, and perfection itself is
       often impossible to define.
 &lt;/li&gt;

 &lt;li&gt;
     Which imperfect solution is best depends more on context than first
       principles.
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We have a name for imperfect methods that work well in many cases we are
   concerned with.  They are called &lt;a href=&quot;http://www.nist.gov/dads/HTML/heuristic.html&quot;&gt;heuristics&lt;/a&gt;.  If a perfect solution
   is unknown, unfeasible, known to be impossible, or not precisely defined
   in terms of what it accomplishes, we will often use heuristics.
&lt;/p&gt;
&lt;p&gt;Eliezer Yudkowsky&apos;s multiplication method is a heuristic.  How often it
   works well is debatable&lt;sup&gt;&lt;a name=&quot;fnr3-296952762&quot; href=&quot;#fn3-296952762&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, but it is not perfect.  It sometimes
   produces answers that are judged to be wrong by the standards of the
   people it is designed to serve.
&lt;/p&gt;
&lt;p&gt;The designation as a heuristic isn&apos;t about the precision of the answer
   or whether it uses math.  It&apos;s about how the results compare to some
   external requirements -- which is always how we define correctness.
&lt;/p&gt;
&lt;p&gt;What we do not and should not do is throw away the external requirements
   and look to the heuristic itself as our definition of correctness.
&lt;/p&gt;
&lt;p&gt;The recommendations from online stores, based on your past purchases,
   come from  heuristics.  They use math and often suggest things you like.
   But sometimes they suggest things you don&apos;t like.  Those are wrong
   answers -- the heuristic is wrong, not you.
&lt;/p&gt;
&lt;p&gt;Your preferences are not defined by store suggestions, and morality is
   not defined by Yudkowsky&apos;s extremely hard-line &lt;a href=&quot;http://plato.stanford.edu/entries/consequentialism/&quot;&gt;utilitarian&lt;/a&gt;
   method.  (Just to be clear, morality is also not defined by your
   preferences or by store suggestions.)
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-296952762&quot;&gt; &lt;/a&gt;&lt;p&gt;Actually, it&apos;s his basic approach to all decisions.  His slogan
   seems to be, &amp;quot;Shut up and multiply.&amp;quot;  (That&apos;s not a parody.  He actually
   says it.)&lt;a href=&quot;#fnr1-296952762&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-296952762&quot;&gt; &lt;/a&gt;&lt;p&gt;It looks like he&apos;s been taking care of some personal business
   recently, so he may be planning a separate post on that soon.&lt;a href=&quot;#fnr2-296952762&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-296952762&quot;&gt; &lt;/a&gt;&lt;p&gt;It&apos;s debatable, but I don&apos;t want to debate it.&lt;a href=&quot;#fnr3-296952762&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/6605.html</comments>
  <category>morality</category>
  <category>requirements</category>
  <lj:mood>surprised</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/6392.html</guid>
  <pubDate>Mon, 31 Dec 2007 10:10:28 GMT</pubDate>
  <title>Jest 1.0</title>
  <link>http://brian-jaress.livejournal.com/6392.html</link>
  <description>&lt;p&gt;The version 1.0 release of &lt;a href=&quot;http://home.gna.org/jest&quot; title=&quot;Brian Jaress&amp;#39;s Software Estimator&quot;&gt;jest&lt;/a&gt; (my &lt;a href=&quot;http://softwaresurvival.blogspot.com/2006/11/dynamics-of-effort-estimation-in-most.html&quot;&gt;software estimator&lt;/a&gt;) is
   available for &lt;a href=&quot;http://download.gna.org/jest/jest-1.0.0.tar.gz&quot;&gt;download&lt;/a&gt;.  The biggest difference from the beta
   versions is that the license has changed to &lt;a href=&quot;http://svn.gna.org/viewcvs/jest/trunk/COPYING?rev=49&amp;amp;view=markup&quot;&gt;GPLv3&lt;/a&gt;.
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Why GPLv3?&lt;/h2&gt;
&lt;p&gt;Version 3 of the GNU General Public License caused some &lt;a href=&quot;http://www.eweek.com/article2/0,1759,2108409,00.asp&quot;&gt;controversy&lt;/a&gt;
   while it was being drafted, but that controversy seemed to &lt;a href=&quot;http://enterprise.linux.com/enterprise/07/03/29/0357254.shtml?tid=41&amp;amp;tid=12&quot;&gt;taper off&lt;/a&gt;
   as the drafting went on.&lt;sup&gt;&lt;a name=&quot;fnr1-389528819&quot; href=&quot;#fn1-389528819&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;
&lt;p&gt;I was already using the &amp;quot;&lt;a href=&quot;http://www.fsf.org/licensing/licenses/gpl-faq.html#v2v3Compatibility&quot;&gt;or later&lt;/a&gt;&amp;quot; phrase, so jest has actually been
   available under GPLv3 since GPLv3 was published.  What I&apos;m really doing
   is dropping GPLv2.  It&apos;s partly for simplicity, but also because it
   &lt;a href=&quot;http://gplv3.fsf.org/rms-why.html&quot; title=&quot;Why Upgrade to GPL Version 3&quot;&gt;plugs some holes&lt;/a&gt; in v2.&lt;sup&gt;&lt;a name=&quot;fnr2-389528819&quot; href=&quot;#fn2-389528819&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;  The most important change for
   jest is the improved &lt;a href=&quot;http://www.fsf.org/licensing/licenses/quick-guide-gplv3.html#stronger-protection-against-patent-threats&quot;&gt;protection&lt;/a&gt; from patents.
&lt;/p&gt;

&lt;h2&gt;What Next?&lt;/h2&gt;
&lt;p&gt;In the middle of talking about software measurement, a
   professor&lt;sup&gt;&lt;a name=&quot;fnr3-389528819&quot; href=&quot;#fn3-389528819&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; asked me how accurate my software estimates are, and
   I basically said, &amp;quot;They can be way off because people ignore them and
   try to dictate the results.&amp;quot;
&lt;/p&gt;
&lt;p&gt;No matter how well the estimate represents what &lt;em&gt;would&lt;/em&gt; happen if we
   wrote the software and timed ourselves, that&apos;s often not what we
   actually do.  Someone says, &amp;quot;We need it in three weeks without cutting
   features,&amp;quot; and everything becomes chaos because we&apos;re attempting the
   impossible.&lt;sup&gt;&lt;a name=&quot;fnr4-389528819&quot; href=&quot;#fn4-389528819&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;  We&apos;ll end up cutting features and wasting effort,
   but since we&apos;re in denial we aren&apos;t even trying to figure out ahead of
   time how much of those things we&apos;ll do.&lt;sup&gt;&lt;a name=&quot;fnr5-389528819&quot; href=&quot;#fn5-389528819&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;That question, and several things the professor said about measurement,
   gave me an idea for what to do in jest 2.0:
&lt;/p&gt;
&lt;p&gt;Run the formulas backward.
&lt;/p&gt;
&lt;p&gt;In other words, start with the amount of time (and people) and estimate
   what can be done in that time.  That might sound a little strange, but
   it fits with the way most software is actually developed.  Resources,
   not wishes, are the limiting factor.
&lt;/p&gt;
&lt;p&gt;I&apos;m hoping it will also nudge people in the right direction.  When you
   start with size and estimate time, it&apos;s tempting to think, &amp;quot;That&apos;s too
   long.  Maybe if I work heroically I can get it done on time.&amp;quot;  Starting
   from time and estimating size will (hopefully) make it easier to think,
   &amp;quot;Are there ways I can satisfy the users with a program of that size?&amp;quot;
   That way, you&apos;re trying to finish sooner by doing less, instead of by
   doing more.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-389528819&quot;&gt; &lt;/a&gt;&lt;p&gt;In my opinion (after reading some of the drafts and
   following some of the process) the process mostly involved
   clarifying the license until the critics stopped misinterpreting it.&lt;a href=&quot;#fnr1-389528819&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-389528819&quot;&gt; &lt;/a&gt;&lt;p&gt;Yes, I actually read the license and decided based on that.
   I&apos;m linking to someone else to give you a nice summary.&lt;a href=&quot;#fnr2-389528819&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-389528819&quot;&gt; &lt;/a&gt;&lt;p&gt;&lt;a href=&quot;http://johnson-engineering-log.blogspot.com/&quot;&gt;Phil Johnson&lt;/a&gt;, of &lt;a href=&quot;http://www.hackystat.org&quot;&gt;Hackystat&lt;/a&gt;.&lt;a href=&quot;#fnr3-389528819&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn4-389528819&quot;&gt; &lt;/a&gt;&lt;p&gt;Professor Johnson seemed a little shocked by that answer.  It&apos;s
   actually more true for students than professionals.  The instructor
   gives you a date and a feature set, with no room for discussions of
   silly things like feasibility.
&lt;/p&gt;
&lt;p&gt;Because they&apos;re often motivated by something real, business
   constraints actually tend to be more flexible.  People can be willing
   to work with you to come at things from a different angle and
   achieve the underlying goals in different way.&lt;a href=&quot;#fnr4-389528819&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn5-389528819&quot;&gt; &lt;/a&gt;&lt;p&gt;The people I&apos;m hoping will use jest are actually the most
   susceptible to this problem.  The other estimators seem to be
   targeting people who already view estimation as an important formal
   process and are able to invest a lot of time and effort in it.  I&apos;m
   going for everyone else.&lt;a href=&quot;#fnr5-389528819&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
  <comments>http://brian-jaress.livejournal.com/6392.html</comments>
  <category>gplv3</category>
  <category>jest</category>
  <lj:mood>pleased</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/5978.html</guid>
  <pubDate>Fri, 28 Sep 2007 02:27:16 GMT</pubDate>
  <title>Markdown-Python Wrapped Tables Extension</title>
  <link>http://brian-jaress.livejournal.com/5978.html</link>
  <description>&lt;p&gt;I&apos;ve been using &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot; title=&quot;Markdown Syntax Documentation on Daring Fireball&quot;&gt;markdown syntax&lt;/a&gt; for a while, and I (very) recently
   switched from the reference interpreter to &lt;a href=&quot;http://www.freewisdom.org/projects/python-markdown/&quot;&gt;markdown-python&lt;/a&gt; which has
   some nice extensions&lt;sup&gt;&lt;a name=&quot;fnr1-303156809&quot; href=&quot;#fn1-303156809&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;
&lt;p&gt;One extension I wanted to use was for tables, but when I tried it I
   found out that it won&apos;t let you put multiple lines in a table cell.  (I
   mean multiple lines in the markdown.  I assume you can force multiple
   lines in the HTML by using &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt;.)
&lt;/p&gt;
&lt;p&gt;So, I wrote my own extension called &amp;quot;wtables.&amp;quot;&lt;sup&gt;&lt;a name=&quot;fnr2-303156809&quot; href=&quot;#fn2-303156809&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
   &lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Please do not hassle me for writing my own instead of modifying the
   existing one.  The basic approach they were taking was incompatible with
   the feature I wanted to add.
&lt;/p&gt;
&lt;p&gt;Markdown-python has a wiki, so I should probably add it there
   eventually.  For now, I&apos;m sticking it here.  This is &lt;em&gt;very untested&lt;/em&gt;
   code.  I&apos;ve used it once on real data and that&apos;s it.  Please let me know
   if it gives you any trouble.
&lt;/p&gt;
&lt;p&gt;One thing it won&apos;t do is turn blank lines into paragraph breaks&lt;sup&gt;&lt;a name=&quot;fnr3-303156809&quot; href=&quot;#fn3-303156809&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, so If
   you want a cell to have multiple paragraphs, you have to write the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;
   tags yourself.  But at least you can put them on their own lines.
&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;code&quot;&gt;
   Contents of the file &lt;code&gt;mdx_wtables.py&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;
Wrapped Tables extension for Markdown Python

2007-09-27

brian_jaress@gna.org

&amp;quot;Wrapped&amp;quot; means that you can wrap lines inside a cell.
It&apos;s inspired by another extension I found at

https://libprs500.kovidgoyal.net/browser/trunk/src/libprs500/ebooks/markdown/mdx_tables.py?format=txt

but that extension didn&apos;t have wrapping and is implemented in a very
different way.

An example of the syntax is:

|*heading*|*heading*|cell|
|cell a|cell b| cell c
    still cell c
    blah blah blah
    still cell c|
|third row|cell|cell|

That gives you a three by three table with two headings (top left and
top center) and one cell with a lot of text (mid right).

&amp;quot;&amp;quot;&amp;quot;

from os import linesep
from csv import reader, QUOTE_NONE
from markdown import Preprocessor, Extension

class TableExtension(Extension):
    def __init__(self, configs):
        self.configs = {
                &apos;delim&apos;: &apos;|&apos;,
                &apos;wrap&apos;: 4 * &apos; &apos;,
                &apos;header&apos;: &apos;*&apos;
                }
        self.configs.update(configs)

    def extendMarkdown(self, md, md_globals):
        md.preprocessors.append(TablePre(**self.configs))

class TablePre(Preprocessor):
    def __init__(self, delim, wrap, header):
        self.delim = delim
        self.wrap = wrap
        self.header = header

    def run(self, lines):
        table_lines = []
        #Group contiguous table lines and convert each group to a table
        for l in lines:
            if l.startswith(self.delim) or (len(table_lines) &amp;gt; 0 and
                    l.startswith(self.wrap)):
                table_lines.append(l)
            else:
                if len(table_lines) &amp;gt; 0:
                    for new_line in self.table(table_lines):
                        yield new_line
                    table_lines = []
                yield l

    def clean(self, cells):
        &amp;quot;&amp;quot;&amp;quot;Remove the empty cells at the beginning and end.&amp;quot;&amp;quot;&amp;quot;
        return cells[1:-1]

    def table(self, lines):
        yield &amp;quot;&amp;lt;table&amp;gt;&amp;quot;
        for r in self.parse(lines):
            yield self.row(r)
        yield &amp;quot;&amp;lt;/table&amp;gt;&amp;quot;

    def parse(self, lines):
        &amp;quot;&amp;quot;&amp;quot;Generate table rows as lists of cell strings.&amp;quot;&amp;quot;&amp;quot;
        read = reader(lines,
                delimiter=self.delim,
                quoting=QUOTE_NONE,
                escapechar=&apos;\\&apos;,
                lineterminator=linesep
                )

        accumulated = []
        for line in read:
            if not line[0].startswith(self.wrap):
                #Start new row
                if len(accumulated) &amp;gt; 0:
                    yield self.clean(accumulated)
                accumulated = line
            else:
                #Continue existing cell
                accumulated[-1] = accumulated[-1] + &apos;\n&apos; + line[0].lstrip()
                accumulated.extend(line[1:])
        yield self.clean(accumulated)

    def row(self, data):
        return self.tag(&apos;&apos;.join(map(self.cell, data)), &amp;quot;tr&amp;quot;)

    def cell(self, data):
        if (data.startswith(self.header) and data.endswith(self.header) and
                len(data) &amp;gt; 1):
            data = data[len(self.header):-len(self.header)]
            tag = &amp;quot;th&amp;quot;
        else:
            tag = &amp;quot;td&amp;quot;
        return self.tag(data, tag)

    def tag(self, data, tag):
        return &amp;quot;&amp;lt;%s&amp;gt;%s&amp;lt;/%s&amp;gt;&amp;quot; % (tag, data, tag)

def makeExtension(configs={}) :
    return TableExtension(configs)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;UPDATE: fixed wrong word.
&lt;/p&gt;

&lt;div class=&quot;footnote&quot;&gt;&lt;hr /&gt;&lt;ol&gt;
 &lt;li&gt;&lt;a name=&quot;fn1-303156809&quot;&gt;&lt;p&gt;For example, footnotes.&lt;a href=&quot;#fnr1-303156809&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn2-303156809&quot;&gt;&lt;p&gt;The &amp;quot;w&amp;quot; stands for &amp;quot;wrapped,&amp;quot; but it&apos;s mostly to distinguish
   between my extension and the other one.&lt;a href=&quot;#fnr2-303156809&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;a name=&quot;fn3-303156809&quot;&gt;&lt;p&gt;In fact, it will translate blank lines into the end of the table.&lt;a href=&quot;#fnr3-303156809&quot; class=&quot;footnoteBackLink&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;&amp;#8617;&lt;/a&gt;
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;</description>
  <comments>http://brian-jaress.livejournal.com/5978.html</comments>
  <category>markdown</category>
  <lj:mood>satisfied</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/5706.html</guid>
  <pubDate>Fri, 21 Sep 2007 22:42:31 GMT</pubDate>
  <title>A Substantive Look at Strategy Letter VI</title>
  <link>http://brian-jaress.livejournal.com/5706.html</link>
  <description>&lt;p&gt;The other day I posted a quick &lt;a href=&quot;http://brian-jaress.livejournal.com/5445.html&quot; title=&quot;A Minor Problem with Strategy Letter VI&quot;&gt;nitpick&lt;/a&gt; of Joel Spolsky&apos;s
&lt;a href=&quot;http://www.joelonsoftware.com/items/2007/09/18.html&quot;&gt;Strategy Letter VI&lt;/a&gt;.  The response was overwhelming (one person)
and negative.&lt;/p&gt;

&lt;p&gt;Now, I reserve my right to complain about bad analogies -- even when
they appear in grand, sweeping theories about something else.  But my
anonymous visitor has a point.  I really should address Joel&apos;s main
idea:
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Somebody is going to write a compelling SDK that you can use to make
  powerful Ajax applications with common user interface elements that
  work together. . . And the NewSDK people ship a pretty decent word
  processor and a pretty decent email app and a killer Facebook/Twitter
  event publisher that synchronizes with everything, so people start
  using it. . .&lt;/p&gt;
  
  &lt;p&gt;And while you&apos;re not paying attention, everybody starts writing NewSDK
  apps, and they&apos;re really good, and suddenly businesses ONLY want
  NewSDK apps, and all those old-school Plain Ajax apps look pathetic and
  won&apos;t cut and paste and mash and sync and play drums nicely with one
  another.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Joel points out that this is what happened with the user interfaces of
PC desktop programs.  It probably happened in a lot of other places,
too.&lt;/p&gt;

&lt;p&gt;But not on the web.  It didn&apos;t happen with &lt;a href=&quot;http://msdn.microsoft.com/workshop/components/activex/activex_node_entry.asp&quot;&gt;ActiveX&lt;/a&gt;, or Java
&lt;a href=&quot;http://java.sun.com/applets/&quot;&gt;applets&lt;/a&gt;, or &lt;a href=&quot;http://en.wikipedia.org/wiki/Microsoft_Passport&quot; title=&quot;. . . or whatever it&amp;#39;s called now&quot;&gt;Microsoft Passport&lt;/a&gt;, or the browsers themselves, or a
thousand other things which had, or could have had, their own special
interop.  You can come up with individual reasons why it didn&apos;t happen
in each case (Joel does that for applets) but it always had the same
reason &lt;em&gt;to&lt;/em&gt; happen -- and it didn&apos;t happen.&lt;/p&gt;

&lt;p&gt;Why is that?  I don&apos;t know.  But here&apos;s a plausible sounding theory: The
web is huge, and it already does the main thing people want from it --
information exchange between people.&lt;/p&gt;

&lt;p&gt;If NewSDK exports something, people want to put it in their forum sig.
If NewSDK lets you embed one page in another, people want to embed
arbitrary news articles.  If NewSDK lets two sites play the drums
together (as Joel puts it) then people want their new site to play drums
with their old one.&lt;/p&gt;

&lt;p&gt;There will be a pressure for sites to work together, but it won&apos;t be a
pressure on sites to use NewSDK.  It will be pressure on NewSDK to make
their features work with the entire rest of the web.  Once they do that,
it becomes (reasonably) easy or unnecessary for other frameworks to compatibly
implement those features.&lt;/p&gt;

&lt;h2&gt;Endnote&lt;/h2&gt;

&lt;p&gt;I am not a pundit, and my opinion that the web already does the main
thing people want from it probably disqualifies me from becoming one.  I
have no plans to do this again, but I felt I ought to write a separate
article addressing the substance of Joel Spolsky&apos;s theory.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/5706.html</comments>
  <lj:mood>indifferent</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/5445.html</guid>
  <pubDate>Wed, 19 Sep 2007 07:48:40 GMT</pubDate>
  <title>A Minor Problem with Strategy Letter VI</title>
  <link>http://brian-jaress.livejournal.com/5445.html</link>
  <description>&lt;p&gt;I just saw &lt;a href=&quot;http://www.joelonsoftware.com/items/2007/09/18.html&quot;&gt;Strategy Letter VI&lt;/a&gt; from Joel Spolsky, and I have one
minor nitpick that I feel compelled to post:
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GMail is not Google&apos;s flagship product.&lt;/p&gt;

&lt;p&gt;There&apos;s a nice &lt;a href=&quot;http://programming.reddit.com/info/2r2dy/comments&quot; title=&quot;Joel Spolsky on the death of GMail&quot;&gt;discussion&lt;/a&gt; on reddit, but it&apos;s mostly about Joel&apos;s
&quot;history is repeating itself&quot; theory.  I figured I&apos;d do my nitpicking
here.&lt;/p&gt;

&lt;p&gt;Although, now that I think about it, it&apos;s a fairly large nit.  Joel&apos;s
argument doesn&apos;t work at all if you swap in Google Search for GMail.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/5445.html</comments>
  <category>spolsky</category>
  <category>google</category>
  <lj:mood>amused</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/5338.html</guid>
  <pubDate>Tue, 04 Sep 2007 20:46:14 GMT</pubDate>
  <title>R6RS Ratified</title>
  <link>http://brian-jaress.livejournal.com/5338.html</link>
  <description>&lt;blockquote&gt;
  &lt;p&gt;The nice thing about standards is that you have so many to choose from.&lt;/p&gt;
  
  &lt;p&gt;-- &lt;a href=&quot;http://en.wikiquote.org/wiki/Andrew_S._Tanenbaum&quot; title=&quot;Wikiquote&quot;&gt;Andrew S. Tanenbaum&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They were a little late announcing it, and I&apos;m a little late saying
anything about it, but r6rs has been &lt;a href=&quot;http://www.r6rs.org/&quot;&gt;ratified&lt;/a&gt;.
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There were implementors on &lt;a href=&quot;http://www.r6rs.org/ratification/results.html&quot;&gt;both sides&lt;/a&gt;, and we&apos;ll probably
have r6rs and r5rs implementations coexisting for a while.&lt;/p&gt;

&lt;p&gt;I&apos;m wondering if r6rs can actually succeed at its goals.  Will people be
able to share libraries across implementations?  Will the industry
embrace Scheme now that it has built-in modules, exceptions, records,
etc.?&lt;/p&gt;

&lt;p&gt;My guess is no, but we shall see.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/5338.html</comments>
  <category>r6rs</category>
  <category>scheme</category>
  <lj:mood>gloomy</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/5081.html</guid>
  <pubDate>Mon, 27 Aug 2007 20:40:36 GMT</pubDate>
  <title>The Grad Student</title>
  <link>http://brian-jaress.livejournal.com/5081.html</link>
  <description>&lt;p&gt;I&apos;ve gone back to &lt;a href=&quot;http://manoa.hawaii.edu/&quot;&gt;UHM&lt;/a&gt;, and last week was my very first as a graduate
student.&lt;/p&gt;

&lt;p&gt;One class, &lt;a href=&quot;http://groups.google.com/group/ics-software-engineering-fall-2007&quot;&gt;ICS 613&lt;/a&gt; Software Engineering, required us to create an
&lt;a href=&quot;http://bpj-613.blogspot.com/&quot;&gt;engineering log&lt;/a&gt; on &lt;a href=&quot;http://blogger.com&quot;&gt;Blogger&lt;/a&gt;.  In general, I&apos;ll be putting
things related to that class on Blogger and everything else here.
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It&apos;s an interesting class.  The professor&apos;s approach is to blitz us with
the  details of development using his preferred Java environment --
Eclipse, Ant, JUnit, etc.  Our first reading assignment included four
chapters (about 200 pages) of the misnamed
&lt;a href=&quot;http://www.oreilly.com/catalog/javanut5/&quot; title=&quot;Java in a Shipping Container&quot;&gt;Java in a Nutshell, 5th ed.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It&apos;s a good experience for me because the professor&apos;s philosophy of
software engineering is completely different from mine.  In fact, his
whole approach to software is nearly opposite to mine.  In only two
lectures, he&apos;s already told us that simple tools are bad because they
don&apos;t scale, that Common Lisp is the greatest language in the world, and
that the class is designed to train us rather than educate us.&lt;/p&gt;

&lt;p&gt;(Some of you are nodding; others are laughing.)&lt;/p&gt;

&lt;p&gt;But he&apos;s nice and he knows a lot, so I&apos;m willing to overlook the giant
slides trashing my school of thought.  This is, after all, one of the
things I came back for -- learning from people with very different views
and backgrounds&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/5081.html</comments>
  <category>uh</category>
  <lj:mood>busy</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/4825.html</guid>
  <pubDate>Mon, 13 Aug 2007 02:14:12 GMT</pubDate>
  <title>Why I Voted No</title>
  <link>http://brian-jaress.livejournal.com/4825.html</link>
  <description>&lt;p&gt;Today I sent in my ballot on r6rs ratification.  I voted no, and
decided to also post the explanation required on the ballot here.
Rather than simply copy and paste in the S-expression ballot, I edited
this into a format better suited to a website. I also changed the
mailing list links to point to the specific message rather than the
whole thread.  The words are the same:
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Although my initial impression of the draft was mildly positive, after
looking it over more thoroughly I am voting against ratification.
My vote is based on my overall impression of the draft, but here are
some illustrative examples of particular things I don&apos;t like about it:&lt;/p&gt;

&lt;p&gt;Fist, the problem of two record systems that don&apos;t quite work together.
This was raised by Will Clinger, most recently in his essay
&quot;&lt;a href=&quot;http://www.ccs.neu.edu/home/will/R6RS/essay.txt&quot;&gt;Fixing the Syntactic Record Layer&lt;/a&gt;.&quot;&lt;/p&gt;

&lt;p&gt;Second, the fact that you cannot simply take a record value and access
one of its fields by name.  I &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2007-August/003146.html&quot;&gt;explained&lt;/a&gt; my &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2007-August/003145.html&quot;&gt;problem&lt;/a&gt; with that on the
mailing list.
None of the explanations given for this in the rationale, the mailing
list, or the srfi discussions satisfy me.  (And the only direct reply
seemed to misunderstand the example -- we want a container that requires
certain behavior of the values it contains while not requiring that they
be on an approved list or inherit from the same ancestor.  Importing the
accessors of each type of value we wish to contain makes the container&apos;s
import list the approved list.)&lt;/p&gt;

&lt;p&gt;Third, the condition system with its simple conditions and compound
conditions.  After reading through this part of the specification and
disliking it, I found a reasonable &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2007-February/001458.html&quot;&gt;counterproposal&lt;/a&gt; on the mailing list.
It was rejected with a statement that it conflicted with other decisions
of the editors and did not appear to be different in any other way.  (It
is, however quite different.  It makes all condition types record types,
eliminating the need for almost everything in section 7.2, and it makes
it much easier to handle an exception by supplementing the condition
with more information and re-raising it.)&lt;/p&gt;

&lt;p&gt;Those three are just illustrative examples.  I am casting my vote based
on my overall impression of r5.97rs: Too many things in the draft are
designed primarily to work around limitations imposed by other things in
the draft.&lt;/p&gt;

&lt;p&gt;The explanation of the condition system in particular helped me
crystallize what I had felt while reading the draft.  It was yet another
explanation of the form &quot;We must do X because we have decided to do Y
and Z.&quot;  Meanwhile, Y and Z are required by W, which is required by P
and Q, which we need because we have X and Y.  The editors are happy to
explain each feature by pointing to the features that require it (or at
least conflict with every alternative they are aware of) but don&apos;t seem
to have considered the glaring possibility that all are bad and that
this is why they are mutually forcing each other into a series of
workarounds.&lt;/p&gt;

&lt;p&gt;The introduction to the draft still begins with, &quot;Programming languages
should be designed not by piling feature on top of feature, but by
removing the weaknesses and restrictions that make additional features
appear necessary.&quot;  I feel I understand that principle much better now
that I have seen r5.97rs itself violate it.  If you start by planning to
add lots of features, add them in ways that introduce weaknesses and
restrictions, then refuse to remove or replace any of your additions as
a way of repairing the damage, you end up with a mess that piles
workaround on top of workaround and calls them features.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/4825.html</comments>
  <category>r6rs</category>
  <category>scheme</category>
  <lj:mood>numb</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/4390.html</guid>
  <pubDate>Sat, 28 Jul 2007 18:39:06 GMT</pubDate>
  <title>I&apos;m a Member of the R6RS Electorate</title>
  <link>http://brian-jaress.livejournal.com/4390.html</link>
  <description>&lt;p&gt;I&apos;ve been knocked out by a flu the past few days, and one of the
emails that piled up was a notice that I&apos;m a member of the
&lt;a href=&quot;http://www.r6rs.org/ratification/electorate.html&quot;&gt;R6RS electorate&lt;/a&gt;, voting on whether to ratify the current
draft of a new
&lt;a href=&quot;http://en.wikipedia.org/wiki/Scheme_%28programming_language%29&quot; title=&quot;Scheme: a minimalist, multi-paradigm dialect of Lisp&quot;&gt;Scheme&lt;/a&gt; standard.
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole process has been controversial, with some prominent people
expressing impassioned opinions -- It&apos;s pretty neat that a regular
person like me got in.&lt;/p&gt;

&lt;p&gt;At the time I sent in my &lt;a href=&quot;http://www.r6rs.org/ratification/electorate.html#X20&quot;&gt;application&lt;/a&gt;, I had looked over the 5.93 draft
(more the core than the library) but now I feel obliged to read the
final &lt;a href=&quot;http://www.r6rs.org/&quot;&gt;9.97 draft&lt;/a&gt; more carefully and look farther into the controversy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alex Shinn &lt;a href=&quot;http://groups.google.com/group/comp.lang.scheme/msg/efd57bedee4e701b&quot; title=&quot;Why R6RS is Controversial&quot;&gt;laid out&lt;/a&gt; the main
objections to 9.93.  There have been &lt;a href=&quot;http://www.r6rs.org/versions/CHANGES&quot;&gt;changes&lt;/a&gt; since then, but
mostly on other things.&lt;/li&gt;
&lt;li&gt;William Clinger, who &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002474.html&quot; title=&quot;Will Clinger has resignedfrom the Editors Committee&quot;&gt;resigned&lt;/a&gt; from the editors committee, has
&lt;a href=&quot;http://www.ccs.neu.edu/home/will/R6RS/essay.txt&quot; title=&quot;an essay on language design: fixing the syntactic layer&quot;&gt;criticized&lt;/a&gt; the record types (and proposed a fix).&lt;/li&gt;
&lt;li&gt;Matthias Felleisen of &lt;a href=&quot;http://www.plt-scheme.org/&quot;&gt;PLT Scheme&lt;/a&gt; thinks the draft is (almost) &lt;a href=&quot;http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002538.html&quot; title=&quot;r6rs is perfect&quot;&gt;perfect&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Felix Winkelmann of &lt;a href=&quot;http://www.call-with-current-continuation.org/index.html&quot;&gt;Chicken Scheme&lt;/a&gt; thinks &lt;a href=&quot;http://www.r6rs.org/ratification/electorate.html#X41&quot; title=&quot;It sucks, folks - face it.&quot;&gt;otherwise&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&apos;ve got a lot of reading to do.  This whole having-a-say thing is hard
work.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/4390.html</comments>
  <category>r6rs</category>
  <category>scheme</category>
  <lj:mood>surprised</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/4097.html</guid>
  <pubDate>Sat, 14 Jul 2007 20:46:28 GMT</pubDate>
  <title>HOSEF Looking for a New Partner</title>
  <link>http://brian-jaress.livejournal.com/4097.html</link>
  <description>&lt;p&gt;The &lt;a href=&quot;http://www.hosef.org/civicspace/history&quot; title=&quot;HOSEF History&quot;&gt;Hawaii Open Source Education Foundation&lt;/a&gt; is looking for a new
workshop and class partner.  I don&apos;t know all the details, but basically
the partner provides space and gets a shared computer lab.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.hosef.org/civicspace/contact&quot; title=&quot;Contact HOSEF&quot;&gt;Contact HOSEF&lt;/a&gt; if that sounds interesting.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/4097.html</comments>
  <category>hosef</category>
  <lj:mood>hopeful</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/3900.html</guid>
  <pubDate>Thu, 28 Jun 2007 08:29:51 GMT</pubDate>
  <title>Think First, Then Program Into a Language</title>
  <link>http://brian-jaress.livejournal.com/3900.html</link>
  <description>&lt;p&gt;There are some impressive things in &lt;a href=&quot;http://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html&quot;&gt;GNU cat&lt;/a&gt;.  I&apos;m not geeky
enough to read the source code of all, or even most, of the programs I
use, but one day I took a quick look at the &lt;a href=&quot;http://cvs.savannah.gnu.org/viewvc/coreutils/src/cat.c?root=coreutils&amp;amp;view=markup&quot; title=&quot;GNU cat source code&quot;&gt;source&lt;/a&gt; of &lt;code&gt;cat&lt;/code&gt;.  I was
reminded of it the other day, when I saw yet another antiblub
&lt;a href=&quot;http://fiatdev.com/2007/6/22/i-will-never-use-that&quot;&gt;article&lt;/a&gt; on &lt;a href=&quot;http://programming.reddit.com&quot;&gt;reddit&lt;/a&gt;.
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Antiblub&lt;/h2&gt;

&lt;p&gt;The name &quot;Blub&quot; was &lt;a href=&quot;http://paulgraham.com/avg.html&quot; title=&quot;Beating the Averages&quot;&gt;coined&lt;/a&gt; by Paul Graham:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[P]rogramming languages are not merely technologies, but habits of mind
  as well . . . when our hypothetical Blub programmer looks in the other
  direction, up the power [&lt;a href=&quot;http://paulgraham.com/power.html&quot; title=&quot;Succinctness is Power&quot;&gt;succinctness&lt;/a&gt;] continuum, he
  doesn&apos;t realize he&apos;s looking up.  . . Blub is good enough for him,
  because he thinks in Blub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, people wrongly think their favorite language is best
because the language itself distorts their thinking.  Oddly enough,
Graham coined the name as part of an argument that
&lt;a href=&quot;http://en.wikipedia.org/wiki/Lisp_%28programming_language%29&quot; title=&quot;Wikipedia: Lisp (programming language)&quot;&gt;his favorite language&lt;/a&gt; really is the best.&lt;/p&gt;

&lt;p&gt;That &quot;antiblub&quot; view caught on, and you&apos;ll &lt;a href=&quot;http://saladwithsteve.com/2004/06/joel-on-software-demonstrating-blub.html&quot;&gt;see&lt;/a&gt; people
&lt;a href=&quot;http://www.haskell.org/haskellwiki/Why_Haskell_matters#Epilogue&quot;&gt;promoting&lt;/a&gt; a language by &lt;a href=&quot;http://bc.tech.coop/blog/041215.html&quot;&gt;calling&lt;/a&gt; other
languages Blub.&lt;/p&gt;

&lt;h2&gt;Think First&lt;/h2&gt;

&lt;p&gt;There&apos;s another way to look at the influence of language on thought:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Don&apos;t limit your programming thinking only to the concepts that are
  supported automatically by your language. The best programmers think of
  what they want to do, and then they assess how to accomplish their
  objectives with the programming tools at their disposal.&lt;/p&gt;
  
  &lt;p&gt;--Steve McConnell, &lt;em&gt;&lt;a href=&quot;http://stevemcconnell.com/cc.htm&quot;&gt;Code Complete 2nd Ed&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Antiblub says that inferior languages constrain your thoughts, so switch
to a superior language.  &quot;Think first&quot; says that any language &lt;em&gt;can&lt;/em&gt;
constrain your thoughts, so don&apos;t let it.&lt;/p&gt;

&lt;p&gt;I prefer &quot;think first.&quot;  After all, there&apos;s no guarantee that you can
choose your language and no guarantee that even the best language (if a
&quot;best&quot; &lt;a href=&quot;http://weblog.raganwald.com/2006/12/lisp-is-not-last-word.html&quot; title=&quot;Lisp is not the last word&quot;&gt;even exists&lt;/a&gt;) will come with the thoughts you need.&lt;/p&gt;

&lt;p&gt;(McConnel is one of a handful of programmers who have promoted this view
under the slogan &quot;program into [the/a/your] language, not in it.&quot;  I
call it &quot;think first, then program into a language&quot; because that&apos;s clearer
and shortens to &quot;think first.&quot;)&lt;/p&gt;

&lt;h2&gt;An Example&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;/* Compute the next line number.  */

static void
next_line_num (void)
{
  char *endp = line_num_end;
  do
    {
      if ((*endp)++ &amp;lt; &apos;9&apos;)
        return;
      *endp-- = &apos;0&apos;;
    }
  while (endp &amp;gt;= line_num_start);
  if (line_num_start &amp;gt; line_buf)
    *--line_num_start = &apos;1&apos;;
  else
    *line_buf = &apos;&amp;gt;&apos;;
  if (line_num_start &amp;lt; line_num_print)
    line_num_print--;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;GNU cat &lt;a href=&quot;http://cvs.savannah.gnu.org/viewvc/coreutils/src/cat.c?root=coreutils&amp;amp;view=markup&quot; title=&quot;GNU cat source code&quot;&gt;uses&lt;/a&gt; that to generate line numbers, in part because
the C language doesn&apos;t have a big enough (or &lt;a href=&quot;http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic&quot;&gt;arbitrary-precision&lt;/a&gt;)
integer type.  It&apos;s longer than it would be in a language that did have
the right types, but the point is that it&apos;s possible.&lt;/p&gt;

&lt;p&gt;This code also shows that programming into a language doesn&apos;t mean your
knowledge of the language is superficial.  It uses some idiomatic
&lt;a href=&quot;http://en.wikipedia.org/wiki/Pointer_%28computing%29&quot;&gt;pointer&lt;/a&gt; work and properties of the &lt;a href=&quot;http://en.wikipedia.org/wiki/ASCII&quot;&gt;ASCII&lt;/a&gt; character set.  You can
look deeply into the language as long as you first decide what you&apos;re
looking for.&lt;/p&gt;

&lt;p&gt;From an antiblub point of view, one might argue that the author of GNU
cat saw a better way to write the program because of experience with
some other language.  That&apos;s a bit of a stretch, since the &quot;better way&quot;
is closer to an odometer or pencil-and-paper addition (with a twist).&lt;/p&gt;

&lt;p&gt;Expert C programmers (which I am not) tend to be good at thinking first
then programming into a language, whether or not they also use other
languages.  You can think of it as being more necessary the less the
language helps you and therefore a sign of weakness in the language, but
there&apos;s no denying it&apos;s a strength in the programmer.&lt;/p&gt;

&lt;h2&gt;Choices&lt;/h2&gt;

&lt;p&gt;Strength and weakness aside, the fact that it&apos;s possible means that
people can think thoughts outside the languages they know.  Then they
can judge whether another language better expresses those thoughts.
Once they&apos;ve done that, they can make trade-offs between the extra work
of programming into a less suitable language and other factors
(libraries, platforms, speed, etc.)&lt;/p&gt;

&lt;p&gt;It also gives you a path out of the language wars.  Thinking first, then
programming into a language means you don&apos;t have to look at things in
terms of Graham&apos;s &quot;power continuum.&quot;  Different languages can be &quot;best&quot;
for different people or for the same person at different times,
depending on the thoughts they want to capture.&lt;/p&gt;

&lt;p&gt;Languages aren&apos;t all equal, but they don&apos;t have a fixed, one-dimensional
ranking either.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/3900.html</comments>
  <category>programming</category>
  <lj:mood>thoughtful</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>5</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/3801.html</guid>
  <pubDate>Wed, 06 Jun 2007 19:26:17 GMT</pubDate>
  <title>Jest Walk-Through</title>
  <link>http://brian-jaress.livejournal.com/3801.html</link>
  <description>&lt;p&gt;The &lt;a href=&quot;http://download.gna.org/jest/jest-beta-3.tar.gz&quot;&gt;beta-3 release&lt;/a&gt; of &lt;a href=&quot;http://home.gna.org/jest/&quot; title=&quot;Brian Jaress&amp;#39;s Software Estimator&quot;&gt;jest&lt;/a&gt;, my command-line software estimator, is
out.  It adds new language factors and adjusts the default factor.  To
celebrate, we&apos;ll take a little project I&apos;m doing and run some estimates
on it using jest.  Near the end, we&apos;ll see some of jest&apos;s advanced
features.
&lt;br /&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;The Project&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.monkeysaudio.com/&quot;&gt;Monkey&apos;s Audio&lt;/a&gt; is a file format for &lt;a href=&quot;http://en.wikipedia.org/wiki/Lossless_data_compression&quot;&gt;lossless&lt;/a&gt; audio compression.
The library source is &lt;a href=&quot;http://www.monkeysaudio.com/files/MAC_SDK_399.zip&quot;&gt;available&lt;/a&gt;, but only under an awkward
&lt;a href=&quot;http://www.monkeysaudio.com/license.html&quot;&gt;license&lt;/a&gt;.  The source is also rather hard to understand; you&apos;ll see
people complaining about that on the &lt;a href=&quot;http://www.monkeysaudio.com/smf/index.php?board=3.0&quot;&gt;forums&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want something that will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;be &lt;a href=&quot;http://www.fsf.org/licensing/essays/free-sw.html&quot; title=&quot;definition of free software&quot;&gt;free software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;let me get sound out of .ape files&lt;/li&gt;
&lt;li&gt;work in the middle of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Pipeline_%28Unix%29&quot;&gt;pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;be useful as a reference for other implementors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Existing Code&lt;/h2&gt;

&lt;p&gt;Since we have the original C++ code, we can count the number of lines in
it and run an estimate off that.  (I&apos;m actually using the unofficial
&lt;a href=&quot;http://www.hydrogenaudio.org/forums/index.php?showtopic=21860&quot;&gt;Linux port&lt;/a&gt;.) Here&apos;s a partial output from &lt;a href=&quot;http://www.dwheeler.com/sloccount/&quot; title=&quot;David Wheeler&amp;#39;s SLOCCount&quot;&gt;sloccount&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Total Physical Source Lines of Code (SLOC)                = 19,611
Development Effort Estimate, Person-Years (Person-Months) = 4.55 (54.62)
Schedule Estimate, Years (Months)                         = 0.95 (11.43)
Please credit this data as &quot;generated using David A. Wheeler&apos;s &apos;SLOCCount&apos;.&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might be wondering why I wrote jest instead of just using sloccount.
Well, sloccount is meant for counting lines in existing code, with some
estimates thrown in.  Jest is meant for estimating code that hasn&apos;t been
written yet.  There&apos;s an overlap when you&apos;re cloning something you have
the source code to, but in general they do different things -- we&apos;ll see
that later.&lt;/p&gt;

&lt;p&gt;Plugging the count into &lt;code&gt;jest-effort&lt;/code&gt; gives:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-effort 19611
months: 15 (4 to 59)
people: 5 (1 to 21)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The answer is a little bit different because jest uses version two of
the &lt;a href=&quot;http://sunset.usc.edu/research/COCOMOII/&quot; title=&quot;Constructive Cost Model&quot;&gt;COCOMO&lt;/a&gt; formulas, while sloccount uses version one.  (These are
full-time months.)&lt;/p&gt;

&lt;p&gt;Let&apos;s forget about trying to recreate the entire Monkey&apos;s Audio package.
We&apos;ll restrict it to just the core maclib library and the command-line
interface:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sloccount mac-3.99-u4-b4/src/Console mac-3.99-u4-b4/src/MACLib
Total Physical Source Lines of Code (SLOC)                = 7,642
Development Effort Estimate, Person-Years (Person-Months) = 1.69 (20.30)
Schedule Estimate, Years (Months)                         = 0.65 (7.85)
Please credit this data as &quot;generated using David A. Wheeler&apos;s &apos;SLOCCount&apos;.&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That gives:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-effort 7642
months: 11 (3 to 42)
people: 3 (1 to 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Function Points&lt;/h2&gt;

&lt;p&gt;There&apos;s another way we can estimate the number of lines we&apos;ll have to
write.  Instead of looking at an existing program that does (sort of)
the same thing, we can estimate it from the specs.&lt;/p&gt;

&lt;p&gt;The COCOMO II model does this using
&lt;a href=&quot;http://www.codeproject.com/useritems/Calculate_Function_Point.asp&quot;&gt;unadjusted function points&lt;/a&gt;,
and jest implements them in the &lt;code&gt;jest-lines&lt;/code&gt; program.
The easiest way to use it is to write a file like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#type   elems   groups
ei      24      2       #External Input: the ape file
ilf     23      3       #Internal Logical File: ape metadata
ilf     1       1       #Internal Logical File: compressed sound

ilf     15      3       #wav header
ilf     1       1       #uncompressed sound
eo      16      2       #External Output: wav file
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Check the link above or &lt;code&gt;jest-lines --help&lt;/code&gt; for details on element and
group counting.)&lt;/p&gt;

&lt;p&gt;Then to estimate the lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-lines &amp;lt;points.txt
4506
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why is this so different?  We&apos;re getting a line estimate that&apos;s much
lower than our line count.  A few things to consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We may be wrong.&lt;/li&gt;
&lt;li&gt;Although we narrowed our count down to only the library and the
    command-line interface, it still included compression and
    editing.  This new estimate only includes decompression.&lt;/li&gt;
&lt;li&gt;The number of lines per function point depends on the language.
    You can specify this, but we&apos;ve just used the default.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Refinement&lt;/h2&gt;

&lt;p&gt;Now we&apos;re going to refine the estimate.  First, we&apos;ll specify a language:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-lines --language haskell &amp;lt;points.txt
2771
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;http://www.haskell.org/&quot; title=&quot;a general purpose, purely functional programming language&quot;&gt;Haskell&lt;/a&gt; is fairly compact language, so our line estimate is smaller
than when we were using the default.  (In C++, the language of the
original maclib, it comes out to 5313.)  Let&apos;s put our most recent line
estimates into the effort estimator:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-effort $(jest-lines &amp;lt;points.txt)
months: 9 (2 to 35)
people: 2 (0 to 7)

$ jest-effort $(jest-lines --language haskell &amp;lt;points.txt)
months: 7 (2 to 30)
people: 1 (0 to 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&apos;s use some ratings.  We&apos;ll just pick a few that really stand out
-- areas where this project seems far from average:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jest-effort --team=easy --language_experience=hard --documentation=hard $(jest-lines --language haskell &amp;lt;points.txt)
months: 8 (2 to 31)
people: 1 (0 to 6)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&apos;ll have a team that gets along great, consisting of one person, but I
don&apos;t know the language very well.  Also, the documentation has to be
very good because this is supposed to be a reference that other
implementors can use.&lt;/p&gt;

&lt;h2&gt;What Does It All Mean?&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If we keep it simple and all goes well, this program can be written by
a single person in a reasonable amount of time.&lt;/li&gt;
&lt;li&gt;Project scope has a big impact.&lt;/li&gt;
&lt;li&gt;Estimating in different ways and for different scenarios gives us a
much clearer picture.&lt;/li&gt;
&lt;li&gt;There&apos;s no one correct estimate.  There&apos;s a collection of decent
estimates, and they collectively sketch out what&apos;s likely to happen.&lt;/li&gt;
&lt;/ul&gt;</description>
  <comments>http://brian-jaress.livejournal.com/3801.html</comments>
  <category>jest</category>
  <category>ape</category>
  <category>programming</category>
  <lj:mood>satisfied</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/3530.html</guid>
  <pubDate>Mon, 28 May 2007 06:58:17 GMT</pubDate>
  <title>R6RS Ratification Registration</title>
  <link>http://brian-jaress.livejournal.com/3530.html</link>
  <description>&lt;p&gt;I just sent in a registration &lt;a href=&quot;http://www.r6rs.org/ratification/registration.txt&quot;&gt;form&lt;/a&gt; for voting on &lt;a href=&quot;http://www.r6rs.org/&quot; title=&quot;the (possible) next version of Scheme&quot;&gt;R6RS&lt;/a&gt;
&lt;a href=&quot;http://www.r6rs.org/ratification/&quot;&gt;ratification&lt;/a&gt;, which is somewhat &lt;a href=&quot;http://groups.google.com/group/comp.lang.scheme/browse_thread/thread/f7ad9d0350313d55/f70b569c2522a15c?lnk=raot#f70b569c2522a15c&quot; title=&quot;heated debate on comp.lang.scheme&quot;&gt;controversial&lt;/a&gt;.  The form
itself is in &lt;a href=&quot;http://www.schemers.org/Documents/Standards/R5RS/&quot; title=&quot;the existing standard&quot;&gt;R5RS&lt;/a&gt; &lt;a href=&quot;http://www.schemers.org&quot;&gt;Scheme&lt;/a&gt;, which is kind of neat:
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;((email-address &quot;___@___&quot;)
 (full-name &quot;Brian Jaress&quot;)
 (geographic-location &quot;Honolulu, HI, USA&quot;)
 (web-page-url &quot;http://brian-jaress@livejournal.com&quot;)
 (statement-of-interest
&quot;I&apos;m a programmer who&apos;s fairly new to Scheme.

To me, the most important proposed changes in R6RS are the standard
module system and the standard libraries.  The core language in R5RS is
great, but the decision to use it always seems to create extra work
because of missing libraries.  There are extensions for most of the
basic things that usually come with a language (sorting, hash tables,
modules, etc.) but the fact that they are nonstandard creates extra work
of its own as far as compatibility and portability.

I haven&apos;t looked at every detail of the module system and libraries, but
they look a lot better than nothing.

One thing I&apos;m not enthusiastic about in the current draft is the fact
that the built-in procedures are still not polymorphic.  For example,
having a single procedure called &apos;sort&apos; that checks the type of the
argument to be sorted is perfectly possible.  It might be a little
faster to have a separate &apos;list-sort&apos; and &apos;vector-sort,&apos; but I don&apos;t
think it&apos;s worth it.  I also think there&apos;s no real benefit to explicitly
stating the type when you sort it.  When you&apos;re creating or using it,
maybe, but not when you&apos;re sorting it.&quot;))
&lt;/code&gt;&lt;/pre&gt;</description>
  <comments>http://brian-jaress.livejournal.com/3530.html</comments>
  <category>r6rs</category>
  <category>scheme</category>
  <category>programming</category>
  <lj:mood>hopeful</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/3127.html</guid>
  <pubDate>Wed, 09 May 2007 07:01:25 GMT</pubDate>
  <title>Functional Sorting in Scheme with Pairing Heaps</title>
  <link>http://brian-jaress.livejournal.com/3127.html</link>
  <description>&lt;p&gt;As part of learning the language, I was looking for a way to implement
sorting in &lt;a href=&quot;http://schemers.org&quot; title=&quot;The Scheme Programming Language&quot;&gt;Scheme&lt;/a&gt;.  I wanted something:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to implement in Scheme, preferably in a functional style&lt;/li&gt;
&lt;li&gt;Somewhat lazy, so I could skip a lot of the processing if I only
wanted the first few items&lt;/li&gt;
&lt;li&gt;Reasonably fast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found &lt;a href=&quot;http://www.cs.cmu.edu/~sleator/papers/Pairing-Heaps.htm&quot; title=&quot;The Pairing Heap: A New Form of Self-Adjusting Heap&quot;&gt;pairing heaps&lt;/a&gt;.
&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;http://en.wikipedia.org/wiki/Heapsort#Overview&quot;&gt;heapsort&lt;/a&gt; using any kind of &lt;a href=&quot;http://en.wikipedia.org/wiki/Heap_%28data_structure%29&quot;&gt;heap&lt;/a&gt; by putting the items in
and then taking them out again, but pairing heaps looked like the
easiest to do in Scheme.  Linking two heaps is done just by making one
root a child of the other.&lt;/p&gt;

&lt;p&gt;The only trick is that when you delete the root, you link the children
in a certain order. First link them into pairs, then link the pairs.
I&apos;m using the &quot;front-to-back variant,&quot; meaning that the children are
paired off going two at a time from newest to oldest, and the pairs are
then also linked from newest to oldest.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;pairing heap represented as
;(parent newest-child second-newest-child ...)
(define (ph-min heap) (car heap))

;combine two heaps
(define (ph-link &amp;lt;? x y)
    (cond
        ((not (pair? x)) y)
        ((not (pair? y)) x)
        ((&amp;lt;? (car x) (car y)) (ph-link &amp;lt;? y x))
        (else (cons
            (car y)
            (cons x (cdr y))
        ))
    )
)

(define (ph-insert &amp;lt;? heap item) (ph-link &amp;lt;? heap (list item)))

;remove the smallest item
(define (ph-delmin &amp;lt;? heap)
    (let loop ((accum &apos;()) (sibs (cdr heap)))
        (cond
            ((not (pair? sibs)) accum)
            (
                (not (pair? (cdr sibs)))
                (ph-link &amp;lt;? accum (car sibs))
            )
            (else (loop
                (ph-link &amp;lt;? (ph-link &amp;lt;? (car sibs) (cadr sibs)) accum)
                (cddr sibs)
            ))
        )
    )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The heaps are represented as nested lists with the root at the head, so
&lt;code&gt;(1 (2 (2)) (3) (1))&lt;/code&gt; is a heap with a one at the root and three
subheaps.  After deleting the root, you would have &lt;code&gt;(1 (2 (3) (2)))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since the goal was to implement it myself and learn by doing, I didn&apos;t
look for other implementations until afterwards.  If you want something
more polished, there&apos;s a full-featured &lt;a href=&quot;http://www.accesscom.com/~darius/software/scheme-data-structures/pairing-heap.scm&quot;&gt;implementation&lt;/a&gt; using
closures by &lt;a href=&quot;http://www.accesscom.com/~darius&quot;&gt;Darius Bacon&lt;/a&gt; and a &lt;a href=&quot;http://schemecookbook.org/Cookbook/FunctionalHeap&quot;&gt;recipe&lt;/a&gt; at the
&lt;a href=&quot;http://schemecookbook.org/&quot;&gt;Schematics Scheme Cookbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To turn the heap functions into a sorting program, you need some code to
read lines, stick them in the heap, take them out again, and print them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(define (read-line) (let loop ((l &quot;&quot;) (c (read-char)))
    (cond
        ((and (eof-object? c) (string=? l &quot;&quot;)) c)
        ((or (eof-object? c) (char=? c #\newline)) l)
        (else (loop (string-append l (string c)) (read-char)))
    )
))

(define lineheap (let loop
    (
        (heap &apos;())
        (l (read-line))
    )
    (if (not (eof-object? l))
        (loop (ph-insert string&amp;lt;? heap l) (read-line))
        heap
    )
))

(let loop ((heap lineheap))
    (if (pair? heap)
        (begin
            (display (ph-min heap))
            (newline)
            (loop (ph-delmin string&amp;lt;? heap))
        )
    )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The funny thing about pairing heaps is that their time-complexity doesn&apos;t
seem to be completely proven yet.  The most recent thing I can find is a
&lt;a href=&quot;http://portal.acm.org/citation.cfm?id=320214&quot; title=&quot;On the efficiency of pairing heaps and related data structures&quot;&gt;paper&lt;/a&gt; on the &lt;code&gt;decrease-key&lt;/code&gt; operation (which isn&apos;t needed
for sorting) and no apparent progress on &lt;code&gt;delete-min&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I compiled this bare-bones sorter using an &lt;a href=&quot;http://en.wikipedia.org/wiki/Stalin_(Scheme_implementation)&quot; title=&quot;The Stalin Scheme compiler&quot;&gt;aggressive compiler&lt;/a&gt;
and timed it for a few runs on a scrambled version of the &lt;a href=&quot;http://codekata.pragprog.com/2007/01/kata_six_anagra.html&quot;&gt;kata 6&lt;/a&gt;
wordlist.  It took about five times as long as &lt;a href=&quot;http://www.gnu.org/software/coreutils/&quot; title=&quot;part of coreutils&quot;&gt;GNU sort&lt;/a&gt;.  (I&apos;m
running &lt;a href=&quot;http://www.debian.org/&quot; title=&quot;Debian GNU/Linux&quot;&gt;Debian&lt;/a&gt; on a 1.5 GHz Sempron, and it was roughly 1.85s vs
0.34s.)&lt;/p&gt;

&lt;p&gt;Of course, my little test runs aren&apos;t as good as the serious testing
that researchers have done, and this program isn&apos;t even close to being a
good replacement for GNU sort.&lt;/p&gt;

&lt;p&gt;But the pairing heaps are neat.&lt;/p&gt;</description>
  <comments>http://brian-jaress.livejournal.com/3127.html</comments>
  <category>scheme</category>
  <category>programming</category>
  <lj:mood>pleased</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>http://brian-jaress.livejournal.com/3000.html</guid>
  <pubDate>Mon, 30 Apr 2007 07:10:11 GMT</pubDate>
  <title>The Mysterious Kata</title>
  <link>http://brian-jaress.livejournal.com/3000.html</link>
  <description>&lt;p&gt;I heard about &lt;a href=&quot;http://codekata.pragprog.com/&quot;&gt;code katas&lt;/a&gt; and thought, &quot;Hey, that sounds kind of
fun.&quot;  I also thought it might be a good way to learn a new language: do
a kata in a language you&apos;re familiar with, then do it again in one
you&apos;re learning.  Then I hit a snag: the &lt;a href=&quot;http://codekata.pragprog.com/2007/01/kata_six_anagra.html&quot; title=&quot;Kata 6&quot;&gt;kata&lt;/a&gt; I started with
comes with a correct result that no one except the creator reports
getting.  Phooey.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea is to read in a list of words, then print out groups of
one-word &lt;a href=&quot;http://en.wikipedia.org/wiki/Anagram&quot;&gt;anagrams&lt;/a&gt;.  For his &lt;a href=&quot;http://pragdave.pragprog.com/data/wordlist.txt&quot;&gt;sample input&lt;/a&gt;, creator Dave Thomas
reports 2,530 groups totaling 5,680.&lt;/p&gt;

&lt;p&gt;I, on the other hand, was getting 2,531 groups with 5,683 words.  That
came from doing it case-insensitive without stripping digits or
punctuation (the sample list contains prefixes like &quot;Sino-&quot; and names
like &quot;Modula-2&quot;).  The description that Dave gives is a little loose, so
I tried tweaking the case sensitivity, punctuation, etc.  No luck.&lt;/p&gt;

&lt;p&gt;Then I tried Google.&lt;/p&gt;

&lt;p&gt;I found people &lt;a href=&quot;http://www.codeodor.com/index.cfm/2007/3/6/Anagrams-in-Ruby/1015&quot;&gt;saying&lt;/a&gt; they&apos;ve done the kata but haven&apos;t
tested it on the sample input.  I found people &lt;a href=&quot;http://wiki.pragprog.com/cgi-bin/wiki.cgi/CodeKatasSix&quot;&gt;reporting&lt;/a&gt; how
&lt;a href=&quot;http://www.bright-green.com/blog/2003_06_11/attempt_at_kata_6.html&quot;&gt;fast&lt;/a&gt; their solution was but not how many words and groups it
output. I also found people &lt;a href=&quot;http://yacheng-meng.blogspot.com/2007/02/code-kataanagram.html&quot;&gt;reporting&lt;/a&gt; &lt;a href=&quot;http://www.artima.com/forums/flat.jsp?forum=121&amp;amp;thread=6116&quot;&gt;various&lt;/a&gt;
&lt;a href=&quot;http://www.joeygibson.com/blog/tech/lisp/Kata6Lisp.html&quot;&gt;other&lt;/a&gt; &lt;a href=&quot;http://mail.python.org/pipermail/tutor/2003-November/026178.html&quot;&gt;results&lt;/a&gt; on the sample input.  I guess it&apos;s
comforting that the results I got seem popular.&lt;/p&gt;

&lt;p&gt;I&apos;m going to ask Dave Thomas to post his code.  I don&apos;t know Ruby, but
it&apos;s probably easier to puzzle out his program than continue the
equivalent of reading tea leaves.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Here&apos;s my code, in Python:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#! /usr/bin/env python

#http://codekata.pragprog.com/2007/01/kata_six_anagra.html

from sys import stdin

def extract(word):
    letters = word.lower()
    return &apos;&apos;.join(sorted(list(letters)))

seen = {}

for line in stdin:
    word = line.strip()
    letters = extract(word)
    if letters not in seen:
        seen[letters] = []
    seen[letters].append(word)

for group in seen.values():
    if len(group) &amp;gt; 1:
        print &apos; &apos;.join(group)
&lt;/code&gt;&lt;/pre&gt;</description>
  <comments>http://brian-jaress.livejournal.com/3000.html</comments>
  <category>programming</category>
  <category>katas</category>
  <lj:mood>frustrated</lj:mood>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
</item>
</channel>
</rss>
