<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-18302393</id><updated>2011-07-28T10:35:12.623-07:00</updated><category term='todo'/><category term='design'/><category term='scheme'/><category term='education'/><category term='math'/><category term='knuth'/><category term='git'/><category term='alloy'/><category term='logic'/><category term='zelda'/><category term='C'/><category term='latex'/><title type='text'>hashcollision</title><subtitle type='html'>(modulo life human-brain) --&gt; (and confusion inquiry)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>51</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-18302393.post-3676338349823531414</id><published>2011-05-08T21:17:00.000-07:00</published><updated>2011-05-08T21:18:30.174-07:00</updated><title type='text'>Migration</title><content type='html'>I'll be moving this blog to &lt;a href="http://blog.hashcollision.org"&gt;http://blog.hashcollision.org&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-3676338349823531414?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/3676338349823531414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=3676338349823531414' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3676338349823531414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3676338349823531414'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2011/05/migration.html' title='Migration'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-5308061069555333776</id><published>2010-04-17T19:16:00.000-07:00</published><updated>2010-04-17T19:33:32.543-07:00</updated><title type='text'>shimmer</title><content type='html'>One of my favorite &lt;a href="http://apple.com"&gt;companies&lt;/a&gt; is trying to &lt;a href="http://www.freedom-to-tinker.com/blog/felten/flash-scratch-ajax-apples-war-programming"&gt;kill&lt;/a&gt; my active area of research and personal interest.  When Apple engages to hurt children, when they enforce a discriminatory and &lt;a href="http://37signals.com/svn/posts/2273-five-rational-arguments-against-apples-331-policy"&gt;irrational&lt;/a&gt; policy, then they've crossed a terrible line.  I've listened to the &lt;a href="http://daringfireball.net/2010/04/why_apple_changed_section_331"&gt;counterarguments&lt;/a&gt;, but I can only conclude that what they're doing here is morally wrong.&lt;br /&gt;&lt;br /&gt;The iPhone has lost its shimmer for me.  Time for a new &lt;a href="http://developer.android.com/"&gt;phone&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-5308061069555333776?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/5308061069555333776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=5308061069555333776' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5308061069555333776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5308061069555333776'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2010/04/shimmer.html' title='shimmer'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-3037854163050452713</id><published>2008-07-22T17:46:00.000-07:00</published><updated>2008-07-22T17:50:37.474-07:00</updated><title type='text'>quilty</title><content type='html'>I wonder if Nabokov would &lt;a href="http://www.afterdawn.com/news/archive/3693.cfm"&gt;laugh&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I need to stop doing things that make me feel guilty.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-3037854163050452713?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/3037854163050452713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=3037854163050452713' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3037854163050452713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3037854163050452713'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2008/07/quilty.html' title='quilty'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-2870087273788673795</id><published>2008-06-01T13:34:00.000-07:00</published><updated>2008-06-01T14:17:32.900-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>decentralize</title><content type='html'>I've been using &lt;a href="http://git.or.cz/"&gt;git&lt;/a&gt; for my source code control, and I'm happy I switched to it.  I found out recently that my hosting service was &lt;a href="http://www.dslreports.com/forum/r20570844-Fire-at-the-Planet"&gt;burning&lt;/a&gt;; apparently something electrical exploded, knocking out a few of webfaction's servers.&lt;br /&gt;&lt;br /&gt;I noticed the problem only when I was trying to &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#pushing-changes-to-a-public-repository"&gt;push&lt;/a&gt; my changes upstream from my machine back to the mothership.&lt;br /&gt;&lt;br /&gt;Long pause, no motion.&lt;br /&gt;&lt;br /&gt;No problem.  I canceled the push, and just continued to work and commit changes to my local machine.&lt;br /&gt;&lt;br /&gt;I remember back at my previous workplace how the knockout of our main &lt;a href="http://subversion.tigris.org"&gt;svn&lt;/a&gt; server meant we got to take the day off because we couldn't get any work done.  Of course, I'm not telling the whole story.  Not only was that server knocked out, but the whole building in general: we had a power outtage for a few hours.  So that somewhat undercuts the story a little; decentralizing our source code server still wouldn't have saved us on that day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-2870087273788673795?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/2870087273788673795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=2870087273788673795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/2870087273788673795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/2870087273788673795'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2008/06/decentralize.html' title='decentralize'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-7534604872635461885</id><published>2008-01-10T20:29:00.001-08:00</published><updated>2008-01-10T20:30:37.933-08:00</updated><title type='text'>happy birthday</title><content type='html'>I didn't realize that &lt;a href="http://www-cs-faculty.stanford.edu/~knuth/"&gt;Don Knuth&lt;/a&gt;'s birthday was today.  Happy birthday Professor Knuth!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-7534604872635461885?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/7534604872635461885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=7534604872635461885' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/7534604872635461885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/7534604872635461885'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2008/01/happy-birthday.html' title='happy birthday'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-8891475391946006601</id><published>2007-11-25T14:04:00.000-08:00</published><updated>2007-11-25T14:55:28.557-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='alloy'/><category scheme='http://www.blogger.com/atom/ns#' term='zelda'/><title type='text'>zelda</title><content type='html'>I held my sword in front, and approached the &lt;a href="http://www.gamespot.com/features/6180482/p-24.html"&gt;village&lt;/a&gt; cautiously.  I would have to slaughter the terrible Yook monster disguised in one of the hapless villagers's homes.  I pushed the doors open, ready to hack and slash.  To my shock, all of the villagers looked exactly the same!&lt;br /&gt;&lt;br /&gt;And each had something to say about the other Anouki:&lt;br /&gt;&lt;br /&gt;    * FoFo said that Gumo was honest.&lt;br /&gt;    * Kumu said Mazo or Aroo was lying.&lt;br /&gt;    * Dobo said Mazo was honest.&lt;br /&gt;    * Gumo said Fofo or Aroo was lying.&lt;br /&gt;    * Aroo said Kumu was lying.&lt;br /&gt;    * Mazo said that he and Dobo were honest.&lt;br /&gt;&lt;br /&gt;How dastardly!  Only the Yook would lie to me.  And I couldn't just kill them all and let God sort them out.  I had to think about this. So I did what anyone in this circumstance would do: I pulled out &lt;a href="http://alloy.mit.edu/"&gt;Alloy&lt;/a&gt;.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;abstract sig Boolean {}&lt;br /&gt;one sig True, False extends Boolean {}&lt;br /&gt;&lt;br /&gt;abstract sig Anouki {&lt;br /&gt;    truthful: Boolean&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;one sig Fofo, Kumu, Dobo, Gumo, Aroo, Mazo extends Anouki {}&lt;br /&gt;&lt;br /&gt;pred whoTellsTruth {&lt;br /&gt;   Fofo.truthful = True implies Gumo.truthful=True&lt;br /&gt;   Kumu.truthful = True implies ((Mazo.truthful=False) or &lt;br /&gt;                                                          (Aroo.truthful=False))&lt;br /&gt;   Dobo.truthful = True implies Mazo.truthful=True&lt;br /&gt;   Gumo.truthful = True implies ((Fofo.truthful=False) or&lt;br /&gt;                                                          (Aroo.truthful=False))&lt;br /&gt;   Aroo.truthful = True implies (Kumu.truthful=False)&lt;br /&gt;   Mazo.truthful = True implies (Mazo.truthful=True and &lt;br /&gt;                                                         Dobo.truthful=True)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred onlyOneIsLying {&lt;br /&gt;    one a: Anouki | a.truthful=False&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;run {&lt;br /&gt;    whoTellsTruth&lt;br /&gt;    onlyOneIsLying&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Ah ha!  But as I was about to raise my gleaming blade against the trembling liar, doubt came to my mind: what if there were two of them out there?  Or three, or four?  I thought: perhaps I should plan this out more carefully before executing my righteous justice.  And maybe I should rewrite the model a little more to make it more general: who knows how many villages of liars I might run across?&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* Anouki can be friendly or antagonistic to other Anouki */&lt;br /&gt;sig Anouki {&lt;br /&gt;   supports: set Anouki,&lt;br /&gt;   denies: set Anouki&lt;br /&gt;} {&lt;br /&gt;   /* and it's nonsensical to be both supportive and antagonistic of&lt;br /&gt;      the same Anouki. */&lt;br /&gt;   no (supports &amp; denies)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* A village consists of folks who tell the truth, and symmetrically,&lt;br /&gt;   those who lie.  And we will categorically make every Anouki a&lt;br /&gt;   truthteller or a liar. */&lt;br /&gt;one sig Village {&lt;br /&gt;   truthtellers: set Anouki,&lt;br /&gt;   liars: set Anouki&lt;br /&gt;} {&lt;br /&gt;   no truthtellers &amp; liars&lt;br /&gt;   Anouki = truthtellers + liars&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;fact truthiness {&lt;br /&gt;   all a : Village.truthtellers {&lt;br /&gt;      all a' : a.supports | a' in Village.truthtellers&lt;br /&gt;      all a': a.denies | a' not in Village.truthtellers&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Here's what everyone says about each other */&lt;br /&gt;pred hearsay {&lt;br /&gt;   some disj fofo, kumu, dobo, gumo, aroo, mazo : Anouki {&lt;br /&gt;      fofo.supports = gumo&lt;br /&gt;      fofo.denies = none&lt;br /&gt;      kumu.supports = none&lt;br /&gt;      kumu.denies = mazo or kumu.denies = aroo&lt;br /&gt;      dobo.supports = mazo&lt;br /&gt;      dobo.denies = none&lt;br /&gt;      gumo.supports = none&lt;br /&gt;      gumo.denies = fofo or gumo.denies = aroo&lt;br /&gt;      aroo.supports = none&lt;br /&gt;      aroo.denies = kumu&lt;br /&gt;      mazo.supports = mazo + dobo&lt;br /&gt;      mazo.denies = none&lt;br /&gt;      fofo + kumu +dobo + gumo + aroo + mazo = Anouki&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred oneLiar {&lt;br /&gt;    hearsay and #Village.liars = 1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred twoLiars {&lt;br /&gt;   hearsay and #Village.liars = 2&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;run oneLiar for 6&lt;br /&gt;run twoLiars for 6&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Hours passed as I played out different scenarios.  By this time, the Yook had already run away, but I had a model I was happy with.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-8891475391946006601?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/8891475391946006601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=8891475391946006601' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8891475391946006601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8891475391946006601'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/11/zelda.html' title='zelda'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-8004987300280408250</id><published>2007-10-02T05:59:00.000-07:00</published><updated>2007-10-02T12:34:22.707-07:00</updated><title type='text'>consistency</title><content type='html'>There's so much work that I have to do, and I've realized that one of my personal failings is not necessarily the understanding of hard stuff.  Rather, it's getting the easy stuff even started.  &lt;br /&gt;&lt;br /&gt;It's a main point of &lt;a href="http://www.gawande.com/better.htm"&gt;Better&lt;/a&gt;: performance isn't about the shiny tools: it is more about the "gruntwork".  It's the mundane task of being consistent, of staying on target, with which I struggle and flounder about like a floppy fish.  My failure to do better isn't for lack of technical tools or skills: what I'm missing is consistency.  Adults should have the firmness of mind to do something even if there are no immediate results.  But my mind is still mushy and squishy.  It has the consistency of oatmeal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-8004987300280408250?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/8004987300280408250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=8004987300280408250' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8004987300280408250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8004987300280408250'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/10/consistency.html' title='consistency'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-3106504692104755073</id><published>2007-06-01T20:24:00.000-07:00</published><updated>2007-06-01T22:12:24.798-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='todo'/><category scheme='http://www.blogger.com/atom/ns#' term='alloy'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>lists 1</title><content type='html'>One of my research topics may involve &lt;a href="http://alloy.mit.edu"&gt;Alloy&lt;/a&gt; in its role as a language for developing software.  The problem is, I don't know Alloy quite well enough to use it in anger yet.  That's something I must fix.&lt;br /&gt;&lt;br /&gt;I need a nice, simple TODO list-keeping application, and so I'll try modeling it with Alloy.  I'll try to verbalize my thinking in real-time, just to show that software isn't written in a vacuum, but is revised and re-revised.&lt;br /&gt;&lt;br /&gt;These are the sort of things I'd want in a TODO list manager:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;I should be able to make Items, and going the other way, deleting should be a snap.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I should be able to assign items to Tags.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I should be able to easily share my TODO lists with other people.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;It's the last requirement that seems interesting to me; I'm not quite sure what I mean by this yet, but it involves some kind of security thing that I'll think about more in a moment.  But let me first start modeling the relationships between the items in my imaginary system.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module lists&lt;br /&gt;sig Person {&lt;br /&gt;    tags: set Tag,&lt;br /&gt;    items: set Item&lt;br /&gt;}&lt;br /&gt;sig Tag {}&lt;br /&gt;sig Public, Private extends Tag {}&lt;br /&gt;sig Item {&lt;br /&gt;    tags: set Tag&lt;br /&gt;}&lt;br /&gt;run {}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I'm thinking of a design like &lt;a href="http://del.icio.us/"&gt;delicious&lt;/a&gt;: a Person manages their TODO Items by tagging them.  I'll keep two special tags called &lt;tt&gt;Public&lt;/tt&gt; and &lt;tt&gt;Private&lt;/tt&gt;, which I'll plan to use to restrict views by other people.  Maybe it's premature to think about this...&lt;br /&gt;&lt;br /&gt;Oh, I do want to say that the tags that are associated with a person are the ones used in that person's items: at the moment, my software model leaves that unconstrained.  Let me fix that and revise the definition of a Person.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sig Person {&lt;br /&gt;    tags: set Tag,&lt;br /&gt;    items: set Item&lt;br /&gt;} {&lt;br /&gt;    tags = items.tags&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Em81XiCh6L8/RmDo7zl2XkI/AAAAAAAAAAs/Tw2IgjOI098/s1600-h/visualization-1.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_Em81XiCh6L8/RmDo7zl2XkI/AAAAAAAAAAs/Tw2IgjOI098/s320/visualization-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5071309294578064962" /&gt;&lt;/a&gt;&lt;br /&gt;At this point, I can ask Alloy: what would a possible situation of my model look like, by executing and showing a model.  Here's one sample visualization that the tool's giving me.&lt;br /&gt;&lt;br /&gt;Ok, but I haven't yet done anything about privacy yet; I need to model the items that a person might be looking at the moment.  Let me extend a Person to also include the items that they're currently looking at, and also assign an "owner" to each Item.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module lists&lt;br /&gt;sig Person {&lt;br /&gt;    tags: set Tag,&lt;br /&gt;    items: set Item,&lt;br /&gt;    viewing: set Item&lt;br /&gt;} {&lt;br /&gt;    tags = items.tags&lt;br /&gt;}&lt;br /&gt;sig Tag {}&lt;br /&gt;sig Public, Private extends Tag {}&lt;br /&gt;sig Item {&lt;br /&gt;    tags: set Tag,&lt;br /&gt;    owner: one Person&lt;br /&gt;}&lt;br /&gt;run {}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ok, so Items know who own them, so I should be able to write an expression capturing a notion of privacy.  It might not be completely right, but let me see what things look like.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;pred respectsPrivacy(p : Person) {&lt;br /&gt;    all i : p.viewing | permit[p, i]&lt;br /&gt;}&lt;br /&gt;pred permit(p : Person, i : Item) {&lt;br /&gt;    p = i.owner || Public in i.tags&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Cool.  Hmm, when I visualize this, though, the diagram's a little cluttered.  And on second thought, I don't really need to have a Person keep track of their items's tags explicitely: that's easily computable as a function.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sig Person {&lt;br /&gt;    items: set Item,&lt;br /&gt;    viewing: set Item&lt;br /&gt;}&lt;br /&gt;// Returns the tags used by a Person&lt;br /&gt;fun personalTags(p : Person) : set Tag {&lt;br /&gt;    p.items.tags&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ok, let me visualize again, with a more interesting scenario.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;pred show {&lt;br /&gt;    all p : Person | respectsPrivacy[p]&lt;br /&gt;    #Person &gt; 1&lt;br /&gt;    some p : Person | some i : Item {&lt;br /&gt;        permit[p, i] &amp;&amp; i.owner != p&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;run show&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Em81XiCh6L8/RmD0UTl2XlI/AAAAAAAAAA0/zUdm5IGuHFs/s1600-h/visualization-2.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_Em81XiCh6L8/RmD0UTl2XlI/AAAAAAAAAA0/zUdm5IGuHFs/s320/visualization-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5071321810112765522" /&gt;&lt;/a&gt;Wait a minute, the diagram doesn't look right at all.  Why does &lt;tt&gt;Person0&lt;/tt&gt; see &lt;tt&gt;Item0&lt;/tt&gt;: she doesn't own it.  Ooooh... I didn't tell my design that a &lt;tt&gt;Person&lt;/tt&gt;'s items must be owned by them.  Ooops.  I want to prevent panhandling.&lt;br /&gt;&lt;br /&gt;Actually, let me just simplify the model so that this issue doesn't even happen.  Just as I treated the personal tags as a function, I'll just make a &lt;tt&gt;personalItems&lt;/tt&gt; function to compute whenever I need it.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Returns a set of the items owned by this person.&lt;br /&gt;fun personalItems(p : Person) : set Item {&lt;br /&gt;    { i : Item | i.owner = p }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Here's my revised model so far.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module lists&lt;br /&gt;&lt;br /&gt;sig Person {&lt;br /&gt;    viewing: set Item&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;// Returns a set of the items owned by this person.&lt;br /&gt;fun personalItems(p : Person) : set Item {&lt;br /&gt;    { i : Item | i.owner = p }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Returns the tags used by a Person&lt;br /&gt;fun personalTags(p : Person) : set Tag {&lt;br /&gt;    p.personalItems.tags&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sig Tag {}&lt;br /&gt;sig Public, Private extends Tag {}&lt;br /&gt;&lt;br /&gt;sig Item {&lt;br /&gt;    tags: set Tag,&lt;br /&gt;    owner: one Person&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred respectsPrivacy(p : Person) {&lt;br /&gt;    all i : p.viewing | permit[p, i]&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred permit(p : Person, i : Item) {&lt;br /&gt;    p = i.owner || Public in i.tags&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;pred show {&lt;br /&gt;    all p : Person | respectsPrivacy[p]&lt;br /&gt;    #Person &gt; 1&lt;br /&gt;    some p : Person | some i : Item {&lt;br /&gt;        permit[p, i] &amp;&amp; i.owner != p&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;assert privateReallyMeansPrivate {&lt;br /&gt;    all i : Item | all p : Person {&lt;br /&gt;        (Private in i.tags &amp;&amp; permit[p, i]) implies (i.owner = p)&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;run show&lt;br /&gt;check privateReallyMeansPrivate&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I also added an assertion making sure that "private" really means private.  There are plenty of counterexamples!  It fails because my definition for permit() currently only cares about &lt;tt&gt;Public&lt;/tt&gt; at the moment, and it's very easy for an &lt;tt&gt;Item&lt;/tt&gt; to get tagged both with the &lt;tt&gt;Public&lt;/tt&gt; and &lt;tt&gt;Private&lt;/tt&gt; tag at once.&lt;br /&gt;&lt;br /&gt;This is pretty cool stuff!  To be able to talk about this software's design even without touching a single hashtable or SQL statement is really nice, and I'm already hitting core issues like handling privacy.  But since the post is getting a bit long, I'll stop for now and continue this when I get back to Massachusetts tomorrow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-3106504692104755073?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/3106504692104755073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=3106504692104755073' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3106504692104755073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3106504692104755073'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/06/lists-1.html' title='lists 1'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Em81XiCh6L8/RmDo7zl2XkI/AAAAAAAAAAs/Tw2IgjOI098/s72-c/visualization-1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-6107548192420967792</id><published>2007-05-30T21:06:00.001-07:00</published><updated>2007-05-30T21:19:40.268-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='knuth'/><title type='text'>powers of two</title><content type='html'>&lt;div style="float: right; margin-left: 10px; margin-bottom: 10px;"&gt; &lt;a href="http://www.flickr.com/photos/77386838@N00/522671065/" title="photo sharing"&gt;&lt;img src="http://farm1.static.flickr.com/214/522671065_2f1b14f8c8_m.jpg" alt="" style="border: solid 2px #000000;" /&gt;&lt;/a&gt; &lt;br /&gt; &lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;  &lt;a href="http://www.flickr.com/photos/77386838@N00/522671065/"&gt;Knuth Check&lt;/a&gt;  &lt;br /&gt;  Originally uploaded by &lt;a href="http://www.flickr.com/people/77386838@N00/"&gt;dyoo&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;One of my friends complained that I didn't put any interesting images on my blog.  So I promised him I'd post &lt;a href="http://en.wikipedia.org/wiki/Knuth_reward_check"&gt;something&lt;/a&gt; with an image on it.  I thought this photo would bring a smile to his face.&lt;br /&gt;&lt;br /&gt;Gotta love powers of two.&lt;br clear="all" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-6107548192420967792?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/6107548192420967792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=6107548192420967792' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6107548192420967792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6107548192420967792'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/05/powers-of-two.html' title='powers of two'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/214/522671065_2f1b14f8c8_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-1673641681367759183</id><published>2007-05-15T21:41:00.000-07:00</published><updated>2007-05-15T22:37:46.860-07:00</updated><title type='text'>turing</title><content type='html'>The thing that struck me about the Turing Test, when I heard about it, was the crazy thought: how do I know that other people are anything like me?  If we can't even judge faithfully between ourselves, how can we judge between humans and computers?  For I can do nothing but observe reactions, the effect of my actions on others.  I can't read people's minds: they could, for all I know, run entirely different mental software.  Everyone is, in some sense, a black box.&lt;br /&gt;&lt;br /&gt;The act of empathy, then, is a little presumptuous and magical: I trust that we can share an understanding with each other, with the assumption that because I share a similar hardware architecture with you, that there's a very strong chance that I share the same kinds of thoughts and values too.  I think that's why we put so much emphasis on physical bodies.  If someone looks different, I may fear them: they don't look like me, and so they might be thinking in an entirely different way.  We all know the dilemma of the Turing Test deep in our bones, and we cheat a little (or a lot) by using irrelevant physical similarities in our judgements of one another.&lt;br /&gt;&lt;br /&gt;I suppose I could be silly and wry and conclude that this is why women are mysterious and terrifying to me.&lt;br /&gt;&lt;br /&gt;But I think that there's something there that deserves more serious thinking.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-1673641681367759183?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/1673641681367759183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=1673641681367759183' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/1673641681367759183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/1673641681367759183'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/05/turing.html' title='turing'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-6193349356201302377</id><published>2007-05-09T11:43:00.000-07:00</published><updated>2007-05-09T12:51:39.238-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>aliasing renaming</title><content type='html'>People are often particular about naming.  Names still hold special power: we may rationalize that names don't matter, but there's something hardcoded in human beings about choosing the right name for a thing.  It's a hard thing to fight.&lt;br /&gt;&lt;br /&gt;Programmers are people too, and programmers also keep concerns (sometimes too much) about the right name for a thing.  As a concrete example, the word &lt;i&gt;lambda&lt;/i&gt; scares off a few people since it's a foreign word.  We might like to be &lt;a href="http://www.paulgraham.com/arclessons.html"&gt;brief&lt;/a&gt; and be able to say:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;    (def (make-adder x)&lt;br /&gt;      (fn (y) (+ x y)))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;where &lt;tt&gt;def&lt;/tt&gt; and &lt;tt&gt;fn&lt;/tt&gt; are really meant to behave like &lt;tt&gt;define&lt;/tt&gt; and &lt;tt&gt;lambda&lt;/tt&gt;, respectively.  One nice thing about Scheme is that it's plastic enough to absorb a trivial change like this.  Here's a small library for aliasing identifiers:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module alias mzscheme&lt;br /&gt;  ;; Practice writing macros that themselves generate macros.  &lt;br /&gt;  &lt;br /&gt;  (provide alias)&lt;br /&gt;  &lt;br /&gt;  ;; (alias old-keyword new-keyword)   SYNTAX&lt;br /&gt;  ;; Creates a new syntax for new-keyword; any occurrence of new-keyword&lt;br /&gt;  ;; is replaced with the old-keyword.&lt;br /&gt;  (define-syntax (alias stx-1)&lt;br /&gt;    (syntax-case stx-1 ()&lt;br /&gt;      [(_1 orig new)&lt;br /&gt;       (syntax/loc stx-1&lt;br /&gt;         (define-syntax (new stx-2)&lt;br /&gt;           (syntax-case stx-2 ()&lt;br /&gt;             [_2&lt;br /&gt;              (identifier? stx-2)&lt;br /&gt;              (syntax/loc stx-2&lt;br /&gt;                orig)]&lt;br /&gt;             [(_2 e (... ...))&lt;br /&gt;              (syntax/loc stx-2&lt;br /&gt;                (orig e (... ...)))])))])))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Once we have a tool like this, then we can test it out:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module test-alias mzscheme&lt;br /&gt;  (require "alias.ss")&lt;br /&gt;  (alias lambda fn)&lt;br /&gt;  (alias define def)&lt;br /&gt;  &lt;br /&gt;  (def (make-adder x)&lt;br /&gt;    (fn (y) (+ x y))))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;That being said, the above example is a silly thing to do.  Even in competent hands, this is easy to abuse; in the wrong hands, one can end up with something that belongs to an obfuscation contest.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&gt; (alias alias a)&lt;br /&gt;&gt; (a define d)&lt;br /&gt;&gt; (a if i)&lt;br /&gt;&gt; (d (f x) (i (= x 0) 1 (* x (f (- x 1)))))&lt;br /&gt;&gt; (f 3)&lt;br /&gt;6&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Communication between people means that we "come to terms", and the inherent abuse here is to turn the language into something that no one else can read.  In PLT Scheme's case, the above is especially bad because there's already an established mechanism for controlled renaming of identifiers as part of PLT Scheme's module system.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module test-alias mzscheme&lt;br /&gt;  (require (rename mzscheme fn lambda)&lt;br /&gt;           (rename mzscheme def define))&lt;br /&gt;  &lt;br /&gt;  (def (make-adder x) (fn (y) (+ x y))))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Still, I thought the macro definition was cute (even if it's silly), and it's one of the more  direct applications of a "macro-generating macro" that I've seen.  But maybe this is all just syntax, futzing with words, distracting us from the real work on nailing down the semantics of our thoughts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-6193349356201302377?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/6193349356201302377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=6193349356201302377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6193349356201302377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6193349356201302377'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/05/aliasing-renaming.html' title='aliasing renaming'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-7699360339586216506</id><published>2007-05-02T13:05:00.000-07:00</published><updated>2007-05-04T11:01:48.842-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>logical</title><content type='html'>I didn't get this so strongly before, but there's a correspondence between the language and structures of first-order logic, and the signatures and units of PLT Scheme (as well as the signatures and structures of ML).  I guess the analogy is something like: "language::signature as structure::unit."&lt;br /&gt;&lt;br /&gt;As a concrete example, a first-order language might just have equality (=), and a 2-arity P relation.  Once we have a language, we can start writing statements in that language.  Here are two statements using the language:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;    for all x, y, z: P(x, y) and P(x, z) implies y = z  &lt;/li&gt;&lt;br /&gt;&lt;li&gt;    for all x: there exists y: P(x, y)  &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;These two sentences, taken together, are trying to say "P must be a relation that represents a total function".  These sentences don't have a true or false value without being evaluated in the context of some structure.  A structure tells us what domain of thingies (the universe) we're iterating over when we say "for all" or "there exists", and also provides a concrete definition for the relations of the language.&lt;br /&gt;&lt;br /&gt;There are some structures that might satisfy this, and other structures that don't.  Structures that satisfy the sentences we care about are called "models".  One example of such a model for those two sentences might be the natural numbers (0, 1, 2, ...), where the interpretation of P is:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;    P(x, y)    if and only if y = square(x)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;But an example of a similar structure that wouldn't fit the above conditions would be natural numbers under a P that's not a function relation, like:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;    P(x, y)    if and only if x &amp;lt; y&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;and so we'd say that this structure isn't a model of those sentences.&lt;br /&gt;&lt;br /&gt;Programmers have an intuitive idea about this: it's similar to the distinction between "interface" and "implementation": the language provides the interface, and the structures provide implementations for that language.  And when we have an interface, we usually have some implicit idea of how that interface should behave; if we have an interface called &lt;i&gt;Stack&lt;/i&gt;, we have an expectation about what it should do.  We can make those assumptions explicit by writing contracts or predicates with that interface: the things that satisfy our expectations are good implementations.&lt;br /&gt;&lt;br /&gt;Again, to make this concrete, when we're programming with signatures and units, we first have to specify the things we're going to be fiddling with.  For example, a signature like:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  ;; A function^ model consists of a universe of elements,&lt;br /&gt;  ;; and a 2-place predicate P between elements.&lt;br /&gt;  (define-signature function^ (universe&lt;br /&gt;                               P))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;gives us a language for talking and using units that implement this signature.  For example, to build a unit where P is the squaring relation, we can do this:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  (define-unit squaring@&lt;br /&gt;    (import)&lt;br /&gt;    (export function^)&lt;br /&gt;    (define universe (list 0 1 2 3 4 '&gt;4))&lt;br /&gt;    (define (P x y)&lt;br /&gt;      (cond &lt;br /&gt;        [(equal? x '&gt;4)&lt;br /&gt;         (equal? y '&gt;4)]&lt;br /&gt;        [(&gt; (* x x) 4)&lt;br /&gt;         (equal? y '&gt;4)]&lt;br /&gt;        [else&lt;br /&gt;         (equal? y (* x x))])))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;(I'm defining the P function a bit peculiarly since I want the universe of elements to be finite.)&lt;br /&gt;&lt;br /&gt;But again, not all implementations of the &lt;tt&gt;function^&lt;/tt&gt; signature will do the right thing.  Here's a structure that doesn't satisfy the intent of the function^ signature.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  (define-unit less-than@&lt;br /&gt;    (import)&lt;br /&gt;    (export function^)&lt;br /&gt;    (define universe '(1 2 3))&lt;br /&gt;    (define (P x y)&lt;br /&gt;      (&amp;lt; x y)))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;How do we capture intent?  We want to be able to catch implementations that don't do what we expect, and one way is to write code to exercise the units.  Here's one example:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  ;; function-model?: function@ -&gt; boolean&lt;br /&gt;  ;; Checks to see if the given unit satisfies what we&lt;br /&gt;  ;; expect out of functions, that their domain is total&lt;br /&gt;  ;; and that each element of the domain maps to&lt;br /&gt;  ;; just one element of the range.&lt;br /&gt;  ;;&lt;br /&gt;  ;; In first-order logic:&lt;br /&gt;  ;;    (for all x, y, z: P(x, y) and P(x, z) implies y = z)&lt;br /&gt;  ;;    and&lt;br /&gt;  ;;    (for all x: there exists y: P(x, y))&lt;br /&gt;  (define (function-model? model@)&lt;br /&gt;    (local ((define-unit-binding a-model@&lt;br /&gt;              model@ (import) (export function^))&lt;br /&gt;            &lt;br /&gt;            (define-unit function-tester@&lt;br /&gt;              (import function^)&lt;br /&gt;              (export)&lt;br /&gt;              (and (for-all* (lambda (x y z)&lt;br /&gt;                               (implies? (and (P x y) (P x z))&lt;br /&gt;                                         (equal? y z)))&lt;br /&gt;                             universe universe universe)&lt;br /&gt;                   (for-all* (lambda (x)&lt;br /&gt;                               (exists? (lambda (y) (P x y))&lt;br /&gt;                                        universe))&lt;br /&gt;                             universe))))&lt;br /&gt;      (invoke-unit&lt;br /&gt;       (compound-unit/infer&lt;br /&gt;        (import)&lt;br /&gt;        (export)&lt;br /&gt;        (link a-model@ function-tester@)))))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;(There are a few definitions I've left out here; see &lt;a href="http://hashcollision.org/svn/repos/projects/plt-misc/logic-practice.ss"&gt;logic-practice.ss&lt;/a&gt; for the other definitions.)&lt;br /&gt;&lt;br /&gt;Once we have this, we can now check to see if &lt;tt&gt;squaring@&lt;/tt&gt; and &lt;tt&gt;less-than@&lt;/tt&gt; satisfy the &lt;tt&gt;function-model?&lt;/tt&gt; predicate.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (function-model? squaring@)&lt;br /&gt;#t&lt;br /&gt;&gt; (function-model? less-than@)&lt;br /&gt;#f&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-7699360339586216506?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/7699360339586216506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=7699360339586216506' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/7699360339586216506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/7699360339586216506'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/05/logical.html' title='logical'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-5709748688018702873</id><published>2007-04-30T22:20:00.000-07:00</published><updated>2007-04-30T22:58:25.140-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='logic'/><title type='text'>spring</title><content type='html'>It finally feels like spring has arrived here in Worcester.  The flowers are blooming from the trees, in great white poofy and pink blossoms.  After my first winter here on the East Coast, it feels glorious to stand outside and just soak in the sun.&lt;br /&gt;&lt;br /&gt;This semester is finally over.  I still feel a little unsatisifed with my performance in &lt;a href="http://web.cs.wpi.edu/~dd/"&gt;Dan&lt;/a&gt;'s logic class; the simplest things trip me up.  Ever time I do a logic session, I come out feeling mentally pummeled.  Brain &lt;a href="http://en.wikipedia.org/wiki/The_Karate_Kid"&gt;squish just like grape&lt;/a&gt;!  But not because the material's necessarily difficult, but just that I come in with so much mental confusion.&lt;br /&gt;&lt;br /&gt;For example,  I got confused with the concepts of &lt;a href="http://en.wikipedia.org/wiki/Skolem_hull"&gt;Skolem Hull&lt;/a&gt; and the &lt;a href="http://mathworld.wolfram.com/HerbrandUniverse.html"&gt;Herbrand universe&lt;/a&gt;, which are different concepts.  The Skolem Hull submodel only contains points that are interpretations of all the nameable elements of a language.  A Herbrand universe, on the other hand, is a set containing only the nameable terms themselves.  A hash collision.&lt;br /&gt;&lt;br /&gt;We talked about models that include "junk" (elements that can't be named by terms) and "confusion" (named terms that go to the same element).  It's funny, though, how the terms of logic are adopted by other subcultures, things like "&lt;a href="http://www.faqs.org/docs/artu/ch04s02.html#compactness"&gt;compactness&lt;/a&gt;" and the "&lt;a href="http://www.faqs.org/docs/artu/ch04s02.html#spot_rule"&gt;no junk, no confusion&lt;/a&gt;" properties, and in ways that are totally different from the definitions in mathematical logic.&lt;br /&gt;&lt;br /&gt;I should probably spend a few more days in the sun and try to weed out the junk and confusion in myself, the ill-formed and redundant thoughts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-5709748688018702873?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/5709748688018702873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=5709748688018702873' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5709748688018702873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5709748688018702873'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/04/spring.html' title='spring'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-8570707824195763816</id><published>2007-04-20T08:13:00.000-07:00</published><updated>2007-04-20T08:56:09.232-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>function of the day: fold</title><content type='html'>The fold function does very much what the name implies: it's meant to fold ingredients into a big mixing bowl, of course.  Here's a definition:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;;; fold: (ingredient bowl -&gt; bowl) bowl (listof ingredient) -&gt; bowl&lt;br /&gt;;; Folds in a list of ingredients into a bowl with a folding-action.&lt;br /&gt;(define (fold folding-action a-bowl ingredients)&lt;br /&gt;  (cond&lt;br /&gt;    [(empty? ingredients) a-bowl]&lt;br /&gt;    [else&lt;br /&gt;     (local ((define mixed-bowl (folding-action&lt;br /&gt;                                 (first ingredients)&lt;br /&gt;                                 a-bowl)))&lt;br /&gt;       (fold folding-action mixed-bowl (rest ingredients)))]))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;FOLD here adds an ingredient at a time, using the folding-action to mix in every ingredient thoroughly into our large bowl.  Once we have this incorporating function, we can roll up our sleeves and whisk some pancake batter:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;;; make-pancake-batter: -&gt; string&lt;br /&gt;;; Example of FOLD to make pancake batter.&lt;br /&gt;(define (make-pancake-batter)&lt;br /&gt;  (local ((define (whisk an-ingredient a-bowl)&lt;br /&gt;            (string-append a-bowl an-ingredient))&lt;br /&gt;          &lt;br /&gt;          (define pancake-ingredients '("flour" "sugar" "eggs" "milk"))&lt;br /&gt;          &lt;br /&gt;          (define empty-bowl ""))&lt;br /&gt;    (fold whisk empty-bowl pancake-ingredients)))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Oh!  I forgot the baking powder, so those pancakes will be a little stiff.  Oh well.&lt;br /&gt;&lt;br /&gt;Of course, we might even want to whisk in a slightly different way:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  (local&lt;br /&gt;      ((define (whisk an-ingredient a-bowl)&lt;br /&gt;         (cond [(string=? an-ingredient "eggs")&lt;br /&gt;                (string-append a-bowl "egg-white-only")]&lt;br /&gt;               [else&lt;br /&gt;                (string-append a-bowl an-ingredient)])))&lt;br /&gt;    (fold whisk "" '("flour" "eggs" "cabbage")))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Now we've got the basics of an okonomiyaki, I suppose.&lt;br /&gt;&lt;br /&gt;We might even be silly enough to mix things that aren't even food!&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&gt; (fold + 0 '(1 2 3 4 5))&lt;br /&gt;15&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;but this seems like a boring example compared to whisking.&lt;br /&gt;&lt;br /&gt;Folding is popular, but for some reason it goes by different names by different programming camps.  Python programmers call it &lt;a href="http://www.python.org/doc/lib/built-in-funcs.html#l2h-60"&gt;REDUCE&lt;/a&gt;, and Ruby programmers call it &lt;a href="http://www.ruby-doc.org/core/classes/Enumerable.html#M003171"&gt;INJECT&lt;/a&gt;.  I don't know about these names, though: I think they sound a little bit aggressive for my taste.  As for me, I like the homeliness of "fold": it reminds me of the kitchen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-8570707824195763816?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/8570707824195763816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=8570707824195763816' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8570707824195763816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/8570707824195763816'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/04/function-of-day-fold.html' title='function of the day: fold'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-5620904719327235212</id><published>2007-04-17T20:55:00.000-07:00</published><updated>2007-04-17T21:20:34.620-07:00</updated><title type='text'>death and taxes</title><content type='html'>I can't help feeling haunted about the deaths in yesterday's shooting.  The shooting itself makes no sense to me.&lt;br /&gt;&lt;br /&gt;I can appreciate that people are trying to find meaning in the murderer's actions, trying to blame video games, or psychotic drugs, or jealousy, or divine retribution.  It can't all be random, can it?&lt;br /&gt;&lt;br /&gt;I suppose there's a story about the murderer that remains to be told, the motives and the exposure of lurid, petty details.  Still, he is meaningless to me.&lt;br /&gt;&lt;br /&gt;I do see clear meaning in the actions of people like &lt;a href="http://en.wikipedia.org/wiki/Liviu_Librescu"&gt;Liviu Librescu&lt;/a&gt;.  How gloriously different are the saints.  I'd rather think about Professor Librescu and the others like him, who faced death with courage, teaching one final lesson: "Love is stronger than death."  Another one of those lessons that I'm trying to believe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-5620904719327235212?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/5620904719327235212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=5620904719327235212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5620904719327235212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5620904719327235212'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/04/death-and-taxes.html' title='death and taxes'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-5662170605130677040</id><published>2007-04-15T16:23:00.001-07:00</published><updated>2007-04-15T17:11:07.671-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><title type='text'>stick a fork() in it</title><content type='html'>Sometimes I really really dislike C for its low-levelness.&lt;br /&gt;&lt;br /&gt;Here's one concrete example why.  Predict the output of the following program:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char** argv) {&lt;br /&gt;  printf("hello world\n");&lt;br /&gt;  if (fork() == 0) {&lt;br /&gt;    printf("child\n");&lt;br /&gt;  } else {&lt;br /&gt;    printf("parent\n");&lt;br /&gt;  }&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;with the following:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;dyoo@dyoo-desktop:~/work/net-2$ gcc -Wall test-fork.c&lt;br /&gt;dyoo@dyoo-desktop:~/work/net-2$ ./a.out&lt;br /&gt;[predict your output here #1]&lt;br /&gt;dyoo@dyoo-desktop:~/work/net-2$ ./a.out | cat&lt;br /&gt;[predict your output here #2]&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Yes; I was surprised too, but #1 and #2 can produce different output.&lt;br /&gt;&lt;br /&gt;At least, this is what I see:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;dyoo@dyoo-desktop:~/work/net-2$ ./a.out&lt;br /&gt;hello world&lt;br /&gt;child&lt;br /&gt;parent&lt;br /&gt;dyoo@dyoo-desktop:~/work/net-2$ ./a.out | cat&lt;br /&gt;hello world&lt;br /&gt;child&lt;br /&gt;hello world&lt;br /&gt;parent&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The bug here is the interaction between the low-level fork() and the way that buffered output works in C.  In the second case, since I'm piping through &lt;tt&gt;cat&lt;/tt&gt;, there's more output buffering going on.  The first printf() is buffered and not immediately printed but rather stored somewhere.  The fork() duplicates the process.  So when both the child and parent processes close, they flush their respective buffers... and we see this unusual output.&lt;br /&gt;&lt;br /&gt;Some man pages do talk about this, like the one from &lt;a href="http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&amp;db=man&amp;fname=/usr/share/catman/p_man/cat3s/fflush.z"&gt;SGI IRIX&lt;/a&gt;.  Linux's man pages, &lt;a href="http://www.die.net/doc/linux/man/man3/fflush.3.html"&gt;not so much&lt;/a&gt;.  Ah well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-5662170605130677040?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/5662170605130677040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=5662170605130677040' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5662170605130677040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5662170605130677040'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/04/stick-fork-in-it.html' title='stick a fork() in it'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-525622107004240767</id><published>2007-04-12T21:39:00.000-07:00</published><updated>2007-04-12T22:06:34.732-07:00</updated><title type='text'>cyberdyne</title><content type='html'>I went to the &lt;a href="http://www.nepls.org/"&gt;NEPLS&lt;/a&gt; conference at Tufts University on Wednesday.  It was a lot of fun; I got to hear programming language theory talks and meet with other people interested in the same sort of crazy things that pull my attention.  I did like &lt;a href="http://www.ccs.neu.edu/home/dherman/"&gt;Dave&lt;/a&gt;'s talk: the idea of collapsing idempotent type checks to &lt;a href="http://www.ccs.neu.edu/home/dherman/research/publications/tfp07-gradual-typing.pdf"&gt;preserve space&lt;/a&gt; seemed perfectly reasonable.  I wonder if any of that will trickle back into PLT's contract system.&lt;br /&gt;&lt;br /&gt;The last presentation, on &lt;a href="http://www.nepls.org/Events/19/abstracts.html#bachrach"&gt;Spatial Computing&lt;/a&gt;, was especially fascinating. At a first glance, &lt;a href="http://people.csail.mit.edu/jrb/stp/stpg.htm"&gt;it&lt;/a&gt; seemed ridiculous, and the scope of the project so breathtakingly absurd.  I clamped my hands over my mouth to muffle my giggles.  But as the speaker presented &lt;a href="http://hdl.handle.net/1721.1/36840"&gt;more and more&lt;/a&gt;, the whimsical thought came into to me: maybe this is how &lt;a href="http://en.wikipedia.org/wiki/Skynet_%28fictional%29"&gt;Skynet&lt;/a&gt; begins.&lt;br /&gt;&lt;br /&gt;I hope that I too will someday build something that brings both laughter and pondering thoughts.  And I'll also keep in mind to try avoiding the development of systems that might lead to the creation of bloodthirsty androids.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-525622107004240767?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/525622107004240767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=525622107004240767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/525622107004240767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/525622107004240767'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/04/cyberdyne.html' title='cyberdyne'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-3457534215907380361</id><published>2007-03-30T14:47:00.000-07:00</published><updated>2007-03-30T15:06:33.046-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>birthday</title><content type='html'>I felt a little silly today, and just learned about SRFI 42 (Eager Comprehensions), so I thought I might play with it on a trivial example.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(module happy-birthday-song mzscheme&lt;br /&gt;  (require (lib "etc.ss")&lt;br /&gt;           (lib "42.ss" "srfi"))&lt;br /&gt;  &lt;br /&gt;  (provide sing)&lt;br /&gt;&lt;br /&gt;  ;; sing: string -&gt; void&lt;br /&gt;  ;; Prints out the popular happy birthday stanza.&lt;br /&gt;  (define (sing person)&lt;br /&gt;    (local ((define (trailer i)&lt;br /&gt;              (cond [(= i 2)&lt;br /&gt;                     (format "dear ~a" person)]&lt;br /&gt;                    [else&lt;br /&gt;                     "to you"])))&lt;br /&gt;      (do-ec (: i 4)&lt;br /&gt;             (begin&lt;br /&gt;               (display "Happy birthday ")&lt;br /&gt;               (display (trailer i))&lt;br /&gt;               (newline))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-3457534215907380361?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/3457534215907380361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=3457534215907380361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3457534215907380361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3457534215907380361'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/03/birthday.html' title='birthday'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-9197706018072609972</id><published>2007-03-29T20:28:00.000-07:00</published><updated>2007-03-29T21:05:13.756-07:00</updated><title type='text'>forgive</title><content type='html'>It's one thing to intone in a dull monotony: "Forgive those who trespass against us," where repetition drains the blood out of a revolutionary and crazy idea.  It's quite another thing to try to put the spirit of forgiveness into real action.  Serious forgiveness seems to me something superhuman, and I'm finding it hard to do.&lt;br /&gt;&lt;br /&gt;Early Monday, right around 1am, I got taken by a pair of con artists who pretended they needed to make an emergency call outside.  I let them use my cell, and when they handed the phone back, I didn't realize they'd yanked the battery and the SIM chip inside.&lt;br /&gt;&lt;br /&gt;Still, I did get the physical phone back, and there wasn't really much damage, except one night of uneasy sleep and an afternoon buying cellphone components.  I should say that I forgive the people who did this to me.  A part of me tries doing so, but another part feels that it's a baldfaced lie, and I catch myself wanting something bad, something karmic to happen to the thieves.&lt;br /&gt;&lt;br /&gt;But I think about it some more.  Frankly, I got off easy: it could have been a lot more perilous, because the two thieves could have gone after much more than my cellphone.  The guy had me in a bear hug at one point, pretending to be thankful.  I couldn't get out of his grip.  He could have squeezed me more tightly, and then I would have been in real trouble.  So I am thankful and lucky not to have been crushed in this encounter.&lt;br /&gt;&lt;br /&gt;If something this insignificant raises my ire, how hard it must be to forgive when people truly hurt each other!  It just makes me wonder.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-9197706018072609972?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/9197706018072609972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=9197706018072609972' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/9197706018072609972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/9197706018072609972'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/03/forgive.html' title='forgive'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-3469852125561682516</id><published>2007-03-01T18:56:00.000-08:00</published><updated>2007-03-01T19:22:18.773-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='education'/><title type='text'>Programmed Learning</title><content type='html'>As I was listening to Guy Steele from a &lt;a href="http://video.google.com/videoplay?docid=-4633168320660258097&amp;hl=en"&gt;talk&lt;/a&gt; he gave at Dan Friedman's 60th birthday, I was a little shocked when Guy voiced the relationship between B.F. Skinner's Programmed Learning method and the style of the conversation used in the Little Schemer.  &lt;br /&gt;I didn't really think of it that way, and now I'm trying to sort out why I have a negative feeling about Programmed Learning and positive feelings about The Little Schemer.&lt;br /&gt;&lt;br /&gt;What both seem to do right is quick iteration: rather than lecture (which bores me to tears), they instruct with a running conversation, Socratic style. I think what's different, at least in the examples that Guy gave, was the degree of difficulty in the questions.  In the examples with Skinner, the respondent answer in one-word sound bites, and there's a feeling of rote memorization and little thinking.  In contrast, in the Little Schemer, the questions require a lot more out of the student.  The stepping stones are spaced widely.&lt;br /&gt;&lt;br /&gt;So there are two ideas I'm picking out of this: just as in Agile development, I should be aiming toward iterative learning.  At the same time, even though the iterations are fairly regular, the goals in each iteration shouldn't be trivial, but have some real substance behind it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-3469852125561682516?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/3469852125561682516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=3469852125561682516' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3469852125561682516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/3469852125561682516'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/03/programmed-learning.html' title='Programmed Learning'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-5870387580556281939</id><published>2007-02-08T22:49:00.000-08:00</published><updated>2007-02-01T19:41:58.303-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>crazed</title><content type='html'>I think I came out a bit raving during Thursday's &lt;a href="http://web.cs.wpi.edu/~gpollice/Dojo.html"&gt;Coding Dojo&lt;/a&gt;; I did a quick-and-dirty derivation of the brute-force countdown program for last afternoon's session, and I only had an hour to work with.  Not only that, but I had to try to explain what I was doing while coding things up, and that almost inevitably gets me into trouble.  And I needed to write unit tests too.  And make unintentional mistakes to justify those unit tests.  I'll show one of those mistakes at the end of this post.&lt;br /&gt;&lt;br /&gt;Actually, it was really exciting!  But my body felt so totally exhausted at the end of it.  Much of it is performance, exaggerations and all.  My stage persona is one that's, well, a bit crazed.  I'm not exactly sure what the audience thought about it.  I hope folks thought was worth it and that the content was useful.&lt;br /&gt;&lt;br /&gt;The function where I made a mistake was this: we were writing a function to see if any number expression was reused.  One way to check for this condition is to do a depth-first traversal across the expression, watching to see if any number appears twice.&lt;br /&gt;&lt;br /&gt;Here's a variation of what I did:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(require (lib "plt-match.ss"))&lt;br /&gt;&lt;br /&gt;;; Data structures, of course, for our expressions:&lt;br /&gt;(define-struct num (n))&lt;br /&gt;(define-struct comb (left op right))&lt;br /&gt;&lt;br /&gt;;; is-legal?: expr -&gt; boolean&lt;br /&gt;;; Returns true if no num is reused more than once in the expression&lt;br /&gt;;; or its subexpressions.&lt;br /&gt;(define (is-legal? expr)&lt;br /&gt;  (define ht (make-hash-table))&lt;br /&gt;  &lt;br /&gt;  (define (seen-already? expr)&lt;br /&gt;    (hash-table-get ht expr #f))&lt;br /&gt;  &lt;br /&gt;  (define (mark-as-seen! expr)&lt;br /&gt;    (hash-table-put! ht expr #t))&lt;br /&gt;  &lt;br /&gt;  (let loop ([expr expr])&lt;br /&gt;    (match expr&lt;br /&gt;      [(struct num (n))&lt;br /&gt;       (cond&lt;br /&gt;         [(seen-already? n) #f]&lt;br /&gt;         [else&lt;br /&gt;          (mark-as-seen! expr)&lt;br /&gt;          #t])]&lt;br /&gt;      [(struct comb (l o r))&lt;br /&gt;       (and (loop l) (loop r))])))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Thankfully, I also wrote a test case.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(require (planet "test.ss" ("schematics" "schemeunit.plt"))&lt;br /&gt;         (planet "text-ui.ss" ("schematics" "schemeunit.plt")))&lt;br /&gt;&lt;br /&gt;(define simple-test-suite&lt;br /&gt;  (test-suite&lt;br /&gt;   "testing"&lt;br /&gt;   (test-true "check simple case"&lt;br /&gt;              (is-legal? (make-num 3)))&lt;br /&gt;   (let ([n1 (make-num 4)])&lt;br /&gt;     (test-false "check false"&lt;br /&gt;                 (is-legal? (make-comb n1 + n1))))))&lt;br /&gt;&lt;br /&gt;(test/text-ui simple-test-suite)&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And the test case quickly showed that I screwed up somewhere.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;Welcome to DrScheme, version 369.6-svn24jan2007 [3m].&lt;br /&gt;Language: Pretty Big (includes MrEd and Advanced Student).&lt;br /&gt;testing &gt; check false&lt;br /&gt;check false has a FAILURE&lt;br /&gt;name: check-false&lt;br /&gt;location: struct:object:...ascheme/diva-link.ss:124:4&gt;:39:5&lt;br /&gt;params: (#t)&lt;br /&gt;1 success(es) 1 failure(s) 0 error(s) 2 test(s) run&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Oh no!  Terror!  But thankfully, I figured out I had made a type error: the hash-table should always hold expressions, and to my chagrin, I stuffed the primitive number into it instead.  Easy to fix.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(define (is-legal? expr)&lt;br /&gt;  (define ht (make-hash-table))&lt;br /&gt;  &lt;br /&gt;  (define (seen-already? expr)&lt;br /&gt;    (hash-table-get ht expr #f))&lt;br /&gt;  &lt;br /&gt;  (define (mark-as-seen! expr)&lt;br /&gt;    (hash-table-put! ht expr #t))&lt;br /&gt;  &lt;br /&gt;  (let loop ([expr expr])&lt;br /&gt;    (match expr&lt;br /&gt;      [(struct num (n))&lt;br /&gt;       (cond&lt;br /&gt;         [(seen-already? expr) #f]&lt;br /&gt;         [else&lt;br /&gt;          (mark-as-seen! expr)&lt;br /&gt;          #t])]&lt;br /&gt;      [(struct comb (l o r))&lt;br /&gt;       (and (loop l) (loop r))])))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;And hesitantly pressed &lt;b&gt;Run&lt;/b&gt; on my tests.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;Welcome to DrScheme, version 369.6-svn24jan2007 [3m].&lt;br /&gt;Language: Pretty Big (includes MrEd and Advanced Student).&lt;br /&gt;2 success(es) 0 failure(s) 0 error(s) 2 test(s) run&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Hurrah.&lt;br /&gt;&lt;br /&gt;In all, it was a fun day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-5870387580556281939?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/5870387580556281939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=5870387580556281939' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5870387580556281939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/5870387580556281939'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/02/crazed.html' title='crazed'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-1510384723797375526</id><published>2007-02-01T18:03:00.000-08:00</published><updated>2007-02-01T19:41:58.363-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>countdown</title><content type='html'>Recently, I've been going to a &lt;a href="http://web.cs.wpi.edu/%7Egpollice/Dojo.html"&gt;Coding Dojo&lt;/a&gt; to practice my programming chops.  One of the problems presented so far has been the &lt;a href="http://rubyquiz.com/quiz7.html"&gt;Countdown&lt;/a&gt; program from &lt;a href="http://rubyquiz.com/"&gt;RubyQuiz&lt;/a&gt;.  I thought I might give it a shot, and &lt;a href="http://www2.blogger.com/post-edit.g?blogID=18302393&amp;postID=1510384723797375526"&gt;cooked&lt;/a&gt; up a solution in Scheme, and it wasn't too bad.&lt;br /&gt;&lt;br /&gt;I'll try to give an write-up on how one might attack the problem starting from scratch, and rather than just give a perfect solution, I'll go at this iteratively.  (And make accidental mistakes along the way!)&lt;br /&gt;&lt;br /&gt;The idea behind the countdown problem is that we are doing exhaustive "brute-force" search for all arithmetic expressions.  For example, if we limit ourselves to the numbers 3, 4, and 5, and the only operations are addition and multiplication, here's a conceptual trace of what expressions we'll be brutishly looking at:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;That the first phase.  Then we take pairs of numbers here, and build new expressions:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;3 + 4&lt;br /&gt;3 + 5&lt;br /&gt;4 + 5&lt;br /&gt;3 * 4&lt;br /&gt;3 * 5&lt;br /&gt;4 * 5&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Ok, now we take pairs again, combining stuff from previous phases and the phase we just generated:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;3 + (4 + 5)&lt;br /&gt;3 + (4 * 5)&lt;br /&gt;4 + (3 + 5)&lt;br /&gt;4 + (3 * 5)&lt;br /&gt;5 + (3 + 4)&lt;br /&gt;5 + (3 * 5)&lt;br /&gt;3 * (4 + 5)&lt;br /&gt;3 * (4 * 5)&lt;br /&gt;4 * (3 + 5)&lt;br /&gt;4 * (3 * 5)&lt;br /&gt;5 * (3 + 4)&lt;br /&gt;5 * (3 * 5)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Whew!  Even with three numbers, this gets a bit long.&lt;br /&gt;&lt;br /&gt;I should be more formal for a moment.  By an expression, I mean either a number, or something that involves two smaller expressions and a number.  In Backus-Naur Form, that's:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;        expression = number&lt;br /&gt;                   | expression op expression&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Let's create a data definition in Scheme for this.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module countdown mzscheme&lt;br /&gt; (provide (all-defined))&lt;br /&gt; ;; An expression is either a&lt;br /&gt; ;;     (make-num n)&lt;br /&gt; ;; where n is a number, or&lt;br /&gt; ;;     (make-comb l o r)&lt;br /&gt; ;; where l and r are expressions, and op is an operator.&lt;br /&gt; (define-struct num (n))&lt;br /&gt; (define-struct comb (left op right)))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Ok, we have our expression data definition.  We should also make a quick-and-dirty helper function to help us visually read expressions; let's call this expression-&gt;string:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module countdown mzscheme&lt;br /&gt; (require (lib "plt-match.ss"))&lt;br /&gt;&lt;br /&gt; ;; [data definition omitted]&lt;br /&gt;&lt;br /&gt; ;; expression-&gt;string: expression -&gt; string&lt;br /&gt; ;; Makes a nice human-readable expression.&lt;br /&gt; (define (expression-&gt;string an-expr)&lt;br /&gt;   (define (operator-&gt;string an-op)&lt;br /&gt;     (cond&lt;br /&gt;       [(eq? an-op +) "+"]&lt;br /&gt;       [(eq? an-op *) "*"]))&lt;br /&gt; &lt;br /&gt;   (match an-expr&lt;br /&gt;     [(struct num (n)) (format "~a" n)]&lt;br /&gt;     [(struct comb (l o r))&lt;br /&gt;      (format "(~a ~a ~a)"&lt;br /&gt;              (expression-&gt;string l)&lt;br /&gt;              (operator-&gt;string o)&lt;br /&gt;              (expression-&gt;string r))]))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ok, now that we've got this, let's exercise the code.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&gt; (expression-&gt;string (make-comb (make-num 3) + (make-num 4)))&lt;br /&gt;"(3 + 4)"&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Good.  But I'm feeling guilty; we should really make this a unit test.  Let's pull in &lt;a href="http://planet.plt-scheme.org/#schemeunit.plt"&gt;SchemeUnit&lt;/a&gt;, the unit testing framework for Scheme.&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;(module countdown mzscheme&lt;br /&gt;  (require ;; [other packages omitted]&lt;br /&gt;           (planet "test.ss" ("schematics" "schemeunit.plt" 2))&lt;br /&gt;           (planet "text-ui.ss" ("schematics" "schemeunit.plt" 2)))&lt;br /&gt;  &lt;br /&gt;  ;; [code omitted]&lt;br /&gt;&lt;br /&gt;  (define countdown-tests&lt;br /&gt;    (test-suite&lt;br /&gt;     "tests for countdown"&lt;br /&gt;     (test-equal?&lt;br /&gt;      "expression-&gt;string simple test"&lt;br /&gt;      (expression-&gt;string (make-comb (make-num 3) + (make-num 4)))&lt;br /&gt;      "(3 + 4)")))&lt;br /&gt;&lt;br /&gt;  (test/text-ui countdown-tests))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;If we run this module, we see:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;1 success(es) 0 failure(s) 0 error(s) 1 test(s) run&lt;br /&gt;&gt; &lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Very good.&lt;br /&gt;&lt;br /&gt;Now let's see if we can build new expressions from old ones.  The idea is that, if we have an existing collection of expressions, we want to pair two of them up together and do something with them.  We might do this naively:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  ;; for-each-pairs: (X X -&gt; void) (listof x) -&gt; void&lt;br /&gt;  ;; Calls f on distinct ordered pairs in the collection.&lt;br /&gt;  (define (for-each-pairs f collection)&lt;br /&gt;    (let outer-loop ([i 0])&lt;br /&gt;      (when (&lt; i (length collection))&lt;br /&gt;        (let inner-loop ([j (add1 i)])&lt;br /&gt;          (when (&lt; j (length collection))&lt;br /&gt;            (f (list-ref collection i) (list-ref collection j))&lt;br /&gt;            (inner-loop (add1 j))))&lt;br /&gt;        (outer-loop (add1 i)))))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Does this work?&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&gt; (for-each-pairs (lambda (x y) (printf "~a ~a~n" x y)) '(red blue green))&lt;br /&gt;red blue&lt;br /&gt;red green&lt;br /&gt;blue green&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Looks reasonable.  Of course, now we want to use this to collect up all the pairs and build an addition and a multiplication from &lt;tt&gt;x&lt;/tt&gt; and &lt;tt&gt;y&lt;/tt&gt;.  Let's call this &lt;tt&gt;build-next-generation&lt;/tt&gt;.  Oh, let's write our unit test first:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;     (test-equal?&lt;br /&gt;      "build-next-generation simple"&lt;br /&gt;      (map expression-&gt;string&lt;br /&gt;           (build-next-generation (list (make-num 3)&lt;br /&gt;                                        (make-num 4))))&lt;br /&gt;      (list "(3 + 4)" "(3 * 4)"))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Ok, let's roll up our sleeves and do it.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  ;; build-next-generation: (listof expression) -&gt; (listof expression)&lt;br /&gt;  ;; Constructs new expressions from pairs of old ones.&lt;br /&gt;  (define (build-next-generation expressions)&lt;br /&gt;    (define next-gen '())&lt;br /&gt;    &lt;br /&gt;    (define (collect! an-expr)&lt;br /&gt;      (set! next-gen (cons an-expr next-gen)))&lt;br /&gt;    &lt;br /&gt;    (define (visit-pair e1 e2)&lt;br /&gt;      (collect! (make-comb e1 + e2))&lt;br /&gt;      (collect! (make-comb e1 * e2)))&lt;br /&gt;    &lt;br /&gt;    (for-each-pairs visit-pair expressions)&lt;br /&gt;    (reverse! next-gen)&lt;br /&gt;    next-gen)&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Ok, should work.  On every pair, we combine two expressions, and collect them.  We do a &lt;tt&gt;reverse!&lt;/tt&gt; to put things in the order expected by the test case.  (Although that might be a little silly.)  Let's rerun our unit tests.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;tests for countdown &gt; build-next-generation simple&lt;br /&gt;build-next-generation simple has a FAILURE&lt;br /&gt;name: check-equal?&lt;br /&gt;location: #&lt;struct:object:...ascheme/diva-link.ss:124:4&gt;:67:5&lt;br /&gt;params: (("(3 * 4)") ("(3 + 4)" "(3 * 4)"))&lt;br /&gt;actual: ("(3 * 4)")&lt;br /&gt;expected: ("(3 + 4)" "(3 * 4)")&lt;br /&gt;1 success(es) 1 failure(s) 0 error(s) 2 test(s) run&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;What?!  Yes, there's something wrong here.&lt;br /&gt;&lt;br /&gt;It turns out that I've misused &lt;tt&gt;reverse!&lt;/tt&gt; here: I should just take the result of &lt;tt&gt;reverse!&lt;/tt&gt; and return it directly.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;  (define (build-next-generation expressions)&lt;br /&gt;    (define next-gen '())&lt;br /&gt;    &lt;br /&gt;    (define (collect! an-expr)&lt;br /&gt;      (set! next-gen (cons an-expr next-gen)))&lt;br /&gt;    &lt;br /&gt;    (define (visit-pair e1 e2)&lt;br /&gt;      (collect! (make-comb e1 + e2))&lt;br /&gt;      (collect! (make-comb e1 * e2)))&lt;br /&gt;    &lt;br /&gt;    (for-each-pairs visit-pair expressions)&lt;br /&gt;    (reverse! next-gen))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Hurrah for unit tests.  But maybe we shouldn't do the reverse after all.  Let me just fix up the test case to expect the paired expressions in a different order.  Since I've made so many changes, let's show what the code looks like now:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;(module countdown mzscheme&lt;br /&gt;  (provide (all-defined))&lt;br /&gt;  (require (lib "plt-match.ss")&lt;br /&gt;           (planet "test.ss" ("schematics" "schemeunit.plt" 2))&lt;br /&gt;           (planet "text-ui.ss" ("schematics" "schemeunit.plt" 2)))&lt;br /&gt;  &lt;br /&gt;  ;; An expression is either a&lt;br /&gt;  ;;     (make-num n)&lt;br /&gt;  ;; where n is a number, or&lt;br /&gt;  ;;     (make-comb l o r)&lt;br /&gt;  ;; where l and r are expressions, and op is an operator.&lt;br /&gt;  (define-struct num (n))&lt;br /&gt;  (define-struct comb (left op right))&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  ;; expression-&gt;string: expression -&gt; string&lt;br /&gt;  ;; Makes a nice human-readable expression.&lt;br /&gt;  (define (expression-&gt;string an-expr)&lt;br /&gt;    (define (operator-&gt;string an-op)&lt;br /&gt;      (cond&lt;br /&gt;        [(eq? an-op +) "+"]&lt;br /&gt;        [(eq? an-op *) "*"]))&lt;br /&gt;    &lt;br /&gt;    (match an-expr&lt;br /&gt;      [(struct num (n)) (format "~a" n)]&lt;br /&gt;      [(struct comb (l o r))&lt;br /&gt;       (format "(~a ~a ~a)"&lt;br /&gt;               (expression-&gt;string l)&lt;br /&gt;               (operator-&gt;string o)&lt;br /&gt;               (expression-&gt;string r))]))&lt;br /&gt;  &lt;br /&gt;  ;; for-each-pairs: (X X -&gt; void) (listof x) -&gt; void&lt;br /&gt;  ;; Calls f on distinct ordered pairs in the collection.&lt;br /&gt;  (define (for-each-pairs f collection)&lt;br /&gt;    (let outer-loop ([i 0])&lt;br /&gt;      (when (&lt; i (length collection))&lt;br /&gt;        (let inner-loop ([j (add1 i)])&lt;br /&gt;          (when (&lt; j (length collection))&lt;br /&gt;            (f (list-ref collection i) (list-ref collection j))&lt;br /&gt;            (inner-loop (add1 j))))&lt;br /&gt;        (outer-loop (add1 i)))))&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  ;; build-next-generation: (listof expression) -&gt; (listof expression)&lt;br /&gt;  ;; Constructs new expressions from pairs of old ones.&lt;br /&gt;  (define (build-next-generation expressions)&lt;br /&gt;    (define next-gen '())&lt;br /&gt;    &lt;br /&gt;    (define (collect! an-expr)&lt;br /&gt;      (set! next-gen (cons an-expr next-gen)))&lt;br /&gt;    &lt;br /&gt;    (define (visit-pair e1 e2)&lt;br /&gt;      (collect! (make-comb e1 + e2))&lt;br /&gt;      (collect! (make-comb e1 * e2)))&lt;br /&gt;    &lt;br /&gt;    (for-each-pairs visit-pair expressions)&lt;br /&gt;    next-gen)&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  (define countdown-tests&lt;br /&gt;    (test-suite&lt;br /&gt;     "tests for countdown"&lt;br /&gt;     (test-equal?&lt;br /&gt;      "expression-&gt;string simple test"&lt;br /&gt;      (expression-&gt;string (make-comb (make-num 3) + (make-num 4)))&lt;br /&gt;      "(3 + 4)")&lt;br /&gt;     (test-equal?&lt;br /&gt;      "build-next-generation simple"&lt;br /&gt;      (map expression-&gt;string&lt;br /&gt;           (build-next-generation (list (make-num 3)&lt;br /&gt;                                        (make-num 4))))&lt;br /&gt;      (list "(3 * 4)" "(3 + 4)"))))&lt;br /&gt;  &lt;br /&gt;  (test/text-ui countdown-tests))&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Ok!  Does this do what we'll need for brute-forcing the countdown problem?&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;&gt; (define expressions (list (make-num 3)&lt;br /&gt;                            (make-num 4)&lt;br /&gt;                            (make-num 5)))&lt;br /&gt;&gt; (define generation-1 (append expressions (build-next-generation expressions)))&lt;br /&gt;&gt; (define generation-2 (append generation-1 (build-next-generation generation-1)))&lt;br /&gt;&gt; (map expression-&gt;string generation-2)&lt;br /&gt;("3"&lt;br /&gt; "4"&lt;br /&gt; "5"&lt;br /&gt; "(4 * 5)"&lt;br /&gt; "(4 + 5)"&lt;br /&gt; "(3 * 5)"&lt;br /&gt; "(3 + 5)"&lt;br /&gt; "(3 * 4)"&lt;br /&gt; "(3 + 4)"&lt;br /&gt; "((3 * 4) * (3 + 4))"&lt;br /&gt; "((3 * 4) + (3 + 4))"&lt;br /&gt; "((3 + 5) * (3 + 4))"&lt;br /&gt; ;; ... a LOT of output omitted&lt;br /&gt; "(3 * (4 * 5))"&lt;br /&gt; "(3 + (4 * 5))"&lt;br /&gt; "(3 * 5)"&lt;br /&gt; "(3 + 5)"&lt;br /&gt; "(3 * 4)"&lt;br /&gt; "(3 + 4)")&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;It's a beginning.  It's not quite right, but it's getting there.  Since this post is getting long, I'll split this up with another blog post later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-1510384723797375526?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/1510384723797375526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=1510384723797375526' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/1510384723797375526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/1510384723797375526'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/02/countdown.html' title='countdown'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-51730257758704437</id><published>2007-02-01T10:45:00.000-08:00</published><updated>2007-02-01T10:50:56.886-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='latex'/><title type='text'>latex</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Em81XiCh6L8/RcI2CWK0ItI/AAAAAAAAAAU/N2g7Xrn21ro/s1600-h/Screenshot.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_Em81XiCh6L8/RcI2CWK0ItI/AAAAAAAAAAU/N2g7Xrn21ro/s320/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5026639548037472978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So I visited Amazon today to buy an egg timer.  I was amused to see the following from Amazon's computerized recommendation system.  The items were supposedly based on my prior purchases.  I've put a screenshot of it here, just in case anyone else gets a chuckle out of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-51730257758704437?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/51730257758704437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=51730257758704437' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/51730257758704437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/51730257758704437'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/02/latex.html' title='latex'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Em81XiCh6L8/RcI2CWK0ItI/AAAAAAAAAAU/N2g7Xrn21ro/s72-c/Screenshot.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-6323448970575969929</id><published>2007-01-14T19:07:00.000-08:00</published><updated>2007-01-14T19:13:19.538-08:00</updated><title type='text'>new year</title><content type='html'>I came in last night from California back into Worcester.  I opened my apartment door, half-expecting a nest of mice to scatter.  If there were any, I didn't see them.  I fell blissfully asleep.  I've been sleeping too much lately.  Classes start tomorrow, so I suppose that will be remedied.&lt;br /&gt;&lt;br /&gt;I'm about to fall asleep again, but before that happens, let me mention &lt;a href="http://www.cs.brown.edu/research/plt/software/divascheme/"&gt;DivaScheme&lt;/a&gt; &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2007-January/016026.html"&gt;2.1&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's hoping this New Year is a good one!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-6323448970575969929?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/6323448970575969929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=6323448970575969929' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6323448970575969929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/6323448970575969929'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2007/01/new-year.html' title='new year'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116735726568167594</id><published>2006-12-28T17:54:00.000-08:00</published><updated>2007-01-30T12:09:16.717-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>debugging test-case</title><content type='html'>I thought it might be useful to do a stream-of-consciousness post about what a programmer does when he or she sees a bug and wants to fix it.&lt;br /&gt;&lt;br /&gt;The bug in question is in DrScheme, and it's triggered whenever one goes to the Special menu and runs an "Insert Test Case".  From that point on, the resulting program is uncompilable, with the following error message:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;require: broken compiled code (phase 0, defn-phase 0): cannot find module |,/Users/dyoo/local/plt/collects/test-suite/private/test-case| in: test-case&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The first thing I wanted to do was isolate the problem: what code is responsible?  I knew the functionality in question had something to do with "Insert Test Case", so let's start there.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mithril:~ dyoo$ cd local/plt/collects/&lt;br /&gt;mithril:~/local/plt/collects dyoo$ cd string-constants/&lt;br /&gt;mithril:~/local/plt/collects/string-constants dyoo$ grep 'Insert Test Case' *&lt;br /&gt;english-string-constants.ss:  (test-case-insert "Insert Test Case")&lt;br /&gt;portuguese-string-constants.ss:  (test-case-insert "Insert Test Case")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;I had some previous knowledge that the menus in DrScheme were all internationalized, so I could start by searching through the string-constants directory to start my search.  Whatever code uses &lt;i&gt;test-case-insert&lt;/i&gt; is probably related, so we should start searching for occurrences of that now.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mithril:~/local/plt/collects/string-constants dyoo$ cd ..&lt;br /&gt;mithril:~/local/plt/collects dyoo$ grep -r test-case-insert *&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;A bunch of output spews out, but I'll ignore anything dealing with string constants; if I do that, I see that there's a particular collection called test-suite, and that sounds promising.&lt;br /&gt;&lt;br /&gt;Next thing to do: let's see if anyone else has already tried looking at this, by searching http://bugs.plt-scheme.org.  Yup, there appear to be a few.  Bugs &lt;a href="http://bugs.plt-scheme.org/query/?cmd=view%20audit-trail&amp;database=default&amp;amp;pr=7001&amp;return_url=http%3A%2F%2Fbugs.plt-scheme.org%2Fquery%2F%3Fdatabase%3Ddefault%3Bdebug%3D%3Bcmd%3Dsubmit%2520query%3BState%3Dany%3Bignoreclosed%3DIgnore%2520Closed%3BSynopsis%3D%3Bmultitext%3Dbroken%2520compiled%2520code%3Bcolumns%3DSynopsis%3Bsortby%3DNumber%20"&gt;7001&lt;/a&gt;, &lt;a href="http://bugs.plt-scheme.org/query/?cmd=view%20audit-trail&amp;amp;database=default&amp;pr=7317&amp;amp;return_url=http%3A%2F%2Fbugs.plt-scheme.org%2Fquery%2F%3Fdatabase%3Ddefault%3Bdebug%3D%3Bcmd%3Dsubmit%2520query%3BState%3Dany%3Bignoreclosed%3DIgnore%2520Closed%3BSynopsis%3D%3Bmultitext%3Dbroken%2520compiled%2520code%3Bcolumns%3DSynopsis%3Bsortby%3DNumber%20"&gt;7317&lt;/a&gt;, and &lt;a href="http://bugs.plt-scheme.org/query/?cmd=view%20audit-trail&amp;database=default&amp;amp;pr=7373&amp;amp;return_url=http%3A%2F%2Fbugs.plt-scheme.org%2Fquery%2F%3Fdatabase%3Ddefault%3Bdebug%3D%3Bcmd%3Dsubmit%2520query%3BState%3Dany%3Bignoreclosed%3DIgnore%2520Closed%3BSynopsis%3D%3Bmultitext%3Dbroken%2520compiled%2520code%3Bcolumns%3DSynopsis%3Bsortby%3DNumber"&gt;7373 &lt;/a&gt; seem to be the same bug.  Ok, time to read those bugs reports thoroughly just to make sure I understand what other people have said about this.&lt;br /&gt;&lt;br /&gt;Ok, it looks like Robby mentioned a workaround: if the user enters:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(require (lib "test-case.ss" "test-suite" "private"))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;then things should work out.  Yup, I can verify that this works.  But that seems really odd to have to do this!&lt;br /&gt;&lt;br /&gt;I'll start to look at test-suite and see what the overall flow of the program is.&lt;br /&gt;&lt;br /&gt;[will fill in as soon as I finish doing a review]&lt;br /&gt;&lt;br /&gt;[hours pass...]&lt;br /&gt;&lt;br /&gt;Well, I traced the issue down to how the snips make external requirements that can't always be met, especially in modularized code.  I posted a &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-December/015844.html"&gt;question&lt;/a&gt; about it in the PLT list, and then, a few days later, they were &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2007-January/015876.html"&gt;obliterated&lt;/a&gt;  altogether.&lt;br /&gt;So, in summary: the code I studied is no longer relevant.  It happens.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116735726568167594?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116735726568167594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116735726568167594' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116735726568167594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116735726568167594'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/12/debugging-test-case.html' title='debugging test-case'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116703636781073706</id><published>2006-12-25T00:46:00.000-08:00</published><updated>2006-12-25T00:47:22.410-08:00</updated><title type='text'>christmas</title><content type='html'>Merry Christmas to my family and friends!  What I have been gifted with is much more than I expected or deserved.  I'm thankful for everyone's support and love.&lt;br /&gt;I don't have anything really programming-related to say (because my brain's fried from debugging &lt;a href="http://www.cs.brown.edu/research/plt/software/divascheme/"&gt;DivaScheme&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;May your holidays be peaceful and without the need of an exception handler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116703636781073706?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116703636781073706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116703636781073706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116703636781073706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116703636781073706'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/12/christmas.html' title='christmas'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116634361535489098</id><published>2006-12-17T00:20:00.000-08:00</published><updated>2006-12-17T00:37:59.920-08:00</updated><title type='text'>the moon</title><content type='html'>I woke up early on Saturday to catch the airport shuttle.  It was one of those hours of the night when everything was still and dark, one of those magic weird moments.&lt;br /&gt;&lt;br /&gt;I could see a crescent moon above me, like a sharp scythe.  But have I really seen a scythe in real life?  The only scythe I know is the one held by a &lt;a href="http://www.lucasarts.com/products/grim/"&gt;Grim Reaper&lt;/a&gt;, and that's clearly fantastical.  I have no practical experience with them.  So what else would be a good analogy from my own experience?&lt;br /&gt;&lt;br /&gt;The moon looked like a large left parenthesis.  As soon as that thought floated in my head, I knew.  I was doomed.&lt;br /&gt;&lt;br /&gt;Anyway, it's nice to be in California again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116634361535489098?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116634361535489098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116634361535489098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116634361535489098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116634361535489098'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/12/moon.html' title='the moon'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116551964114897501</id><published>2006-12-07T11:27:00.000-08:00</published><updated>2007-01-30T12:10:04.083-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><title type='text'>heresy</title><content type='html'>Every so often, a fey mood takes me, and I write a program that probably shouldn't see the light of day.  I've done so with a PLT package called &lt;a href="http://planet.plt-scheme.org/#infix.plt"&gt;infix&lt;/a&gt;.  It's a package for writing infix expressions in PLT Scheme, but it does some other funky stuff.  For example:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;br /&gt;(module test mzscheme&lt;br /&gt; (require (planet "infix.ss" ("dyoo" "infix.plt" 1 0)))&lt;br /&gt;&lt;br /&gt; (infix printf("hello, this is a test: ~a ~a~n",&lt;br /&gt;               list(3, 4),&lt;br /&gt;               5))&lt;br /&gt;&lt;br /&gt; (define (in-order a b c)&lt;br /&gt;   (infix printf("in-order(~a, ~a, ~a): ~a~n",&lt;br /&gt;                 a, b, c, a &lt;= b &lt;= c)))      (infix in-order(1, 2, 3))   (infix in-order(1, 3, 2))) &lt;/pre&gt;&lt;br /&gt;I had a very good laugh with Guillaume when I showed this to him.  You have to be a Schemer to appreciate how very wrong this is.&lt;br /&gt;&lt;br /&gt;This technique is a proof-of-concept that shows just how programmable the PLT Scheme syntax system can be.  It wouldn't be much more work to embed a different programming language syntax in here, as long as it's compatible with s-expressions.  The source code for this can be found &lt;a href="http://hashcollision.org/svn/repos/projects/infix/"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116551964114897501?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116551964114897501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116551964114897501' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116551964114897501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116551964114897501'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/12/heresy.html' title='heresy'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116538489322429518</id><published>2006-12-05T22:01:00.000-08:00</published><updated>2006-12-05T22:01:33.253-08:00</updated><title type='text'>falling snow</title><content type='html'>I saw a hint of snow by the window.&lt;br /&gt;&lt;br /&gt;I thought for a moment that I had been seeing ash drifting in the air, but one step out into the frigid air convinced me.  Snow!  (&lt;a href="http://www.megatokyo.com/index.php?strip_id=374"&gt;Sad girl in snow?&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;It's &lt;a href="http://en.wikipedia.org/wiki/Baby,_It's_Cold_Outside_(song)"&gt;cold outside&lt;/a&gt;!  It's not yet the kind of cold that makes one think of fairy tales and wolves, but it's slightly chilly now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116538489322429518?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116538489322429518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116538489322429518' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116538489322429518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116538489322429518'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/12/falling-snow.html' title='falling snow'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116390553194898300</id><published>2006-11-18T19:05:00.000-08:00</published><updated>2006-11-18T19:05:32.020-08:00</updated><title type='text'>baking bread</title><content type='html'>I had the compulsion to bake bread for about a week, but having never done so before, I hesitated.  Do I get a bread machine, or buy a few books, or...?&lt;br /&gt;&lt;br /&gt;It turns out there is a very nice &lt;a href="http://www.nytimes.com/2006/11/08/dining/081mrex.html?ex=1163912400&amp;en=08a3a90265978bd3&amp;ei=5070"&gt;recipe&lt;/a&gt; for newbies like me.  I tried it, and it didn't turn out half bad.&lt;br /&gt;&lt;br /&gt;I suppose this is why almost everyone is forced to write a &lt;a href="http://www2.latech.edu/~acm/HelloWorld.shtml"&gt;"hello world"&lt;/a&gt; program when they start off learning to program.  If only "hello world" were more... sustaining.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116390553194898300?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116390553194898300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116390553194898300' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116390553194898300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116390553194898300'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/11/baking-bread.html' title='baking bread'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116249176169366001</id><published>2006-11-02T10:22:00.000-08:00</published><updated>2006-11-02T11:24:11.756-08:00</updated><title type='text'>how not to write xml</title><content type='html'>I came across &lt;a href="http://www.ibiblio.org/xml/books/xmljava/chapters/ch03.html"&gt;Writing XML with Java&lt;/a&gt; the other day, and hoped that the authors wouldn't advocate building XML through plain string concatenations.  Unfortunately, they had.&lt;br /&gt;&lt;br /&gt;Here's what the author said to justify this:&lt;br /&gt;&lt;blockquote&gt;Eventually we’ll take up some alternatives to the direct string approach such as DOM and JDOM that do allow you to automatically maintain well-formedness and sometimes even validity. However, for many simple cases, these are vast overkill. It can be much simpler to just write a few strings onto an output stream.&lt;/blockquote&gt;&lt;br /&gt;I disagree: maintaining well-formedness should be the computer's job, not ours, because it it mindless and very easy to get wrong if we do it by hand.  Well-formedness is something I shouldn't have to worry about: it should be trivial to get this right.&lt;br /&gt;&lt;br /&gt;The author also said:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Making sure the output is correct is simply one part of testing and debugging your code. &lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Yes, making sure we're outputting the right thing is part of a good test suite.  But there are some kinds of bugs that just don't deserve to be out into the open.  The most common error I've seen in HTML/XML generation is failing to properly quote and escape things.  It's precisely because of this cavalier attitude toward generating structured data that we see such problems.&lt;br /&gt;&lt;br /&gt;Here's the style of code they wrote (translation of Exercise 3.8):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (define (simple)&lt;br /&gt;    (printf "&amp;lt;?xml version=\"1.0\"?&amp;gt;~n")&lt;br /&gt;    (printf "&amp;lt;mathml:math xmlns:mathml=\"http://www.w3.org/1998/Math/MathML\"&amp;gt;~n")&lt;br /&gt;    (let loop ([i 1]&lt;br /&gt;               [low 1]&lt;br /&gt;               [high 1])&lt;br /&gt;      (when (&amp;lt;= i 10)&lt;br /&gt;        (printf "&amp;lt;mathml:mrow&amp;gt;~n")&lt;br /&gt;        (printf "     &amp;lt;mathml:mi&amp;gt;f(~a)&amp;lt;/mathmi&amp;gt;~n" i)&lt;br /&gt;        (printf "     &amp;lt;mathml:mo&amp;gt;=&amp;lt;/mathml:mo&amp;gt;~n")&lt;br /&gt;        (printf "     &amp;lt;mathml:mn&amp;gt;~a&amp;lt;/mathml:mn&amp;gt;~n" low)&lt;br /&gt;        (printf "&amp;lt;/mathml:mrow&amp;gt;~n")&lt;br /&gt;        (loop (add1 i) high (+ high low))))&lt;br /&gt;    (printf "&amp;lt;/mathml:math&amp;gt;~n"))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This style of building XML is simple, as the author notes, but it doesn't scale.  As soon as we start dealing with XML documents that have interesting content, we suddenly have to start thinking about HTML injection issues, entity quotation, and keeping those darn tags balanced all the time.&lt;br /&gt;&lt;br /&gt;Writing code that treats the XML as real structure is not much harder than the above:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;  (require (lib "xml.ss" "xml")&lt;br /&gt;           (lib "list.ss"))&lt;br /&gt;  (define (simple-2)&lt;br /&gt;    (define (make-row i low)&lt;br /&gt;      `(mathml:mrow (mathml:mi ,(format "f(~a)" i))&lt;br /&gt;                    (mathml:mo "=")&lt;br /&gt;                    (mathml:mn ,(format "~a" low))))&lt;br /&gt;    (define (make-rows)&lt;br /&gt;      (let loop ([i 1]&lt;br /&gt;                 [low 1]&lt;br /&gt;                 [high 1])&lt;br /&gt;        (cond&lt;br /&gt;          [(&lt;= i 10) (cons (make-row i low)&lt;br /&gt;                           (loop (add1 i) high (+ high low)))]&lt;br /&gt;          [else empty])))&lt;br /&gt;    (printf "~a" (xexpr-&gt;string&lt;br /&gt;                  `(mathml:math&lt;br /&gt;                    ((xmlns:mathml "http://www.w3.org/1998/Math/MathML"))&lt;br /&gt;                    ,@(make-rows)))))&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The difference here is that all the niggling issues from the first example --- balancing tags, properly quoting values --- don't apply at all.  The XML library takes care of this busywork, as it should.  It's guaranteed to be well-formed.&lt;br /&gt;&lt;br /&gt;Not everything has to be treated as a string.  We shouldn't be afraid to play with structured data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116249176169366001?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116249176169366001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116249176169366001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116249176169366001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116249176169366001'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/11/how-not-to-write-xml.html' title='how not to write xml'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116201167028000231</id><published>2006-10-27T22:01:00.000-07:00</published><updated>2006-10-27T22:11:29.150-07:00</updated><title type='text'>streaky</title><content type='html'>There's a peculiar behavior in human psychology where something that catches your attention ends up showing up everywhere.  &lt;a href="http://www.cs.utexas.edu/users/arvindn/misc/knuth_song_complexity.pdf"&gt;Knuth&lt;/a&gt; noticed it in his discussion on &lt;a href="http://technetcast.ddj.com/tnc_play_stream.html?stream_id=160"&gt;randomness&lt;/a&gt;.  We are pattern matchers: we try to make sense of the world by looking at similarity, at streaks of continuity.&lt;br /&gt;&lt;br /&gt;So I was amused to post &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-October/015143.html"&gt;this&lt;/a&gt; and &lt;a href="http://mail.python.org/pipermail/tutor/2006-October/050435.html"&gt;that&lt;/a&gt; within the same week.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116201167028000231?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116201167028000231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116201167028000231' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116201167028000231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116201167028000231'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/10/streaky.html' title='streaky'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116102457524411512</id><published>2006-10-16T11:49:00.000-07:00</published><updated>2007-01-30T12:10:29.601-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>in summation...</title><content type='html'>In an earlier &lt;a href="http://hashcollision.blogspot.com/2006/09/new-car-brand-toyota-type-corolla.html"&gt;post&lt;/a&gt;, I wondered out how to get a closed form for my car debt.  The program I wrote can be actually thought of as a &lt;span style="font-style: italic;"&gt;recurrence relation&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   debt at the very beginning = initial debt at zero months&lt;br /&gt;&lt;br /&gt;   debt(n) = monthly interest * (debt from last month - my monthly car payment)&lt;br /&gt;             and where n has to be greater than 0.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But since that's a bit wordy, I'll use some shorter variable names when I'm talking about the debt I'm incurring at month &lt;span style="font-weight: bold;"&gt;n&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   d(n) = I * (d(n-1) - P)     for n &gt; 0&lt;br /&gt;        = I * d(n-1) - I*P     for n &gt; 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I didn't quite remember how to get a closed form for this formula at the time.  Yesterday, though, as I was quaffing a coffee at Cape Cod, I flipped through &lt;a href="http://www-cs-faculty.stanford.edu/%7Eknuth/gkp.html"&gt;Concrete Mathematics&lt;/a&gt;.  There in the first few pages of the book was the technique I needed!&lt;br /&gt;&lt;br /&gt;The core idea is to use a summation factor to make the function I'm solving for a little simpler.  For the recurrence above,&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   (1/I)^n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;is a good summation factor.  When I multiply my recurrence with it, I get:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   d(n)/(I^n) = d(n-1)/(I^(n-1)) - P/(I^(n-1))     for n &gt; 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The reason this is simpler is because I can consider a parallel formula:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   S(n) = d(n) / (I^n)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which I can use to restate the recurrence as:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   S(0) = d(0) / (I^0) = d(0)         (since anything to the zeroth power is 1)&lt;br /&gt;   S(n) = S(n-1) - P/(I^(n-1))        for n &gt; 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And now &lt;span style="font-weight: bold;"&gt;S(n)&lt;/span&gt; is, structurally, simple enough to be treated as a straight summation rather than a wacky recurrence:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   S(n) = d(0) - sum across k from 1 to n of: P/(I^(k-1))&lt;br /&gt;&lt;br /&gt;        = d(0) - P * sum across k from 0 to (n-1) of: (1/I)^k&lt;br /&gt;&lt;br /&gt;        = d(0) - that horrendous sum&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But it turns out that that horrendous sum is actually not bad at all.  If we squint our eyes at it, it's a geometric sum, and those have a very nice closed form: it's the "first term - the first excluded term in the sum, divided by one minus the term ratio".  That is, if I'm doing:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   a^0 + a^1 + a^2 + ... + a^n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I don't have to actually add up all those terms: I can just do:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   ((a^0) - a^(n+1)) / (1 - a)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So by applying the transformation on that geometric sum, I can get a closed form for &lt;span style="font-weight: bold;"&gt;S(n)&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   S(n) = d(0) - P * sum across k from 0 to (n-1) of: (1/I)^k&lt;br /&gt;        = d(0) - P*(1 - (1/I)^n)/(1 - 1/I)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But &lt;span style="font-weight: bold;"&gt;S(n)&lt;/span&gt; isn't what I was originally going after: I was going after &lt;span style="font-weight: bold;"&gt;d(n)&lt;/span&gt;, so let me backpatch that fix in:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   S(n) = d(n) / (I^n), so&lt;br /&gt;   d(n) = S(n) * I^n&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is, my car debt at any given month is going to be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   d(n) = I^n * (d(0) - P*(1 - (1/I)^n)/(1 - 1/I))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Whew!  Let's try that out:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(module car-payment-2 mzscheme&lt;br /&gt; ;; debt: number number number number -&gt; number&lt;br /&gt; ;; Returns the amount of money owed after months pass,&lt;br /&gt; ;; given a particular monthly payment and apr rate.&lt;br /&gt; (define (debt months initial-debt monthly-payment apr)&lt;br /&gt;  &lt;br /&gt;   ;; closed-form: number number number number -&gt; number&lt;br /&gt;   ;; This is a closed form solution for the recurrence:&lt;br /&gt;   ;;&lt;br /&gt;   ;; d(n) = I * (d(n-1) - P)&lt;br /&gt;   ;;&lt;br /&gt;   ;; d(n) = I^n * (d(0) - P*(1 - (1/I)^n)/(1 - 1/I))&lt;br /&gt;   (define (closed-solution n d0 P I)&lt;br /&gt;     (let* ([I^n (expt I n)]&lt;br /&gt;            [1/I (/ 1 I)]&lt;br /&gt;            [1/I^n (/ 1 I^n)])&lt;br /&gt;       (I^n . * .&lt;br /&gt;            (d0 . - .&lt;br /&gt;                ((P . * . (1 . - . 1/I^n))&lt;br /&gt;                 . / .&lt;br /&gt;                 (1 . - . 1/I))))))&lt;br /&gt;  &lt;br /&gt;   (let ([monthly-interest (+ 1 (/ apr 12))])&lt;br /&gt;     (closed-solution months&lt;br /&gt;                      initial-debt&lt;br /&gt;                      monthly-payment&lt;br /&gt;                      monthly-interest))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and let's look at a few values:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (debt 0 16300 327.93 0.0767)&lt;br /&gt;16300&lt;br /&gt;&gt; (debt 1 16300 327.93 0.0767)&lt;br /&gt;16074.158147416665&lt;br /&gt;&gt; (debt 2 16300 327.93 0.0767)&lt;br /&gt;15846.872788992236&lt;br /&gt;&gt; (map (lambda (x) (debt x 16300 327.93 0.0767))&lt;br /&gt;      (list 0 1 2 3 4 5 6 7 8 9 10))&lt;br /&gt;(16300&lt;br /&gt;16074.158147416665&lt;br /&gt;15846.872788992236&lt;br /&gt;15618.13469831854&lt;br /&gt;15387.934590015295&lt;br /&gt;15156.263119353142&lt;br /&gt;14923.110881874338&lt;br /&gt;14688.46841301098&lt;br /&gt;14452.32618770081&lt;br /&gt;14214.67462000053&lt;br /&gt;13975.5040626967)&lt;br /&gt;&gt; (map (lambda (x) (debt x 16300 327.93 0.0767))&lt;br /&gt;      (list 56 57 58 59 60))&lt;br /&gt;(1150.9196104211048&lt;br /&gt;828.2498856810436&lt;br /&gt;503.5177636170277&lt;br /&gt;176.71006207281036&lt;br /&gt;-152.1864853637734)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I did a little fist-pump after I got this working.  CS students are weird.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116102457524411512?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116102457524411512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116102457524411512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116102457524411512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116102457524411512'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/10/in-summation.html' title='in summation...'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-116036640583936482</id><published>2006-10-08T21:00:00.000-07:00</published><updated>2006-10-08T21:00:06.026-07:00</updated><title type='text'>the guy in the second row</title><content type='html'>I've always wondered what was up with the&lt;br /&gt;&lt;a href="http://perl.plover.com/yak/presentation/samples/slide027.html"&gt; guy in the second row&lt;/a&gt;, the person in any class that seems to hold a personal conversation with the professor.  God, those people were both impressive and annoying.&lt;br /&gt;&lt;br /&gt;God has a sense of humor.  To my horror, I've found that I've become one of those people.&lt;br /&gt;&lt;br /&gt;Sometimes I wonder if it would have been better to go with the meek and shy persona in class.  Oh well.  Jay Parini wrote in &lt;a href="http://www.oup.com/us/catalog/he/subject/Education/GeneralMethods/?view=usa&amp;ci=9780195169690"&gt;The Art of Teaching&lt;/a&gt; that a successful teacher is a stage performer, that they have no choice but to adopt a persona to become a successful teacher.  I suppose that goes for students as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-116036640583936482?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/116036640583936482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=116036640583936482' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116036640583936482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/116036640583936482'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/10/guy-in-second-row.html' title='the guy in the second row'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115863594566129933</id><published>2006-09-18T20:19:00.000-07:00</published><updated>2006-09-18T20:25:24.926-07:00</updated><title type='text'>(new car% [brand "toyota"] [type "corolla"])</title><content type='html'>The big thing that's happened this weekend was getting a car; I bought a 2007 Toyota Corolla.  I still have some mixed feelings about this, but I think I'll need it to survive the winters here.&lt;br /&gt;&lt;br /&gt;These machines cost a lot!  I dropped by http://www.edmunds.com/apps/calc/CalculatorController.  But it's a black box to me: I had no real idea how it was actually doing its calculation.  So I tried to cook up the calculations from scratch:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(module car-payment mzscheme&lt;br /&gt;  ;; Small toy code for calculating car stuff.&lt;br /&gt;  (provide (all-defined))&lt;br /&gt;  &lt;br /&gt;  ;; debt: number number number number -&gt; number&lt;br /&gt;  ;; Returns the amount of money owed after months pass,&lt;br /&gt;  ;; given a particular monthly payment and apr rate.&lt;br /&gt;  (define (debt months current-debt monthly-payment apr)&lt;br /&gt;    (let loop ([n months]&lt;br /&gt;               [current-debt current-debt])&lt;br /&gt;      (cond&lt;br /&gt;        [(= n 0) current-debt]&lt;br /&gt;        [else&lt;br /&gt;         (let ([monthly-interest (/ apr 12)])&lt;br /&gt;           (loop (sub1 n)&lt;br /&gt;                 (* (+ 1 monthly-interest)&lt;br /&gt;                    (- current-debt monthly-payment))))])))&lt;br /&gt;  &lt;br /&gt;  ;; months-till-debt-free: number number number -&gt; number&lt;br /&gt;  ;; Returns how many months have to pass before we're debt free.&lt;br /&gt;  (define (months-till-debt-free initial-cost monthly-payment apr)&lt;br /&gt;    (let loop ([n 0])&lt;br /&gt;      (let ([new-debt (debt n initial-cost monthly-payment apr)])&lt;br /&gt;        (cond&lt;br /&gt;          [(&lt;= new-debt 0) n]&lt;br /&gt;          [else (loop (add1 n))])))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now I could verify for myself: how long would it be until I dig myself out of a big hole?&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (months-till-debt-free 16300 327.93 0.0767)&lt;br /&gt;60&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Oh.  Ok, so at least it looks like the code is doing the same thing as the Edmunds calculator.  That's good.&lt;br /&gt;&lt;br /&gt;I should brush up on my &lt;a href="http://www.math.upenn.edu/~wilf/DownldGF.html"&gt;recurrence relations&lt;/a&gt;, though, since I'm sure that there's a closed form for this calculation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115863594566129933?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115863594566129933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115863594566129933' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115863594566129933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115863594566129933'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/09/new-car-brand-toyota-type-corolla.html' title='(new car% [brand &quot;toyota&quot;] [type &quot;corolla&quot;])'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115638459548835005</id><published>2006-08-23T18:56:00.000-07:00</published><updated>2006-08-23T18:59:34.263-07:00</updated><title type='text'>lights out</title><content type='html'>Some fragmented, disconnected thoughts:&lt;br /&gt;&lt;br /&gt;My room light in Providence blew out two weeks ago.  I jumped, but couldn't reach the ceiling.  I told the landlady about it, but she said not to worry, since I would be moving out anyway.&lt;br /&gt;&lt;br /&gt;A few days later &lt;a href="http://users.wpi.edu/~fgeller/"&gt;Felix&lt;/a&gt; and I chatted about manga; he asked what the Japanese word for "light" was.  "&lt;a href="http://en.wikipedia.org/wiki/Hikari_%28song%29"&gt;Hikari&lt;/a&gt;," I said with assurance.  Felix raised his eyebrow, and countered that he was sure it was "&lt;a href="http://raito.aetheria.net/"&gt;Raito&lt;/a&gt;".  We were confused.  It turns out, though, that we were both right: "Raito" is the Engrish romanization for "light".  I groaned.&lt;br /&gt;&lt;br /&gt;I remember watching Guillaume standing on top of his patio, trying to catch the dying sunset in his digital &lt;a href="http://www.dpchallenge.com/profile.php?USER_ID=50287"&gt;camera&lt;/a&gt;.  I came to visit his place again, and the lights were out; he had moved back to Montreal.  I hope he's doing ok.  My summer at Brown is over.&lt;br /&gt;&lt;br /&gt;Four days ago, as I climbed the steps to my new &lt;a href="http://www.bancroftcommons.com/"&gt;apartment&lt;/a&gt; in Worcester, I saw a notice: "TO ALL TENANTS: THE POWER WILL BE OUT FOR TWO DAYS AS WE WILL BE REPLACING THE ELECTRICAL SYSTEM."  Suddenly, the prospect of living on the tenth floor didn't seem so comfortable.&lt;br /&gt;&lt;br /&gt;Yesterday, I flew back from Providence to LA to see my folks.  As I entered the airport, I could hear sirens going off, and all the computer monitors were dead black.  The &lt;a href="http://www.beloblog.com/ProJo_Blogs/newsblog/archives/2006/08/power_back_on_a.html"&gt;electricity&lt;/a&gt; at the airport had blown, and everything was at a standstill.  I sighed.&lt;br /&gt;&lt;br /&gt;Looking back at the last few days, I notice that I've been leaving a trail of darkness in my wake.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115638459548835005?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115638459548835005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115638459548835005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115638459548835005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115638459548835005'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/08/lights-out.html' title='lights out'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115567058760465429</id><published>2006-08-15T12:36:00.000-07:00</published><updated>2006-08-15T12:36:27.686-07:00</updated><title type='text'>in bed</title><content type='html'>I recently went to a Chinese buffet restaurant on Sunday, and my fortune cookie for that day had an unusual property of passive resistance:&lt;br /&gt;&lt;br /&gt;&lt;quote&gt;If you think you're too small to be effective, you have never been in bed with a mosquito.&lt;/quote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115567058760465429?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115567058760465429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115567058760465429' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115567058760465429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115567058760465429'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/08/in-bed.html' title='in bed'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115154692984889164</id><published>2006-06-28T19:08:00.000-07:00</published><updated>2006-06-28T19:08:49.866-07:00</updated><title type='text'>emacs / DrScheme keystroke of the day: kill!</title><content type='html'>C-M-k: kills the s-expression to the right of the cursor point.  This is really useful in parenthetical languages like Scheme, since it further reduces the need to count parentheses.&lt;br /&gt;&lt;br /&gt;But speaking of keystrokes, I should lay off typing for a little time; my wrists have been itching as of late, and I think I've been overdoing my keyboarding.  I'm back in LA to attend Ken's wedding, so I should use this time to get away from the keyboard.  But I'm typing at this very moment!  But I can't write what I'm thinking without typing... Argh... C-c C-c C-c C-c...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115154692984889164?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115154692984889164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115154692984889164' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115154692984889164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115154692984889164'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/06/emacs-drscheme-keystroke-of-day-kill.html' title='emacs / DrScheme keystroke of the day: kill!'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115084570337486702</id><published>2006-06-20T16:21:00.000-07:00</published><updated>2006-06-20T16:25:45.903-07:00</updated><title type='text'>reading papers: Exploring the Design of an Intentional Naming Scheme with an Automatic Constraint Analyzer</title><content type='html'>Notes to self on &lt;a href="Exploring the Design of an Intentional Naming Scheme with an Automatic Constraint Analyzer"&gt;http://sdg.csail.mit.edu/pubs/2000/INS_ASE00.pdf&lt;/a&gt;.  I'm revising this as I read more.&lt;br /&gt;&lt;br /&gt;Shallow summary: the authors use Alloy, a model checker, to validate the design of the Intentional Naming System (INS); along the way, they show that INS has flaws in it.  They use Alloy as a counterexample generator and as a tool to explore INS's design.&lt;br /&gt;&lt;br /&gt;What questions does the paper ask?&lt;br /&gt;&lt;br /&gt;    * When does INS break?&lt;br /&gt;    * When does it work?&lt;br /&gt;    * Can we use the model to describe general properties for any intentional naming system?&lt;br /&gt;&lt;br /&gt;Why is this novel?&lt;br /&gt;&lt;br /&gt;    * It's another data point showing that model checking can be used effectively in real world applications.&lt;br /&gt;    * It shows, in particular, that Alloy can handle the modeling of complex data structures.  This is a new application of Alloy to a recursive algorithm (Lookup-Name) that has not been done before.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115084570337486702?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115084570337486702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115084570337486702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115084570337486702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115084570337486702'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/06/reading-papers-exploring-design-of.html' title='reading papers: Exploring the Design of an Intentional Naming Scheme with an Automatic Constraint Analyzer'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-115043566494005089</id><published>2006-06-15T22:27:00.000-07:00</published><updated>2006-06-15T22:40:45.966-07:00</updated><title type='text'>learning to play wisely</title><content type='html'>I just played another Go game with Guillaume.  One of the problems I have is that when I see a &lt;a href="http://senseis.xmp.net/?KoFighting"&gt;ko&lt;/a&gt; that I can fight, I'll rush into it like a lemming.&lt;br /&gt;&lt;br /&gt;It must be exhausting to play me sometimes.&lt;br /&gt;&lt;br /&gt;I have to stop fighting just for the sake of fighting.  Playing games is not all I'm doing for the summer.  I am getting a Nintendo DS tomorrow, though.  Hmmm...&lt;br /&gt;&lt;br /&gt;In retrospect, I suppose I am playing too many games.  The days here at Brown have been a lot of fun, but there is serious work I am trying to do.  (Or am I trying to be serious about my work?)  I've been fighting with PLT Scheme's module system; who knew that loading a module could be so frustrating sometimes?&lt;br /&gt;&lt;br /&gt;The issue I've been seeing involves trying to &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-June/013522.html"&gt;erase lexical scope&lt;/a&gt; and &lt;a href="http://hashcollision.org/svn/repos/projects/plt-misc/namespace.ss"&gt;inject modules&lt;/a&gt; through the blood-brain barrier that is PLT Scheme's &lt;a href="http://download.plt-scheme.org/doc/301/html/tools/tools-Z-H-118.html#node_sec_3.24"&gt;evaluation REPL&lt;/a&gt;.  DrScheme likes to fight back, and I find myself very exhausted and writing error prone code.&lt;br /&gt;&lt;br /&gt;In fact, my lexical-scope-erasing macro code was flawed; here's the &lt;a href="http://hashcollision.org/svn/repos/projects/plt-misc/erase-lexical-scope.ss"&gt;corrected code&lt;/a&gt;.  So Schemers do write buggy code too.&lt;br /&gt;&lt;br /&gt;If only it were easy to transfer my determination in playing into programming well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-115043566494005089?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/115043566494005089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=115043566494005089' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115043566494005089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/115043566494005089'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/06/learning-to-play-wisely.html' title='learning to play wisely'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-114922835326950675</id><published>2006-06-01T23:05:00.000-07:00</published><updated>2006-06-01T23:06:16.773-07:00</updated><title type='text'>learning to resign</title><content type='html'>I've been playing &lt;a href="http://playgo.to/interactive/"&gt;Go&lt;/a&gt; with &lt;a href="http://www.cs.brown.edu/~gmarceau/"&gt;Guillaume&lt;/a&gt;; it's a lot of fun, but occassionally I get boneheaded and just don't know when to resign.  It's bad courtesy, and I should be better about it.  There's a difference between optimism and denial, and I resolve to tell the difference better next time.&lt;br /&gt;&lt;br /&gt;There's also a point when one is programming something difficult; sometimes I feel like I should resign and step back and see that my approach is altogether wrong.  But there's the mythology of the heroic programmer --- that one last bug fix, and maybe-if-I-fiddle-with-this-it-will-work syndrome --- that I'm still enamored with.&lt;br /&gt;&lt;br /&gt;This fault runs deep in me, and I will need to retrain myself to be less silly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-114922835326950675?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/114922835326950675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=114922835326950675' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114922835326950675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114922835326950675'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/06/learning-to-resign.html' title='learning to resign'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-114849536299716570</id><published>2006-05-24T11:29:00.000-07:00</published><updated>2006-05-24T11:29:27.520-07:00</updated><title type='text'>getting started in programming language theory</title><content type='html'>These are the two textbook resources I'm reading to get myself up to speed:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/"&gt;Programming Languages: Application and Interpretation&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.cs.utah.edu/classes/cs7520/notes.pdf"&gt;Programming Languages and Lambda Calculi&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The second book, PLLC, is a very good book that appears to cover the same material as in Benjamin Pierce's &lt;a href="http://www.cis.upenn.edu/~bcpierce/tapl/"&gt;Types and Programming Languages&lt;/a&gt;.  (Why do all these textbooks have four-letter acronyms?)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-114849536299716570?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/114849536299716570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=114849536299716570' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114849536299716570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114849536299716570'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/05/getting-started-in-programming.html' title='getting started in programming language theory'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-114783632254414343</id><published>2006-05-16T20:25:00.000-07:00</published><updated>2006-05-16T20:40:04.026-07:00</updated><title type='text'>nightmare</title><content type='html'>I wanted to post something entirely non-programming related.  I had a nightmare last night; I dreamt of &lt;a href="http://en.wikipedia.org/wiki/Fallout_2"&gt;atomic bombs&lt;/a&gt; going off.  It was bizarre; in my dream, I imagined that the ISS had been taken over by terrorists (or aliens; not quite sure who was responsible here).  LA had been hit by bombs, the floor shuddered, and blackness.  The scene shifted, and I stumbled into a dark bar.  CNN played in the dim light.  Were the talking heads even American?  Whispers all around.  And again, the lights went out, screams, and I heard a large thudding roar in the distance, with the earth shifting in protest.  Much too close.  I tried to close the ajar bar door.  It didn't help, but it made me feel better.&lt;br /&gt;&lt;br /&gt;It was as if I were an extra in a bad B-rated movie.  I stirred and, half-waking, looked at my clock.  8:00am.  Well, there's nothing else to do.  The Apocalypse dream is, at least, more interesting than getting up.  Might as well watch how this all ends.   I went back to sleep to finish watching the nightmare of my dreams.  I don't remember what happened afterwards.&lt;br /&gt;&lt;br /&gt;I write this now so that my future self can laugh at me.  What a strange time we live in.&lt;br /&gt;&lt;br /&gt;Speaking of anxieties: I'm going &lt;a href="http://brown.edu"&gt;here&lt;/a&gt; tomorrow.  Not to say that this has anything to do with my nightmares.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-114783632254414343?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/114783632254414343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=114783632254414343' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114783632254414343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114783632254414343'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/05/nightmare.html' title='nightmare'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-114599648611837916</id><published>2006-04-25T13:21:00.000-07:00</published><updated>2006-04-25T13:21:26.253-07:00</updated><title type='text'>macro-happy</title><content type='html'>I'm still a &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-April/012672.html"&gt;little&lt;/a&gt; &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-April/012675.html"&gt;too&lt;/a&gt; &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-April/012678.html"&gt;macro-happy&lt;/a&gt; these days.  Hopefully this phase will pass.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I found a few good references on guidelines for macros:&lt;br /&gt;http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg02079.html&lt;br /&gt;&lt;br /&gt;I can't end this without not posting my little &lt;span style="font-style:italic;"&gt;assert&lt;/span&gt; macro&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  (define-syntax (assert stx)&lt;br /&gt;    (syntax-case stx ()&lt;br /&gt;      [(_ expr)&lt;br /&gt;       (quasisyntax/loc stx&lt;br /&gt;         (unless expr&lt;br /&gt;           (error 'assert (format "~a lineno ~a: ~s failed" &lt;br /&gt;                                  #,(syntax-source stx)&lt;br /&gt;                                  #,(syntax-line stx)&lt;br /&gt;                                  (quote expr)))))]))&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-114599648611837916?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/114599648611837916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=114599648611837916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114599648611837916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114599648611837916'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/04/macro-happy.html' title='macro-happy'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-114543041680877314</id><published>2006-04-19T00:06:00.000-07:00</published><updated>2006-04-19T00:06:56.843-07:00</updated><title type='text'>Reading and writing</title><content type='html'>I've been reading Richard Gabriel's book, "Writers' Workshops &amp; the Work of Making Things".  I'm really liking what I've read so far.  It speaks a lot to what I think about collaborative learning --- what we do when we read and write each other's programs to give and share the gift of making.&lt;br /&gt;&lt;br /&gt;In some sense, a mailing list like &lt;a href="http://mail.python.org/mailman/listinfo/tutor"&gt;tutor@python.org&lt;/a&gt; tries to --- perhaps instinctively --- follow the writers' workshop environment.  There is satisfying work in building communities that help each other; I would like to continue with it.&lt;br /&gt;&lt;br /&gt;Besides reading, I'm continuing my study of PLT Scheme, and think that I can contribute to the &lt;a href="http://list.cs.brown.edu/pipermail/plt-scheme/2006-April/012593.html"&gt;documentation-for-mainstream-programmers-is-missing&lt;/a&gt; problem.  I'll start by attacking &lt;a href="http://schemecookbook.org/Cookbook/IntroductionToMzlibClasses"&gt;classes&lt;/a&gt;, since that'll be the thing that Java programmers will reach first, and I'll probably try to tackle MrEd next.&lt;br /&gt;&lt;br /&gt;Last: sometimes I'm too eager to jump into a question and write something that I think is helpful; I should watch out not to reveal too much, lest I do damage.  The lessons that John Holt learned in &lt;a href="http://www.educationreformbooks.net/failure.htm"&gt;How Children Fail&lt;/a&gt; should always be at the back of my mind.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-114543041680877314?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/114543041680877314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=114543041680877314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114543041680877314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/114543041680877314'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/04/reading-and-writing.html' title='Reading and writing'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113918175329389411</id><published>2006-02-05T15:22:00.001-08:00</published><updated>2006-02-05T15:22:33.306-08:00</updated><title type='text'>opening the time capsule</title><content type='html'>&lt;p&gt;I've been starting to browsing through old archives of the &lt;a href="http://www.swiss.ai.mit.edu/projects/scheme/rrrs-archive.html"&gt;RnRS mailing list&lt;/a&gt; and it's a blast to see how the ideas behind Scheme have evolved.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;For example, it was somewhat shocking (and amusing) to hear that call-with-current-continuation was &lt;a href="http://www.swiss.ai.mit.edu/ftpdir/scheme-mail/HTML/rrrs-1984/msg00016.html"&gt;deliberately named&lt;/a&gt; to make it hard for programmers to type and misuse!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Well, better continue reading; I've only read up to 1985, and there's a few more years of mail left to read...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113918175329389411?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113918175329389411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113918175329389411' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113918175329389411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113918175329389411'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/02/opening-time-capsule_05.html' title='opening the time capsule'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113723072462388719</id><published>2006-01-14T01:25:00.000-08:00</published><updated>2006-01-14T01:25:24.660-08:00</updated><title type='text'>learning to read papers: why calculating is better than scheming</title><content type='html'>I just finished reading &lt;a href="http://www.cs.kent.ac.uk/people/staff/dat/miranda/wadler87.pdf"&gt;Why calculating is better than scheming&lt;/a&gt;, and it's good stuff.  But I get the feeling that I'll need to read a lot more papers to get up to date with programming languages.&lt;br /&gt;&lt;br /&gt;One thing that bothers me occassionally is this: I don't think I know enough about programming language theory yet to talk with specialists about it.  So there's an isolating feeling I get about reading early papers, because I think it's cool stuff, and yet it's probably so elementary that everyone else is so beyond it already.&lt;br /&gt;&lt;br /&gt;But, despite all these being elementary,  I still do want to write what I'm getting out of reading these papers, just in case I make conclusions that are absolutely wrong.  If it's public, then there's still some chance that someone out there can correct me.  *grin*  So here goes...&lt;br /&gt;&lt;br /&gt;A few of the critiques made in Wadler's paper are addressed in PLT Scheme.  For example, pattern-matching does exist in a &lt;a href="http://download.plt-scheme.org/doc/301/html/mzlib/mzlib-Z-H-32.html#node_chap_32"&gt;library&lt;/a&gt;.  The sum Miranda code in the paper:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sum [] = 0&lt;br /&gt;sum (x:xs) = x + sum xs&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;can be written in PLT Scheme as:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(require (lib "plt-match.ss"))&lt;br /&gt;(define sum&lt;br /&gt;  (match-lambda&lt;br /&gt;   ((list) 0)&lt;br /&gt;   ((list-rest x xs) (+ x (sum xs)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;though this also brings up a point about syntax: the Miranda code does use an appealing syntax, whereas everything in Lisp is an s-expression.  Syntax is also an issue, though I think Wadler discounts too much the role of macros in Lisp-like languages.&lt;br /&gt;&lt;br /&gt;The points for a type discipline seem fair, and I suspect a proper use of MrFlow would catch the same kind of mistakes that a static type system would catch.  (Though I don't know yet: I haven't played with MrFlow seriously.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Wadler's term "free data types" goes over my head slightly.  *grin*  Concretely in terms of Scheme, I think he's trying to say that equal? only works on s-expressions, and that trying to do equal? on arbitrary compound data might not work because we're never sure what the choice of representation is.&lt;br /&gt;&lt;br /&gt;Does PLT Scheme's &lt;a href="http://download.plt-scheme.org/doc/301/html/mzscheme/mzscheme-Z-H-4.html#node_chap_4"&gt;structure&lt;/a&gt; and inspector support meet the requirements of free data type definition?  It seems to me that:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;;; a structure is either a Weight or a Mobile.&lt;br /&gt;(define-struct Weight (n) (make-inspector))&lt;br /&gt;(define-struct Mobile (left right) (make-inspector))&lt;br /&gt;&lt;br /&gt;(define-struct Branch (length structure) (make-inspector))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;could also be considered a way to define free data types, though I'm probably missing something subtle.&lt;br /&gt;&lt;br /&gt;Anyway, better stop now and sleep.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113723072462388719?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113723072462388719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113723072462388719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113723072462388719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113723072462388719'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2006/01/learning-to-read-papers-why.html' title='learning to read papers: why calculating is better than scheming'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113289938930804121</id><published>2005-11-24T22:16:00.000-08:00</published><updated>2005-11-24T22:16:29.320-08:00</updated><title type='text'>starting with dtrace</title><content type='html'>Notes about setting up dtrace user on a Solaris 10 system: by default, it appears that normal users don't have enough privileges to access dtrace.  These privileges are:&lt;br /&gt;&lt;br /&gt;    * dtrace_user&lt;br /&gt;    * dtrace_proc&lt;br /&gt;    * dtrace_kernel&lt;br /&gt;&lt;br /&gt;and these are described in the privileges(5) man page.&lt;br /&gt;&lt;br /&gt;So how do we add these privileges to a user account?  According to http://forum.sun.com/thread.jspa?threadID=22787&amp;messageID=73761, it's a matter of editing /etc/user_attr with a set of default privileges.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113289938930804121?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113289938930804121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113289938930804121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113289938930804121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113289938930804121'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2005/11/starting-with-dtrace.html' title='starting with dtrace'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113236174290635401</id><published>2005-11-18T16:55:00.000-08:00</published><updated>2005-11-18T16:55:42.926-08:00</updated><title type='text'>One hacker's treasure is another hacker's junk</title><content type='html'>Sun's patch 120289 recently change gnome-terminal's behavior on page up and page down keys.  Some people are very happy about this:&lt;br /&gt;&lt;br /&gt;    http://ptribble.blogspot.com/2005/09/yay-gnome-terminal-fixed.html&lt;br /&gt;&lt;br /&gt;Unfortunately, I'm not.  *grin*&lt;br /&gt;&lt;br /&gt;I do understand why the change was made --- usability matters! --- but for me, the existing behavior was perfectly usable and right: I want those keys to be sent to the terminal.  I use those keys all the time in pine, and they don't work anymore.&lt;br /&gt;&lt;br /&gt;I'm now trying to figure out how to work with gconf-editor to preserve the old behavior but haven't figured out where things need to change yet.  Oh well.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113236174290635401?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113236174290635401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113236174290635401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113236174290635401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113236174290635401'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2005/11/one-hackers-treasure-is-another.html' title='One hacker&apos;s treasure is another hacker&apos;s junk'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113213078106314457</id><published>2005-11-16T00:46:00.000-08:00</published><updated>2005-11-16T00:46:21.083-08:00</updated><title type='text'>Emacs keystroke of the day</title><content type='html'>I learned two new Emacs keystrokes that will make Scheme coding that much less painful:&lt;br /&gt;&lt;br /&gt;    C-M-f: forward-sexp&lt;br /&gt;    C-M-b: backward-sexp&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113213078106314457?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113213078106314457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113213078106314457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113213078106314457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113213078106314457'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2005/11/emacs-keystroke-of-day.html' title='Emacs keystroke of the day'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18302393.post-113030369464294392</id><published>2005-10-25T15:13:00.000-07:00</published><updated>2005-10-25T22:24:05.173-07:00</updated><title type='text'>Testing, testing</title><content type='html'>(define greeting (lambda () (printf "hello world!~%")))&lt;br /&gt;(greeting)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18302393-113030369464294392?l=hashcollision.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hashcollision.blogspot.com/feeds/113030369464294392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=18302393&amp;postID=113030369464294392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113030369464294392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/18302393/posts/default/113030369464294392'/><link rel='alternate' type='text/html' href='http://hashcollision.blogspot.com/2005/10/testing-testing.html' title='Testing, testing'/><author><name>Danny Yoo</name><uri>http://www.blogger.com/profile/04298793721597988477</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
