<?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-21500237</id><updated>2011-12-23T15:25:49.370-05:00</updated><category term='Haskell'/><category term='C++'/><category term='Python'/><category term='Music Theory'/><category term='Linux'/><category term='C'/><category term='Newton'/><category term='Administrivia'/><category term='Geek Food'/><category term='School of Expression'/><category term='Sudoku'/><category term='GHC'/><category term='Math'/><category term='Kernel'/><category term='Holiday 2007'/><category term='Banking'/><category term='Scheme'/><category term='Programming'/><category term='Snow Leopard'/><category term='MacPorts'/><title type='text'>Praise, Curse, and Recurse</title><subtitle type='html'>On programming and programming languages: because there has got to be a better way.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-21500237.post-2112454165227250739</id><published>2009-09-09T23:44:00.003-04:00</published><updated>2009-09-09T23:49:13.176-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Snow Leopard'/><category scheme='http://www.blogger.com/atom/ns#' term='MacPorts'/><category scheme='http://www.blogger.com/atom/ns#' term='GHC'/><title type='text'>MacPorts, Snow Leopard, and GHC == Sadness</title><content type='html'>Wow, it has been a long time since I've had anything to say on this particular blog. Another baby (we're at four now) will do that to a guy, I guess.&lt;br /&gt;&lt;br /&gt;I was going to do a little exploratory coding tonight, and so installed XCode, then MacPorts, then tried to install GHC. MacPorts tells me (after installing most of the components) that "ghc is not yet supported on Mac OS X 10.6.x (SnowLeopard)."&lt;br /&gt;&lt;br /&gt;I know it hasn't been out very long, but the APIs have supposedly been frozen since May, so I'm a bit surprised.&lt;br /&gt;&lt;br /&gt;I guess I'll see if the package installer works, but I was hoping to go a little more cutting-edge.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2112454165227250739?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2112454165227250739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2112454165227250739' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2112454165227250739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2112454165227250739'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2009/09/macports-snow-leopard-and-ghc-sadness.html' title='MacPorts, Snow Leopard, and GHC == Sadness'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-3959506017833288992</id><published>2008-11-17T17:31:00.001-05:00</published><updated>2008-11-17T17:40:54.221-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Reading Real World Haskell</title><content type='html'>I've sort of let this blog lie fallow while my attention was distracted by having a new baby, playing shiny guitars, twittering, making podcasts and YouTube videos, and other distracting things.&lt;br /&gt;&lt;br /&gt;I am excited to see that &lt;span style="font-style:italic;"&gt;Real World Haskell&lt;/span&gt; has gone to press, and so I am reading the electronic edition while waiting for the print edition to arrive. I had read some of the draft chapters, but it has changed considerably!&lt;br /&gt;&lt;br /&gt;For those interested, I recorded audio during the birth of my newest child, Joshua Gregory Potts, born just under three weeks ago. I am turning this into a series of podcasts along with the tweets I sent out during the birth. I won't spam you with a lot of links, but here is a link to &lt;a href="http://generalpurposepodcast.blogspot.com"&gt;The Potts House General Purpose Podcast&lt;/a&gt;. Over on &lt;a href="http://geeklikemetoo.blogspot.com"&gt;Geek Like Me Too&lt;/a&gt; you can find baby pictures, some serious and some silly.&lt;br /&gt;&lt;br /&gt;I am learning to live with sleep deprivation again! So, these days, Twitter seems like a more appropriate medium for the short attention span which is pretty much all I'm capable of at the moment. If you are so inclined, you can find me on twitter as "paulrpotts."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-3959506017833288992?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/3959506017833288992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=3959506017833288992' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3959506017833288992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3959506017833288992'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/11/reading-real-world-haskell.html' title='Reading Real World Haskell'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-8801092962744678499</id><published>2008-09-02T13:39:00.002-04:00</published><updated>2008-09-02T13:41:30.154-04:00</updated><title type='text'>Summer's Over</title><content type='html'>My son Isaac started high school today, so it must be true.&lt;br /&gt;&lt;br /&gt;Here is my first YouTube video: the &lt;a href="http://www.youtube.com/watch?v=tSVuCYOYYKM"&gt;Potts family vacation&lt;/a&gt; in Grand Marais, Michigan and other points north this past week, set to Jonathan Coulton's Creative Commons-licensed song "Summer's Over."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-8801092962744678499?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/8801092962744678499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=8801092962744678499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8801092962744678499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8801092962744678499'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/09/summers-over.html' title='Summer&apos;s Over'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-9205784839415483629</id><published>2008-07-22T11:26:00.000-04:00</published><updated>2008-07-22T11:28:02.501-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Administrivia'/><title type='text'>Cross-Blog Information and Introductions</title><content type='html'>In order to try to avoid boring people with material they aren't interested in, I have divided my writing up into five separate blogs. The downside to this is that I have a tendency to wander from one area of interest to another over the course of a typical year, so it may look like I've dropped off the face of the earth. In case anyone is interested in following what is going on in one of my other blogs, I thought it might be useful to post this road map once in a while.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://geeklikemetoo.blogspot.com/"&gt;Geek Like Me Too&lt;/a&gt; is my general-purpose personal blog. The most recent postings are about a recent Jonathan Coulton concert in Pontiac that I attended and recorded. I have provided recordings of the show as a set of MP3 files, of interest to geeks who like music.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thepottshouse.org/blosxom.cgi/"&gt;Geek Like Me&lt;/a&gt; is its predecessor, done in Blosxom, now still up only for archival purposes.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://geekversusguitar.blogspot.com/"&gt;Geek Versus Guitar&lt;/a&gt; is about guitar playing. Recently I've recorded a few Jonathan Coulton songs myself. It will also be about learning to produce songs with my home studio.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://praisecurseandrecurse.blogspot.com/"&gt;Praise, Curse, and Recurse&lt;/a&gt; is about programming topics, mostly Haskell, Python, and Scheme. My free time has been devoted to other things but I will no doubt be back around to programming before too long.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://armstrong-collection.blogspot.com/"&gt;The Marcella Armstrong Memorial Collection&lt;/a&gt; is about my family history, and the big task of scanning, restoring, preserving, and archiving family photos and documents. Of interest to any family members, but also of possible interest to people doing their own similar projects.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://hodgecast.blogspot.com/"&gt;Tales from the Potts House: William Hope Hodgson&lt;/a&gt; contains information about the "Hodgecast" podcast available on iTunes, in which I record classic William Hope Hodgson novels and stories. I have more podcasts planned in both this series and possibly others in the near future.&lt;br /&gt;&lt;br /&gt;Anyway, there it is... please join me on any of these blogs that might catch your interest. I always have far too many projects going at once!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-9205784839415483629?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/9205784839415483629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=9205784839415483629' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/9205784839415483629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/9205784839415483629'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/07/cross-blog-information-and.html' title='Cross-Blog Information and Introductions'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-5428825838999473180</id><published>2008-04-03T21:58:00.001-04:00</published><updated>2008-04-03T22:04:17.230-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Snakes on the Wing</title><content type='html'>So far, Wing IDE gets the nod as the best Python editor I've tried. I had a very productive day with Wing IDE on Windows, and it worked great, with no crashes, and very nice debugging functions.&lt;br /&gt;&lt;br /&gt;WIng IDE for MacOS X is an XWindows app. This makes it very slightly un-Mac-like, but it makes up for it by having some nice GUI themes. I haven't yet exercised the Mac version very hard, but it seems quite nice so far.&lt;br /&gt;&lt;br /&gt;I'm grateful for all the recommendations!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-5428825838999473180?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/5428825838999473180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=5428825838999473180' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5428825838999473180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5428825838999473180'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/04/snakes-on-wing.html' title='Snakes on the Wing'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7515003991831054322</id><published>2008-04-03T01:15:00.001-04:00</published><updated>2008-04-03T01:39:48.755-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Beware the IDEs of April</title><content type='html'>My post on Python IDEs got a huge number of comments, including recommendations for Eclipse with plug-ins, Visual Studio with plug-ins, and Emacs.&lt;br /&gt;&lt;br /&gt;One of the two highest-recommended options was Komodo IDE. I've had some success with a trial of Komodo IDE on Windows, with only one major crash, which I was unable to reproduce. However, the same code brought over to run under the same version of Komodo for MacOS X produces a strange syntax error. I've filed this as bug 76114. It seems quite strange, especially given that the same code runs fine using the command-line Python under MacOS X. Despite this issue it seems overall to be a pretty usable environment.&lt;br /&gt;&lt;br /&gt;I've also had several recommendations for WingIDE, which I will check out as well.  Thanks to everyone who responded!&lt;br /&gt;&lt;br /&gt;The program mostly reads an XML file, does a little validating and destructuring of the nodes into dictionaries, and then generates some C++ using a template. About as "real-world" a program as they come. Even as boiled-down as I can make it, it still seems awfully wordy and full of functions whose behavior is extremely dependent on my intermediate data representation. In Common Lisp, I'd be trying to use s-expressions instead of XML for the starting data, and using destructuring macros to turn the input data into data structures. With NewtonScript, I might try to find a way to do it by writing accessors that used path expressions. Is there a better way in Python? How about Haskell? I'll have to give it some thought.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7515003991831054322?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7515003991831054322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7515003991831054322' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7515003991831054322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7515003991831054322'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/04/beware-ides-of-april.html' title='Beware the IDEs of April'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-839760370593741665</id><published>2008-04-01T00:10:00.000-04:00</published><updated>2008-04-01T00:29:21.547-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>The Abysmal State of Python IDEs</title><content type='html'>In the past few weeks I've sampled numerous Python IDEs for Mac OS X. Without exception, every one of them has major problems.&lt;br /&gt;&lt;br /&gt;Without exception, they have crude GUIs, with drawing problems.&lt;br /&gt;&lt;br /&gt;Without exception, every one of them has had either lacked completely, or had broken, the kind of source-level debugging that has been commonplace since the mid-1980s, such as visually setting breakpoints.&lt;br /&gt;&lt;br /&gt;Most of them have the look of personal hobby projects, where the developer put in a little effort, and then abandoned the project. Menu items do nothing, help commands say "no help available." Documentation? Don't make me laugh, it hurts too much.&lt;br /&gt;&lt;br /&gt;Even the allegedly polished products work really erratically. On Windows, I have to restart the ActiveState environment every time I want to re-run my program after making a change and saving the program, because it doesn't seem to ever realize that the file has been updated. Except sometimes it starts detecting changes for a while. It won't save my window layout. Except once in a while it does. However, breakpoints do work for me, and I'm able to do some debugging. But ActiveState for Mac seems to install completely different tools than ActiveState for Windows: no IDE whatsoever. Huh?&lt;br /&gt;&lt;br /&gt;I'm having to do most of my debugging with print statements. I'm horrified. There is some kind of primitive debugger, but it requires modifying my source code, and that just seems stupid. The program I'm trying to debug is not unusual nor particularly complex; it just works over some XML and transforms some files.&lt;br /&gt;&lt;br /&gt;My download log for tonight reads like a litany of failure: drpython, SPE, ScrIDE, and ActivePython.&lt;br /&gt;&lt;br /&gt;DrPython: no interactive debugging. SPE: allegedly some kind of debugger, but it doesn't seem to work. ScrIDE: weird issue handling basic import statements that work on the other IDEs and with the command-line python without any trouble; other users are reporting this on the message board. ActivePython: claims to have some kind of IDE, but the Mac OS X package doesn't have it.&lt;br /&gt;&lt;br /&gt;Is there one that would be as useful as, oh, Lightspeed Pascal circa 1985, if I were willing to pay for it?&lt;br /&gt;&lt;br /&gt;As the song goes, is this all there is?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-839760370593741665?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/839760370593741665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=839760370593741665' title='47 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/839760370593741665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/839760370593741665'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/04/abysmal-state-of-python-ides.html' title='The Abysmal State of Python IDEs'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>47</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7652906849017869306</id><published>2008-03-16T20:05:00.002-04:00</published><updated>2008-12-09T21:21:32.543-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Newton'/><title type='text'>Smug Newton Weenie</title><content type='html'>This past week I've been wallowing in nostalgia as I re-familiarize myself with the Newton's development environment and take a fresh look at code I wrote for the platform a dozen years ago. It's got me thinking more about the joys of small languages, and the clever hacks that enabled such an advanced GUI and applications to run on such a lightweight platform. Also, at the runtime implementation for dynamic language like this, compiled as byte codes.&lt;br /&gt;&lt;br /&gt;I'm happy to say that I I have wireless e-mail working via my home wireless network on two MessagePad 2100s, using Simon Bell's excellent Mail V, an IMAP/POP client that integrates nicely with the Newton's built-in Inbox/Outbox program, and a couple of Lucent WaveLan cards running Hiroshi Noguchi's driver. I can even send myself big JPEG files. This is my extremely geeky equivalent of carrying around family photos in my wallet, although the 2100 only displays a few gray levels:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_I3IWwUe_TZM/R92_EpWp9hI/AAAAAAAAApk/KxH-bev8lDs/s1600-h/isaac_and_veronica.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_I3IWwUe_TZM/R92_EpWp9hI/AAAAAAAAApk/KxH-bev8lDs/s320/isaac_and_veronica.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5178505233087198738" /&gt;&lt;/a&gt;&lt;br /&gt;Interestingly, after ten days of experimentation the 4 AA batteries powering my 2100 unit still have juice left, although they are starting to fade. The 2000/2100 were a very interesting advance, because they were far faster than their predecessors the 110/120/130, yet lasted longer on the same batteries.&lt;br /&gt;&lt;br /&gt;I hope you find this at least marginally interesting. Not everyone around me is as interested as I am in the joys of old technology, as this doodle illustrates...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_I3IWwUe_TZM/R-YGbY7i7EI/AAAAAAAAAp0/CtdGvB-qgfY/s1600-h/Smug+Newton+Weenie.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_I3IWwUe_TZM/R-YGbY7i7EI/AAAAAAAAAp0/CtdGvB-qgfY/s320/Smug+Newton+Weenie.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5180835488954772546" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7652906849017869306?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7652906849017869306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7652906849017869306' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7652906849017869306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7652906849017869306'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/03/smug-newton-weenie.html' title='Smug Newton Weenie'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_I3IWwUe_TZM/R92_EpWp9hI/AAAAAAAAApk/KxH-bev8lDs/s72-c/isaac_and_veronica.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6044853841668934255</id><published>2008-03-12T11:30:00.000-04:00</published><updated>2008-03-12T11:39:39.579-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Newton'/><title type='text'>Looking for a NewtonScript Book</title><content type='html'>I know it is available in PDF form, but for nostalgia purposes I am looking for a paper copy of the book "The NewtonScript Programming Language." There were a couple of versions of this book; it was not sold separately but included in packaged versions of the Newton Toolkit sold to developers. And thus, most of them have probably been discarded. The older version of the book can be seen in bottom row, just left of center in this picture from the &lt;a href="http://www.newtonmuseum.com/pages/image03.html"&gt;Newton Museum&lt;/a&gt;. The later version, if I recall correctly, was white with yellow typography and a picture of a toolbox on the cover. I will pay (some reasonable amount, plus shipping cost) for either or both books reasonable condition.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6044853841668934255?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6044853841668934255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6044853841668934255' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6044853841668934255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6044853841668934255'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/03/looking-for-newtonscript-book.html' title='Looking for a NewtonScript Book'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4960024208565432969</id><published>2008-03-06T16:24:00.004-05:00</published><updated>2008-03-07T10:00:26.477-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Newton'/><title type='text'>All that is Solid Melts into Air</title><content type='html'>I've been moody this week. It's been just about ten years since Apple's Newton project was canceled, the products discontinued, and the staff of the project began their exodus. I hope readers will forgive me if I wax a little autobiographical.&lt;br /&gt;&lt;br /&gt;In 1993 I attended, along with a couple of friends, the launch of the original Apple Newton. I nearly melted my credit cards into slag by buying an original MessagePad and a copy of the Newton Toolkit. Both products were over-hyped (see &lt;a href="http://www.tuaw.com/2007/01/29/blast-from-the-past-getting-started-with-the-newton/"&gt;this impressive and slightly utopian video&lt;/a&gt;), and promised far more than they could deliver on that hardware, but to me the technical innovation and potential were far more interesting than the actual practicality; I was excited about some kind of platonic ideal Newton device, not the actual stubby greenish device that crashed and locked up and wouldn't boot in cold weather and ate batteries like candy and turned my handwriting into word salad. Developing with beta-this and 1.0-that was a struggle, but within a few weeks I had sent my first Newton freeware application out into the world, an ugly, misshapen little utility called Strainer, best forgotten. But it was a start -- and a doorway into a whole world of dynamic typing, closures, garbage collection, prototype-based programming, byte codes, garbage collection, and even "eval" and "apply."&lt;br /&gt;&lt;br /&gt;My co-worker Mike and I dove into it. He created the Usenet newsgroups for Newton. I developed and maintained the early FAQ list. I did so much testing and analysis of the behavior of the built-in applications that I wound up getting calls from developers within Apple to discuss the bugs I was finding. I got to know the Newton developer tech support engineers. I wanted to be one of them. I published articles, most of them likely best forgotten, but overflowing with my enthusiasm for the new architecture. I exchanged e-mail messages with Walter Smith, the very smart guy behind NewtonScript, talking about the implementation of NewtonScript itself; he explained closures. Which got me into Dylan. Which got me into Scheme. Which (ultimately) got me into Haskell. And so forth.&lt;br /&gt;&lt;br /&gt;The Newton was a big part of my career, on and off, for the next six years or so. I got paid to write Newton applications -- not consistently, and not just Newton applications, and not end-user, shrink-wrapped applications, but a lot of NewtonScript nonetheless. I developed a kind of DSL, in NewtonScript, built into the package by executing NewtonScript code at build time. That package acted as a kind of script itself that ran on a NewtonScript engine capable of presenting a variety of nicely-formatted question types. The survey engine had a kind of transactional semantics, even across branching, so that the data it was recording always remained consistent. It could do all kinds of post-processing and analysis on the fly, with little embedded function objects, and basically ran as a big state machine to administer surveys. It was code-as-data; it was higher-order programming. NewtonScript was, at least for me at the time, an Acceptable Lisp. For several research projects, that's how the Health Media Research Lab at the University of Michigan collected data from study participants. There were several other parts to the process -- built around AppleScript, Quark XPress, WebObjects (Java), C++, and even Visual BASIC and Perl and Scheme and Macromedia Director, and I was involved to some extent in most of them, but the Newton survey engine was my particular baby.&lt;br /&gt;&lt;br /&gt;Apple released Newton hardware in two more form factors, ultimately culminating in the MessagePad 2000 and 2100, which pretty much _were_ that platonic ideal of a Newton device, a local maximum as far as design, usability, and features per watt, and that product hasn't had a serious contender in user-interface design prior to the arrival of the iPhone. And it came crashing down, rather abruptly, just a few months after the release of the MessagePad 2100. There was no one left to fix bugs. Because of one particular bug in the 2100, we had to scramble to stockpile the earlier MessagePad 2000, so that we would have enough units on hand to complete our research study.&lt;br /&gt;&lt;br /&gt;A couple of years ago I discarded my original MessagePad, with its original case and "Getting Started" card and cute little power adapter and a press kit from the Newton launch -- just tossed it in the dumpster. I shouldn't have done that. Original MessagePads -- not upgraded -- are scarce on the ground, and though they are not terribly usable, the design remains interesting. A few years ago I picked up a 2100, and just recently bought 3 more Newtons on eBay, one of each form factor, but I miss the neat leather-journal feel of the rubberized original MessagePad and its snug-fitting, book-like case.&lt;br /&gt;&lt;br /&gt;Interestingly, the Newton architecture has proved to be flexible past the point of Apple's involvement. In the box of scuffed-up Newton MessagePads was a wireless modem card. Some enterprising hackers actually got support for these devices working; I have not yet gotten it working, but I'm told that it's possible to get it working on a modern WiFi network, albeit with a somewhat minimalist web browser. I wonder if I can get the Webmail interface working via a web browser on the Newton?&lt;br /&gt;&lt;br /&gt;I gave my wife a short demo, and she wants one, so she's going to be a rather late beta tester herself. That's good; I'd rather see them get used, than just sit on the shelf and corrode. Me, I'm going to fire up the development tools and see what it looks like to me now with ten year's more perspective.&lt;br /&gt;&lt;br /&gt;But more broadly, the history of this technology is causing me to think seriously about what just what exactly it is that I've been doing since I got my first computer in 1977, at the age of ten.&lt;br /&gt;&lt;br /&gt;One of the famed Alan Perlis &lt;a href="http://www.cs.yale.edu/quotes.html"&gt;Epigrams in Programming&lt;/a&gt; reads:&lt;blockquote&gt;Is it possible that software is not like anything else, that it is meant to be discarded: that the whole point is to see it as a soap bubble?&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4960024208565432969?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4960024208565432969/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4960024208565432969' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4960024208565432969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4960024208565432969'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/03/all-that-is-solid-melts-into-air.html' title='All that is Solid Melts into Air'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7879174823761680555</id><published>2008-03-01T13:07:00.000-05:00</published><updated>2008-12-09T21:21:32.789-05:00</updated><title type='text'>The Vanishing Hard Drive</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_I3IWwUe_TZM/R8mcJ50RNHI/AAAAAAAAAoM/LZW2yeYJEgQ/s1600-h/S7301868.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_I3IWwUe_TZM/R8mcJ50RNHI/AAAAAAAAAoM/LZW2yeYJEgQ/s320/S7301868.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5172837340964533362" /&gt;&lt;/a&gt;&lt;br /&gt;8 inches, 5.25 inches, 3.5 inches, 2.5 inches, 1.8 inches, and 1 inch.&lt;br /&gt;&lt;br /&gt;I predict that hard disk drives will be entirely invisible to the naked eye by 2019.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7879174823761680555?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7879174823761680555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7879174823761680555' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7879174823761680555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7879174823761680555'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/03/vanishing-hard-drive.html' title='The Vanishing Hard Drive'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_I3IWwUe_TZM/R8mcJ50RNHI/AAAAAAAAAoM/LZW2yeYJEgQ/s72-c/S7301868.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6139592392877766815</id><published>2008-02-18T11:49:00.001-05:00</published><updated>2008-12-09T21:21:32.936-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Is Python an Acceptable Haskell?</title><content type='html'>So I struggled with some Python this weekend. I'm taking over a piece of code that is written in Python, but the original is very imperative, with a lot of for loops. It was giving me a headache. It just looked way too long and tedious. I'm too old to spend my life debugging off-by-one errors in for loops.&lt;br /&gt;&lt;br /&gt;After staying up half the night struggling with a malfunctioning IDLE on MacOS X, I finally discovered the cure for the headache was -- more Python!&lt;pre&gt;&lt;br /&gt;# This gives us a "curry" equivalent&lt;br /&gt;from functools import partial&lt;br /&gt;&lt;br /&gt;# Reduce a list of strings to a single string by concatenation&lt;br /&gt;reduce_stringlist = partial( reduce, str.__add__ )&lt;br /&gt;&lt;br /&gt;# Given a list of XML elements, return a list of only the data from only the text nodes&lt;br /&gt;# (ignores any non-text nodes)&lt;br /&gt;def get_text_data( nodelist ):&lt;br /&gt;    return map( lambda node: node.data,&lt;br /&gt;                filter( lambda node: node.nodeType == node.TEXT_NODE, nodelist ) )&lt;br /&gt;&lt;br /&gt;# Now, combined: reduce a list of nodes to the concatenated text extracted out of only&lt;br /&gt;# the text node data&lt;br /&gt;def extract_text( nodelist ):&lt;br /&gt;    return reduce_stringlist( get_text_data( nodelist ) )&lt;br /&gt;&lt;br /&gt;# Given a portion of the parsed XML tree and a name, extract a single string. Expect&lt;br /&gt;# only one element.&lt;br /&gt;def get_one_text_element( node, name ):&lt;br /&gt;    elt_list = node.getElementsByTagName( name )&lt;br /&gt;    assert elt_list.length == 1&lt;br /&gt;    return extract_text( elt_list[0].childNodes )&lt;br /&gt;&lt;br /&gt;# Given a starting node and a list of tag names, retrieve one text string each and&lt;br /&gt;# put them in a newly created dictionary using the tag name as a key&lt;br /&gt;def make_text_element_dict( node, namelist ):&lt;br /&gt;    return dict(&lt;br /&gt;        zip( namelist,&lt;br /&gt;             map ( partial( get_one_text_element, node ),&lt;br /&gt;                   namelist ) ) )&lt;br /&gt;&lt;/pre&gt;Ahhh, I feel much better! All that excess hairy boilerplate seems to be just melting away!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_I3IWwUe_TZM/R7ecfpJv-aI/AAAAAAAAAnQ/ya6Lzhem8HU/s1600-h/Jonathan+Solidarity+(Isaac%27s+Camera)+-+2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_I3IWwUe_TZM/R7ecfpJv-aI/AAAAAAAAAnQ/ya6Lzhem8HU/s320/Jonathan+Solidarity+(Isaac%27s+Camera)+-+2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5167771164867557794" /&gt;&lt;/a&gt;&lt;br /&gt;The only thing I did not like is that there did not seem to be a nice way to specify keyword arguments to "reduce" so that I could create a partial (curried) application that supplied the first and optional third parameter, leaving the second as the one to be supplied at runtime.&lt;br /&gt;&lt;br /&gt;I experimented with writing the above with Python's list comprehension idiom, generators, and various permutations on join(). The above just seems to make more sense to me. Haskell has apparently ruined me for other languages.&lt;br /&gt;&lt;br /&gt;Apparently Guido would like to ban reduce() from Python. I say -- prefer the standard idiom to the offbeat, and avoid the Not Invented Here syndrome. Python's comprehensions and generators are nice, but apparently I've been ruined by seeking more and more expressive languages, seeking truth and beauty on my wandering but inexorable path from Dylan to NewtonScript to Scheme to Haskell. Lambda, map, curry, reduce, and zip now seem to me to be fundamental primitives that any reasonable dynamic language ought to provide, and it seems to me that they ought to be preferred to an obscure language-specific trick. As long as I have to use Python, Guido will have to pry the curried functions from my cold, dead hands!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6139592392877766815?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6139592392877766815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6139592392877766815' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6139592392877766815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6139592392877766815'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/02/is-python-acceptable-haskell.html' title='Is Python an Acceptable Haskell?'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_I3IWwUe_TZM/R7ecfpJv-aI/AAAAAAAAAnQ/ya6Lzhem8HU/s72-c/Jonathan+Solidarity+(Isaac%27s+Camera)+-+2.jpg' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4210420556474583034</id><published>2008-02-14T17:20:00.002-05:00</published><updated>2008-02-14T17:51:29.879-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>A Pet Peeve -- Proprietary Fasteners</title><content type='html'>As if it wasn't hard enough to keep tools on hand for the following screws: &lt;br /&gt;&lt;br /&gt;- Flat blade&lt;br /&gt;&lt;br /&gt;- Hex (in metric and fractional inch sizes)&lt;br /&gt;&lt;br /&gt;- Philips &lt;br /&gt;&lt;br /&gt;- Torx&lt;br /&gt;&lt;br /&gt;- Tamper-resistant Torx (with a post in the middle)&lt;br /&gt;&lt;br /&gt;- Torx Plus (with wider holes)&lt;br /&gt;&lt;br /&gt;- Tamper-resistant Torx Plus (hard to come by -- with wider holes, a post in the middle, and five points instead of six)&lt;br /&gt;&lt;br /&gt;- TTAP (a six-point variation with a deep hole in the middle, also hard to come by)&lt;br /&gt;&lt;br /&gt;- Tamper-resistant TTAP (which I've never seen)&lt;br /&gt;&lt;br /&gt;- Several other unusual fastener heads, such as square, two-pin, etc.&lt;br /&gt;&lt;br /&gt;I've found that certain hard drive screws use a five-pointed variant of the six-pointed Torx star shape, which corresponds to "none of the above" and which doesn't seem to be available, anywhere. I found this out the hard way after buying a very nice set of Torx bits. The screws in question are so small it is very hard for my 40-year-old eyes to distinguish the five-pointed star from the six. They are roughly the size of a Torx T3 or T4.&lt;br /&gt;&lt;br /&gt;The only reason I can imagine that manufacturers would use a fastener like this is sheer perversity. It isn't to make the devices tamper-proof -- the screws can be turned with a flat-head screwdriver of just the right width, although this is not ideal for either fastener or tool. Or, I could always just drill them out, as I've done on more than one occasion with a very stripped or damaged screw.&lt;br /&gt;&lt;br /&gt;To the best of my knowledge the correct tool is not available for purchase _anywhere_ for a nobody like me, although I think you can sometimes find tools for larger versions of the bits for sale on eBay.&lt;br /&gt;&lt;br /&gt;Several of these fasteners are apparently actually patented, and several apparently can't be legally sold except to properly licensed OEMs or other authorized personnel. Wiha sells, but will not sell to me, tamper-resistant Torx Plus tools, for example. And even if they would, they don't seem to have any this small.&lt;br /&gt;&lt;br /&gt;As far as I'm concerned, such restrictions should be illegal. I'm sure there is an analogy here to be made to software APIs. I'm reminded of a talk I saw by Stallman, in which he drew puzzle pieces representing APIs, and talked about the evils of proprietary APIs. I bought it, I ought to have the right to take it apart!&lt;br /&gt;&lt;br /&gt;By the way, the device in question is an iPod hard drive, made for Apple by Toshiba. But I'm sure there are many other variants of the same thing going on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4210420556474583034?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4210420556474583034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4210420556474583034' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4210420556474583034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4210420556474583034'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/02/pet-peeve-proprietary-fasteners.html' title='A Pet Peeve -- Proprietary Fasteners'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-3838842781811783170</id><published>2008-02-13T15:06:00.002-05:00</published><updated>2008-02-13T16:11:22.785-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Trying Programming Environments for Children</title><content type='html'>I am home sick today, feeling terrible and feverish, and should be sleeping, but can't sleep, so I thought I would try out some of the programming environments for kids. A while back I set up my son with the Haskell tools used for The Haskell School of Expression and Thompson's Craft of Functional Programming book, hoping my son would work his way into one of the texts a bit. He didn't get that far, so I thought I'd try out some other options for him.&lt;br /&gt;&lt;br /&gt;I started learning when personal computers came with BASIC interpreters built-in, so I am looking for something equally as easy to start with, although I think teaching my son BASIC might be considered child abuse.&lt;br /&gt;&lt;br /&gt;I thought I'd try to set him up with Hackety Hack, a Ruby environment found &lt;a href="http://hacketyhack.net/get/"&gt;here&lt;/a&gt;. On Ubuntu Gutsy, I found that it segfaults immediately upon launch. According to the forum this issue has been reported for close to a year, with no patch.&lt;br /&gt;&lt;br /&gt;OK, the next one on my list to try is Greenfoot. Greenfoot is Java-based, and requires a JDK. I haven't been a Java hacker since the dot-com crash, but at one point knew it pretty well, so how hard could it be for a feverish software engineer? My install of Gutsy tells me its java is "java version "1.7.0, IcedTea Runtime Environment (build 1.7.0-b21), IcedTea Client VM (build 1.7.0-b21, mixed mode, sharing)." So I'll try installing the IcedTea JDK. That looks promising, although the notes indicating it is a "temporary fork" make me a little nervous; Ubuntu lives up to its ease-of-use repuation, the JDK installs, and the Greenfoot installer now seems to be able to figure out for itself where the JDK is. The Greenfoot executable launches, and looks at least moderately interesting, so I'll call that a qualified success for now, and see if he can get his head around it.&lt;br /&gt;&lt;br /&gt;I had it on my list to check out Nodebox, but that's for MacOS X only, and today I'm on the Linux box, so we'll save that for another sick day.&lt;br /&gt;&lt;br /&gt;Finally, I wanted to take a shot at setting up Sugar, the Python-based environment that was designed for the One Laptop Per Child system. I'm not hugely keen on Python; having used Python and Ruby, I harbor a slight preference for Ruby, and I've got a laundry list of things I don't like about both of them. However, I'm being asked to use and get comfortable with extending several tools in my workplace that are based on Python, so for better or worse I'm getting myself re-familiarized with Python. It's quite a mature language with lots of libraries. My son could do worse, so let's see what Sugar has to offer.&lt;br /&gt;&lt;br /&gt;There are various ways to get Sugar going on Ubuntu. See the Wiki pages &lt;a href="http://wiki.laptop.org/go/Sugar_on_Ubuntu_Linux"&gt;here&lt;/a&gt;. To begin, I'm going to try the emulated route, where my Linux PC will literally emulate an OLPC laptop. The other options look considerably more complicated and error-prone; in particular, there is an absolute rat's nest of required packages. So let's see how painful setting up emulation is. First, we download a bzip'ed image file. While it is downloading, I install QEMU, which is not difficult. For now I'm not going to attempt to install the kernel support for accelerating QEMU; we'll see if it is really painfully slow. This machine is "only" a Pentium 4 2.8 GHz system that I built from parts a few years ago; pretty obsolete, but usually plenty fast.&lt;br /&gt;&lt;br /&gt;So, image is done downloading, unzip it, and try running QEMU on it -- it works! Although it does indeed take a very long time to launch. I still find it quite surreal to watch Linux boot on top of Linux!&lt;br /&gt;&lt;br /&gt;That's all for now -- I am still home sick, after all -- it's time to have some hot lemon tea and try to get a nap!&lt;br /&gt;&lt;br /&gt;Followup: installing the kqemu acceleration tools does make the OLPC image run _significantly_ faster -- it is quite tolerable now, although I have no idea how it compares to how the image runs on the target hardware itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-3838842781811783170?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/3838842781811783170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=3838842781811783170' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3838842781811783170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3838842781811783170'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/02/trying-programming-environments-for.html' title='Trying Programming Environments for Children'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-3793720612240598880</id><published>2008-01-16T12:15:00.000-05:00</published><updated>2008-01-16T12:31:08.524-05:00</updated><title type='text'>I Voted. I Think. Probably. Maybe.</title><content type='html'>So, I don't know if you have been following news of Michigan's primaries, but they seem to be an utter farce this year. There is some kind of a dispute between the national Democratic party and the state party. The side effects are:&lt;br /&gt;&lt;br /&gt;- Several of the biggest-name Dem candidates (Edwards and Obama among them) are not listed on the primary ballot.&lt;br /&gt;&lt;br /&gt;- There's a write-in option, but if you write in one of these missing candidates, your vote will not be counted for that candidate(!)&lt;br /&gt;&lt;br /&gt;- One of the candidates (Dodd) was listed, but he actually dropped out of the race earlier. (According to the results he still received 1% of the vote).&lt;br /&gt;&lt;br /&gt;The recommendation was that if you wanted to vote for someone else, you should vote uncommitted. According to the results on Wikipedia, a whopping 40% followed this recommendation.&lt;br /&gt;&lt;br /&gt;My precinct uses paper ballots with optical scanners. These are generally considered to be pretty reliable, and there is a paper trail in event of a recount. But this year, when I approached the scan machine, its counter read 466. After scanning my ballot, it still read 466. I asked the staff member about this -- she told me that it should read 466 and that if the machine took in the ballot and didn't spit it out, my vote was counted. Me, I'm not so sure. But the kids were in the car and my wife was late for a class so I didn't have time to stand there and try to determine exactly what was happening. But I left feeling somewhat uncertain that I had actually cast my vote. This just does not seem like democracy as it should be practiced!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-3793720612240598880?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/3793720612240598880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=3793720612240598880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3793720612240598880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3793720612240598880'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/i-voted-i-think-probably-maybe.html' title='I Voted. I Think. Probably. Maybe.'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6529868139441391604</id><published>2008-01-14T15:35:00.000-05:00</published><updated>2008-01-14T16:16:36.085-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Banking'/><title type='text'>A Bank Tries to Help Out</title><content type='html'>I got a call from Midwest Financial Credit Union -- it seems that someone in management read my blog post. We had a long and interesting conversation and I ended the conversation a much happier customer. For now, we are going to keep our accounts, and I am happy that they are doing some things to try to keep our business.&lt;br /&gt;&lt;br /&gt;Among the details:&lt;br /&gt;&lt;br /&gt;The hold on deposits was part of their anti-fraud measures in place automatically for the first 30 days of a new account. Apparently this is when they get hit with the most fraudulent deposits. A warning at the time we deposited the check would have helped us out.&lt;br /&gt;&lt;br /&gt;The $100 limit of check card transactions applies only when using the card like a credit card, as opposed to a debit card. So I can still use it as a debit and make reasonable-sized purchases. The staff member I spoke to agreed that the $100 limit is unreasonable for any real-world use and is going to try to get it raised. It would have been really helpful to be warned at the time the cards were issued, or better, beforehand, that this limit was going to be in force.&lt;br /&gt;&lt;br /&gt;So, why such a low limit?&lt;br /&gt;&lt;br /&gt;The conversation was illuminating. In recent years I have put in some effort and a lot of money to try to clean up my credit report. This included starting payment on some debts that were dormant for many years.&lt;br /&gt;&lt;br /&gt;The largest of these was a medical bill for a single night in the hospital. I was fully insured at the time, or so I believed; the hospital I presented my cards to told me that they accepted my insurance; but yet I would up owing somewhere north of $5,000 because my insurer did not want to pay what the hospital wanted to bill. The hospital was not one of the insurer's "preferred" providers.&lt;br /&gt;&lt;br /&gt;Ultimately my insurance provider paid almost nothing, but also revealed to me the collusion that goes on between hospitals and insurers -- the individual line item fees the hospital charges to their supported insurers are in some cases as low as 10% of the same item as it is billed to someone with no health insurance. But that is a rant for another day.&lt;br /&gt;&lt;br /&gt;I ignored this bill for many years more out of disgust and anger at the insurer and hospital than out of the inability to pay, but last year contacted the credit agency that owned the debt and started paying it down. It's now about 3/4 gone.&lt;br /&gt;&lt;br /&gt;I also had the interesting experienced of getting sued for an ancient phone bill. The bill was real, but I had become so disgusted at AT&amp;T's refusal to accept any payment plan other than immediate payment in full, and their dogpile of additional fees and charges, that I vowed they would not get a penny from me.&lt;br /&gt;&lt;br /&gt;Well, they did, but not willingly. The debt was sold, and sold again. I wound up paying an attorney to come up with a settlement for me, and paid the settlement. It was again highly illuminating to find out that the agency in question completely ignored several written settlement offers that I tendered, but as soon as an attorney's letterhead was involved, settled for less than I had offered. I have a piece of paper in my file that says the bill is paid.&lt;br /&gt;&lt;br /&gt;They say that no good deed goes unpunished, and it appears that settling one debt and nearly paying off another has damaged my credit rating, because both debts are now listed as currently "in dispute" instead of just hanging on as old debts. So, it is time to write some letters. There are procedures to go through to get items on a credit report corrected. But I refuse (again, on those damned principles of mine) to pay to receive my credit scores, so instead I will have to rely on the free annual reports I'm entitled to. Paying the rating agency for my scores seems too much like extortion, as if I had to pay eBay to improve my seller rating.&lt;br /&gt;&lt;br /&gt;So, on balance, I'm much happier with the Credit Union, but much less happy with the creditors who are screwing with my life. And I have more crap to deal with. But I guess that's what you need to do in order to play the banking game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6529868139441391604?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6529868139441391604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6529868139441391604' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6529868139441391604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6529868139441391604'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/bank-tries-to-help-out.html' title='A Bank Tries to Help Out'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-1231400926015176752</id><published>2008-01-07T14:03:00.000-05:00</published><updated>2008-01-07T14:33:18.944-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Banking'/><title type='text'>Banks that Suck</title><content type='html'>Sorry, still no Haskell content. Please don't delete my blog! I'm working on it.&lt;br /&gt;&lt;br /&gt;So, we were in the process of migrating our finances to a new bank, after our old bank, Republic, was pwned by Citizen's Bank and stopped doing all the things we liked about it, and started doing all the things we don't like (killing off our overdraft protection arrangement, stopping our various automatic repayment arrangements, removing access to our overdraft account from their online site, charging ludicrous fees, taking 3 days to clear electronic transactions, back-dating checks to try to hit is with more overdraft fees).&lt;br /&gt;&lt;br /&gt;Based our on readings of their various rates and policies, we chose Midwest Financial Credit Union, here in Ann Arbor.&lt;br /&gt;&lt;br /&gt;Less than a month later, we're now planning to close the accounts we just set up and continue our hunt for a decent bank that doesn't treat our accounts like an opportunity to slam us with fees at every opportunity -- just like Republic Bank didn't. I had my Republic account for about fifteen years and they helped me through many difficult times. Does such a place exist?&lt;br /&gt;&lt;br /&gt;Midwest Financial got on our bad side immediately by taking ten calendar days to process a deposited $3,000 check -- while we were out of town. They finally managed to clear it (I think they took it to the originating bank in Erie, Pennsylvania by riding a mule along the old Erie Canal). It's in the fine print that they're allowed to do such things, apparently. (It's in the fine print that they can do just about anything they want, apparently).&lt;br /&gt;&lt;br /&gt;Yesterday I tried to make a fairly large purchase (about $600) using a check card on the account -- it has a VISA logo). We have similar cards for our Citizen's Bank account and they function as either debit cards (with a PIN) or credit cards; they work fine, and we've never had an issue like this.&lt;br /&gt;&lt;br /&gt;Anyway, the transaction was denied. Today I got word in my e-mail that a much smaller purchase (about $125) that I made online was also denied. Which is odd, because according to our most recent statement we had just shy of $3,000 in that account.&lt;br /&gt;&lt;br /&gt;My wife went to the bank to talk to them and apparently someone's credit rating (possibly hers, since she opened the account) is rather low (we already knew that, thanks; that's old news, mostly from her days, now seven years gone, as an under-emplyed single mother), and therefore there is a $100 limit on transactions. Even though there is $3,000 in that account. Now, for a family of 5, $100 is not even a largish grocery store run. Some of these transactions could go through as debits, I guess, although there is probably some relatively low limit on the debit transactions as well. And we _have_ a card with a VISA logo because not everyone is setup to handle PIN-based debit transactions.&lt;br /&gt;&lt;br /&gt;They told her she can apply for a 48-hour waiver to make a large purchase, or in four months we can apply to have our "credit" limit raised.&lt;br /&gt;&lt;br /&gt;This is all too much. We're going to do neither; we're going to fire this goddamn bank and get our money back. I'm giving serious thought to turning our money into gold, silver, and platinum bars and burying them in undisclosed locations! Maybe we'll just keep our old accounts; we're starting to get used to the exact ways they screw us, as opposed to all these new ways! We are very fortunate in that here in 2008 we are finally getting ourselves to the point where we have a little bit of a safety margin in our accounts, which kept us from getting stranded while we were out-of-state on vacation. But if we didn't have that margin -- if we were still living close to the edge -- we'd have been absolutely screwed. And having been that indebted slob for most of my life, I'm only going to do business with institutions whose policies are designed to be fair to that person, not to make their problems far worse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-1231400926015176752?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/1231400926015176752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=1231400926015176752' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1231400926015176752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1231400926015176752'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/banks-that-suck.html' title='Banks that Suck'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-2062644328388083942</id><published>2008-01-04T13:31:00.000-05:00</published><updated>2008-01-04T14:33:17.059-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Holiday 2007'/><title type='text'>The Potts Vacation 2007</title><content type='html'>So, we are back and the holiday trauma is over. We took the family to visit my cousins in the Washington, DC area and saw various friends along the way. I have just a touch of ranting I have to get off my chest before I can write anything else!&lt;br /&gt;&lt;br /&gt;The trip, on Amtrak, went well for the most part. It is not easy, though, getting a disobedient pre-schooler, an infant, a teenager, two car seats, and a lot of unchecked luggage around.&lt;br /&gt;&lt;br /&gt;The train from Toledo to Rockville, MD was only late getting into Toledo by about an hour. I was rather surprised!&lt;br /&gt;&lt;br /&gt;We stayed in Gaithersburg with my cousin. We had planned to stay there each night, but things became more complicated. My cousin has just been diagnosed with a thyroid illness called Graves disease. This was making her unable to sleep and prone to a racing heart and anxiety attacks. This isn't good for a hostess who has to cope with two babies, so I really sympathized. We spent a couple of days staying out of her hair as much as we could, going to some of the Smithsonian Institution museums.&lt;br /&gt;&lt;br /&gt;To top it off, our hostess was scheduled to take a dose of radioactive iodine. We had to find another place to stay for the last couple of nights because our hostess was literally about to become radioactive, and her instructions advised her to avoid people, and especially children, as much as possible! So we had to scramble a bit.&lt;br /&gt;&lt;br /&gt;Another complication -- I deposited a check, which was going to cover some of the expenses for the latter part of our vacation, the Friday before we left, thinking that it would clear in a few days. A week later, though, acting on a hunch, I asked Grace to call the bank, and she found out that the check had not cleared, and in fact the funds would not be available until the tenth calendar day after making the deposit.&lt;br /&gt;&lt;br /&gt;We had just set up these new accounts because we were unhappy with our old bank, which was acquired, unilaterally cancelled our overdraft protection arrangement, instituted ridiculously punitive fees, and put in place various floats and back-dating of checks apparently designed specifically to absolutely maximize said fees.&lt;br /&gt;&lt;br /&gt;Granted, the ten calendar days, during the holidays, was only five banking business days, but in the world of Check 21 and electronic check clearing it seems just insane to me that an institution would hold a deposit that long. We were able to convince them to make enough of the funds available to cover several check card transactions we had just made, but our old bank -- the one I'm planning to leave -- clears all deposits overnight. It seems that this was technically legal under the Expedited Funds Availability Act, but I am distinctly unhappy with this, and contemplating whether or not I want to close these new accounts immediately and find another bank. (Do any of them not suck?)&lt;br /&gt;&lt;br /&gt;Fortunately, I had set aside a little bit of extra money in a savings account at our old bank. Using my other cousin's iPhone, was able to log in to the bank and move that money into checking. Did I mention the iPhone is very cool?&lt;br /&gt;&lt;br /&gt;We were able to stay with family friends for the last couple of days in Richmond, Virginia. Along the way I got to make Christmas better for two of their three sons. They had both gotten iPod Shuffles for Christmas. (I wonder how many people got iPod Shuffles for Christmas? It must be in the millions!) iTunes would not run correctly on their Windows XP box. They had taken it to a local Staples and the guru there had spent a whole afternoon trying to get it to work, and failed. The symptoms were this: iTunes apparently installed successfully, but would crash immediately after launching, with the usual "tell Microsoft about the problem" message. QuickTime player would also crash upon launch, with one of several error messages, including a security warning about stack overflow in a Visual C++ library. The uninstall process for iTunes and QuickTime always failed.&lt;br /&gt;&lt;br /&gt;Despite a distinct lack of expertise with Windows system administration, I decided to take a crack at it. I had to putz around for a long time. I Googled myself into a frenzy looking for notes from people with similar problems. I downloaded and ran several virus and trojan detectors. I installed every recommended Windows XP update I could find, and cleaned out a bunch of unused software. Nothing seemed to help. Finally, I forcibly uninstalled iTunes and QuickTime (removing everything Apple-related from the registry, and deleting the program directories). I then downloaded a whole series of earlier versions of iTunes, starting with 6.10. This one installed and ran without a hitch, so I started going version-by-version. At some point, I found an installer which said that it could not run properly because the VBScript service was not enabled. This led me to an Apple support article on enabling VBScript, which had probably been turned off by a security product. After that all the installers seemed to work and I was able to get the latest iTunes installed.&lt;br /&gt;&lt;br /&gt;The problems seems to be that one of the more recent iTunes installers silently fails if VBScript is not enabled. It runs and seems to believe that it has succeeded, but leaves behind an unusable QuickTime configuration. iTunes needs QuickTime and thus crashes on startup. Somewhere along the way Apple's installers lost the ability to verify that the necessary VBScript service is available.&lt;br /&gt;&lt;br /&gt;After finally getting iTunes working, I thought it was all going to come to nothing, because the iPod Shuffle itself was not working. iTunes could see it, and fill it up with music, but when it came time to turn it on and push play, it would just flash a series of alternating green and orange lights and do nothing. A complete reinstall of the Shuffle's firmware didn't help. Running Apple's separately available iPod Shuffle utility designed to fix this problem didn't fix it. I thought we might have to just send the iPod back. But then apparently just toggling the little switch between continuous play and shuffle made it suddenly work. This does _not_ fill me with confidence about the device's firmware, but it was working.&lt;br /&gt;&lt;br /&gt;Anyway, I spent a ridiculous five or six hours messing with this, but got a number of hugs in return when it finally worked. I can attribute my success only to being tenacious. Age and tenacity beats the 18-year-old Staples employee FTW!&lt;br /&gt;&lt;br /&gt;We also got the opportunity to meet up with my friend Antonio, and had a great chat with him.&lt;br /&gt;&lt;br /&gt;Although we gave ourselves what I thought was a sufficient safety margin, planning to arrive at the train station an hour and 45 minutes prior to scheduled departure, we had a couple of delays. We got slightly lost getting back to the train station, and so arrived only 20 minutes before the train was scheduled to arrive. While we were waiting at the light to turn into the station parking lot, it arrived. Then, under two minutes later, before we could even get inside the building, it left. Without us. &lt;br /&gt;&lt;br /&gt;So we had another night in Gaithersburg, at a Holiday Inn. That wasn't so bad. It meant I got to watch Iron Chef and soak in the tub. We had to get a hotel shuttle to the nearest metro station, then carry the car seats on the metro, while a friend of my cousin drove our luggage to the train station. He was a huge help. &lt;br /&gt;&lt;br /&gt;We spent New Years' Eve on the train. No one got much sleep, and we got back to Toledo on time (about 5 in the morning on the 1st). Then we had a drive back up to Ann Arbor. The drive turned into blizzard conditions. We had to crawl along moving at times just 25 mph, nervously looking at quite a few cars that had slid of the road. But we all made it back safely.&lt;br /&gt;&lt;br /&gt;Oh, we did nearly lose one of the babies. At the end of of our train, at the last door, where you could stand and watch the tracks retreating, Grace and I had come back and stood there and looked out the window. "I wonder if that door would open if I pushed the button?" she asked. "No way," I said. "I'm sure there is a security interlock of some kind so if it isn't connected to another car, it won't open. That would be a huge liability issue if there wasn't."&lt;br /&gt;&lt;br /&gt;Well, Veronica proved me wrong. We were walking up and down the train and she pushed the button to open the door. Fortunately, I was holding her hand. There is a kind of cage to prevent someone falling out, but it was really just a couple of metal bars and they were spaced far too widely to keep a child from pitching right out the door onto the tracks, from the upper level of a speeding train.&lt;br /&gt;&lt;br /&gt;Grace mentioned to the conductor that the rear door was unlocked. She saw, as she described it to me, "a black man turn white." Yes, it was supposed to be locked. He _ran_ back to lock it.&lt;br /&gt;&lt;br /&gt;So, that was our Christmas vacation. No casualties but my sanity. Now I just need a vacation from my vacation!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2062644328388083942?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2062644328388083942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2062644328388083942' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2062644328388083942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2062644328388083942'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/potts-vacation-2007.html' title='The Potts Vacation 2007'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-5968273752508155645</id><published>2008-01-03T19:42:00.001-05:00</published><updated>2008-01-03T19:42:43.661-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Geek Food'/><title type='text'>Brussels Sprouts with Toasted Cashews</title><content type='html'>I made up this recipe after being inspired by an episode of Iron Chef I happened to see on vacation. That was a venison battle, but one of the dishes involved brussels sprouts. My family tells me it is one of the tastiest dishes I've ever concocted. I served it on New Year's Day. It seemed like a very new-year-ish dish.&lt;br /&gt;&lt;br /&gt;If you don't like brussels sprouts, it could be because if you cook them by steaming or boiling, they tend to turn into nasty, bitter, sulfurous little cabbages. Cooking them in a dry method with high heat caramelizes them and releases wonderful complex nutty flavors and aromas.&lt;br /&gt;&lt;br /&gt;A warning: if you are not used to eating a lot of cruciferous vegetables, this dish may be a bit challenging to digest. You may need to sleep with the windows open!&lt;br /&gt;&lt;br /&gt;Serves 8, or me and three other people : )&lt;br /&gt;&lt;br /&gt;I served this with mixed greens (collards, kale, and mustard greens) cooked with sage-flavored bulk pork sausage and a loaf of challah with unsweetened butter. We had a Shiraz with it, but that was all wrong; it would have gone much better with a very cold Charonnay or Riesling.&lt;br /&gt;&lt;br /&gt;You will need:&lt;br /&gt;&lt;br /&gt;3 or 4 lbs. fresh brussels sprouts&lt;br /&gt;1 cup raw cashews&lt;br /&gt;Hard cheese (parmesan reggiano, aged gouda, etc) -- enough to yield 1/2 cup grated&lt;br /&gt;3 Tbs grapeseed oil&lt;br /&gt;2 tsp allspice or pumpkin pie spice mix (allspice, nutmeg, cinammon, cloves)&lt;br /&gt;1 tsp red pepper flakes (optional)&lt;br /&gt;Salt to taste&lt;br /&gt;&lt;br /&gt;For the spices, I actually used a leftover pumpkin pie spice mix that my wife made for Thanksgiving. I tend to cook by sniffing and tasting the spices and the raw food and deciding what seems like it would go well together. Trust your instincts!&lt;br /&gt;&lt;br /&gt;A heatproof bowl&lt;br /&gt;A large frying pan&lt;br /&gt;&lt;br /&gt;Prep: grate the cheese. The sprouts should be dry, so if you washed them, dry them completely with paper towels. Cut off the stem ends and make them into 1/4" slices. (Don't worry if some of them fall apart and you have loose bits -- the goal is to give the vegetables a lot of surface area).&lt;br /&gt;&lt;br /&gt;Heat half the oil to medium heat and throw in the cashews. Fry until nicely browned, turning constantly to avoid burning (perhaps 3 minutes). Scoop the cashews out into the heatproof bowl (make sure you get all the pieces of nut, or they will burn in the pan and ruin the flavor). Leave some of the nut-flavored oil in the pan. Add the cheese to the hot cashews and stir quickly. Set the nut mixture aside.&lt;br /&gt;&lt;br /&gt;Add the remaining oil to the pan and increase the heat to high. Before the oil starts to burn, toss in the brussels sprouts. You want to cook them quickly, turning several times to lightly brown the cut surfaces, until they are softened slightly and a bit brightened in color. They should release a nutty aroma. You don't want them to start cooking down and releasing a lot of liquid. On my stove this took 3 minutes or so, but your stove may vary. Add the allspice and red pepper flakes about halfway through cooking. Add the cashew/cheese mixture and mix. Add salt to taste (I threw in only a small amount, perhaps a quarter-teaspoon). Serve immediately.&lt;br /&gt;&lt;br /&gt;If you try this recipe, I'd be interested to know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-5968273752508155645?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/5968273752508155645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=5968273752508155645' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5968273752508155645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5968273752508155645'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/brussels-sprouts-with-toasted-cashews.html' title='Brussels Sprouts with Toasted Cashews'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-587534322166398331</id><published>2008-01-03T19:32:00.000-05:00</published><updated>2008-01-03T19:37:07.653-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Security Warnings with Ubuntu 7.10 (Gutsy) Updates</title><content type='html'>The most recent updates to Ubuntu suddenly started generating warning messages saying that the patches could not be authenticated.&lt;br /&gt;&lt;br /&gt;This is apparently a known bug in package bookkeeping. The procedure for fixing it seemed to be:&lt;br /&gt;&lt;br /&gt;1. sudo mv /etc/apt/sources.list /etc/apt/sources.list.backup&lt;br /&gt;2. sudo touch /etc/apt/sources.list&lt;br /&gt;3. Run the package manager and check for updates. You should see none; quit the package manager.&lt;br /&gt;4. sudo rm /etc/apt/sources.list&lt;br /&gt;5. sudo mv /etc/apt/sources.list.backup /etc/apt/sources.list&lt;br /&gt;6. Run the package manager again; this time you should be able to install the updates without warnings.&lt;br /&gt;&lt;br /&gt;Weird!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-587534322166398331?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/587534322166398331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=587534322166398331' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/587534322166398331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/587534322166398331'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2008/01/security-warnings-with-ubuntu-710-gutsy.html' title='Security Warnings with Ubuntu 7.10 (Gutsy) Updates'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7076048012944154501</id><published>2007-12-21T12:46:00.000-05:00</published><updated>2007-12-21T12:51:37.663-05:00</updated><title type='text'>Newegg Makes Good</title><content type='html'>Newegg is refunding me the camera and case and I was able to find the camera elsewhere in time, so it is all working out OK. They have excellent customer service, so I will no doubt be buying from them again in the future.&lt;br /&gt;&lt;br /&gt;Today is the shortest day of the year. It takes a lot of caffeine and St. John's Wort to keep me functioning this time of year. I think the barista at the local Caribou Coffee realized I needed a triple espresso and so I got a free upgrade. Either that or she was thinking "you know, we don't see you in here often enough... you're just not quite as addicted as we'd like you to be!"&lt;br /&gt;&lt;br /&gt;This year really was a challenge -- illness, death, and mayhem all around us. Let's hope 2008 is better!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7076048012944154501?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7076048012944154501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7076048012944154501' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7076048012944154501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7076048012944154501'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/12/newegg-makes-good.html' title='Newegg Makes Good'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-1942022353796972834</id><published>2007-12-19T12:27:00.000-05:00</published><updated>2007-12-19T19:04:03.051-05:00</updated><title type='text'>Newegg Screws Up</title><content type='html'>So, I decided rather late in the season to get my son an inexpensive digital camera for Christmas. I ordered it from Newgg, a company I've had great service from in the past. I bought a motherobard and CPU from them a few years ago; I've ordered various little things like flash drives and hard drives.&lt;br /&gt;&lt;br /&gt;They took the order for a camera, case, memory cards, and card reader. I paid with PayPal; everything went through normally. The package went out; it is supposed to be delivered today. I wanted to make sure of that, since we're obviously getting pretty close to Christmas, and my family is also planning on going out of town. In fact, we're taking the train out of town to see family. The plan was for my son to enjoy taking pictures of the trip. So it has to be here, or there wasn't much point.&lt;br /&gt;&lt;br /&gt;Today, the day that my UPS package I've been tracking is scheduled for delivery, I got a note saying that it was all just a joke... the package I've been tracking doesn't actually have a camera in it, and I should get a refund in two or three days. Oh, it does have a cheap little camera case in it, which I threw in just because they were shipping me the camera anyway. Which means I just paid $5.24 to ship a $10 camera case.&lt;br /&gt;&lt;br /&gt;I'm scrambling to try find the camera locally. I'm fortunate in that my finances aren't that tight right now, but if they were, I'd be completely screwed, because i wouldn't be able to charge the replacement camera on my debit card until the PayPal refund went through. &lt;br /&gt;&lt;br /&gt;I can't recall any company I've ever ordered from screwing up an order in quite this way. I mean, I've had items cancelled on me at the last minute, or delayed, but I've never, ever been charged for an item that was not actually shipped. I'm a bit boggled by just what kind of a failure in their IT infrastructure allowed the charge to go through. Wow!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-1942022353796972834?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/1942022353796972834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=1942022353796972834' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1942022353796972834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1942022353796972834'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/12/newegg-screws-up.html' title='Newegg Screws Up'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4007042470683270714</id><published>2007-12-18T00:32:00.000-05:00</published><updated>2007-12-18T09:58:40.923-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='School of Expression'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The SOE</title><content type='html'>I have been looking at Paul Hudak's book The Haskell School of Expression. My first barrier was getting the sample code to work under Ubuntu "Gutsy Gibbon." While I highly recommend Graham Hutton's book, which I think of as the K&amp;R of Haskell, SOE is more of a tutorial and may be more useful to people who learn by doing. I got a bit of assistance from Paul Liu. It turns out that in addition to installing ghc using &lt;span style="font-weight:bold;"&gt;sudo apt-get install ghc&lt;/span&gt;, I needed to install &lt;span style="font-weight:bold;"&gt;libghc6-opengl-dev&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Without this, when I tried to configure GLFW using &lt;span style="font-weight:bold;"&gt;runhaskell Setup.hs configure&lt;/span&gt;, I got an error that said &lt;span style="font-weight:bold;"&gt;Setup.hs: cannot satisfy dependency OpenGL&gt;=2.1&lt;/span&gt;. I went down a dead end of trying to figure out what kind of package I needed to install to give me the right OpenGL libraries, but the key was realizing that it is looking for the Haskell OpenGL library, not the system library.&lt;br /&gt;&lt;br /&gt;This is not specifically mentioned in any of the docs I found online -- the only place I found it mentioned was on the Debian package list -- so I am mentioning it here! Maybe if someone with the same issue is Googling for the answer, they will now find it quicker.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4007042470683270714?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4007042470683270714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4007042470683270714' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4007042470683270714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4007042470683270714'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/12/soe.html' title='The SOE'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-1472779892732009286</id><published>2007-12-17T20:50:00.000-05:00</published><updated>2007-12-17T21:08:55.624-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Music Theory'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Getting Back Online with Music Theory</title><content type='html'>Well, this hellacious year is almost over. Most of my spare time has been spent on the archiving and family history project, which I'm documenting at &lt;a href="http://armstrong-collection.blogspot.com"&gt;The Marcella Armstrong Memorial Collection&lt;/a&gt;. That project is bearing fruit in that I have almost a thousand images scanned, and so I'll be giving some of the originals to family members. I've created some beautiful prints, as well, and over Christmas I'm hoping to share some of the images with family members in the form of slideshows.&lt;br /&gt;&lt;br /&gt;Meanwhile, in the back of my mind I'm thinking about how to get back into Haskell programming. Music theory keeps coming to mind.&lt;br /&gt;&lt;br /&gt;The problem with music theory is that it is really a collection of ad hoc convenient rules and relationships in the guise of a coherent theory. The various named entities have completely inconsistent nomenclatures. You kind of get used to this when you learn to play chords and transcribe songs, but it is easy to forget how inconsistent it is and thus confusing for students.&lt;br /&gt;&lt;br /&gt;For example, intervals. A major second is an interval also known as a whole step. If you start on the root note of a scale, say, a C major scale, the C is known as the root or "first." If you add a major second to a first, you might imagine that you'd get to a third note of the scale. But, no, you have a second note.&lt;br /&gt;&lt;br /&gt;Does that mean the steps in the scale are off by one in their naming (that is, the first is really the zeroth?) No, because if you add two major seconds to the root, you have a third, not a fourth. It is the naming of the intervals that are off.&lt;br /&gt;&lt;br /&gt;So can you just start the intervals at zero instead of one? Well, kind of. A minor second is a half-step, or the difference between adjacent keys on a piano. Call that 0.5. A major second is then 1.0. But this still doesn't explain intervals, because a "fourth" is actually three whole steps and a half step. And if you add a third and a third, you don't have a sixth, you have a flat seventh!&lt;br /&gt;&lt;br /&gt;So it keeps coming back to me that I should try to codify the rules of intervals and chords in some bits of Haskell code. It might even be of use to geeks trying to understand music theory.&lt;br /&gt;&lt;br /&gt;Don't even get me started on time signatures or tuning!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-1472779892732009286?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/1472779892732009286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=1472779892732009286' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1472779892732009286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1472779892732009286'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/12/getting-back-online-with-music-theory.html' title='Getting Back Online with Music Theory'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-2793715217195058889</id><published>2007-10-30T10:53:00.000-04:00</published><updated>2007-10-30T10:54:05.930-04:00</updated><title type='text'>Memento Mori</title><content type='html'>So, I have been falling behind on all sorts of commitments -- I was excited by the prospect of working through a bunch of Haskell exercises and get more serious about learning Haskell; I was learning all kinds of new jazz chord voicings in my guitar lessons; I had plans to record another podcast with original music.&lt;br /&gt;&lt;br /&gt;Instead life intervened, and my mother died after a brief, unexpected illness, and then Grace's father died just under two weeks later. We've had a lot of death recently -- my grandmother died two years ago, at the age of 102, and Grace's brother died at the age of 40 just last year.&lt;br /&gt;&lt;br /&gt;"Memento Mori" means roughly "remember, you will die." There's nothing quite like sitting in a room with the dead body of your mother to make this clear. It has been my task this year to think pretty hard about this, and to try to start planning for it, beginning what I hope will be my "ars moriendi" -- the art of dying well. And, I hope, a lot later.&lt;br /&gt;&lt;br /&gt;I've been living on a kind of "split screen" for the last few months -- on the one hand, working on retirement plans and investments for my children's education and imagining what Grace and I are going to do for the next five, ten, twenty, or forty years, and on the other hand preparing our wills and making sure we are properly insured. It's been a strange combination of unnerving and reassuring. My grandmother made it to 102, and I have her genes, so I could have 60 years or more to live. Or I could take after my mother, and have 30.&lt;br /&gt;&lt;br /&gt;Or none.&lt;br /&gt;&lt;br /&gt;On the way to work this morning, as often happens, the light changed for me to make a left turn. I did my usual deep breath, look both ways, count slowly to five -- to wait for whoever was going to blast through the red light to go ahead and do so -- and then started to enter the intersection. At the ten second mark a woman in an SUV blasted through the red light, going way over the speed limit, talking on her cell phone. Missing me by only a few feet.&lt;br /&gt;&lt;br /&gt;Memento, mori.&lt;br /&gt;&lt;br /&gt;A year ago someone did this and I was hit by such an attack of road rage I actually chased him down, cut him off and forced him over to the side of the road, then got out of the car and chewed him out for nearly leaving my children fatherless. I can't advocate that behavior. Today I took a deep breath and let it go.&lt;br /&gt;&lt;br /&gt;It would be a stupid way to die. But so is cancer, or heart disease. And we don't have control over everything. And believing that we do is a recipe for a heart attack.&lt;br /&gt;&lt;br /&gt;There is good news in our lives too -- we just celebrated our sixth wedding anniversary and baby Sam's first birthday and baby Veronica's third birthday -- but these celebrations have all been kind of subdued.&lt;br /&gt;&lt;br /&gt;There have been a whole bunch of miscellaneous estate issues -- fortunately my stepfather and the estate attorney have been managing most of this -- but my stepfather wants to sell the house he and my mother shared in the very short term, and so is trying to dispose of my mother's personal effects very quickly.&lt;br /&gt;&lt;br /&gt;This means a house full of furniture, clothes, and personal effects. Since I'm the son that lives a mere 250 miles away, instead of 2,000, I'm the one that has to figure out how to triage everything and move anything we want to save into our rather cramped and cluttered apartment. Which means a major purge of our existing clutter, and also coming to terms with letting go of almost all of my mother's personal effects.&lt;br /&gt;&lt;br /&gt;Along the way I discovered that my mother and my grandmother had amassed a huge collection of family photos and documents, going back several generations. In addition, hundreds of documents: letters, journals, autobiographies, even short stories.&lt;br /&gt;&lt;br /&gt;We have pictures of people I think are my son's great, great, great, great grandparents. I have not identified everyone yet, but there may even be pictures of a five-greats grandparent. My grandmother was a member of the Daughters of the American Revolution, which means she can trace her ancestry back to 1776. Which means my daughter can, too. That's good, because it appears from the organization's somewhat controversial history that they could use more black members!&lt;br /&gt;&lt;br /&gt;There are Civil-war era photos. Cyanotypes from around 1900. Thousands of photographs -- perhaps 10,000. The oldest ones are mostly in pretty good shape, but many of the color photos, for example instant photographs from the 1970s, are fading badly. And there are some serious preservation issues -- photos that were recently annotated in ballpoint pen ink, which is acidic and eats through the paper until it stains the emulsion. Photos torn from albums and scotch-taped into new albums, or bundled together with paper clips or rubber bands and stuffed into acidic paper envelopes and shoe boxes.&lt;br /&gt;&lt;br /&gt;I decided, and Grace concurred, that I was going to engage on a preservation and archiving project. We can't let the collection of family history end with my generation. So I have embarked on that project, which will consist of organizing, cataloging and propagating both the original artifacts and digital derived works.&lt;br /&gt;&lt;br /&gt;So, for the immediate future, this project is now my highest priority. My other projects, blogs, and commitments are largely at a standstill. I apologize to everyone who I've ignored or failed to follow up with on some promise or another. But I think my children  and grandchildren will approve.&lt;br /&gt;&lt;br /&gt;Anyone interested can follow my progress on my blog, &lt;a href="http://armstrong-collection.blogspot.com"&gt;The Marcella Armstrong Memorial Collection&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2793715217195058889?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2793715217195058889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2793715217195058889' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2793715217195058889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2793715217195058889'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/10/memento-mori.html' title='Memento Mori'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-3202993763229196286</id><published>2007-08-31T19:55:00.001-04:00</published><updated>2007-08-31T19:55:43.119-04:00</updated><title type='text'>Another Death in the Family</title><content type='html'>We just received word that Grace's father, my father-in law, died today at about 6:10 p.m. He died just 13 days after my mother.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This means that this month we lost both my mother and my wife's father. Our children just lost two of their four grandparents in a span of just under two weeks. Isaac, at 13, was old enough to get to know them a little bit, but Veronica and Sam, at 2 years 10 months and 10 months, respectively, will never really get to know them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's been a hell of a month. Since bad things usually come in threes, it makes me wonder what we're facing next! Maybe it's my turn?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-3202993763229196286?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/3202993763229196286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=3202993763229196286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3202993763229196286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3202993763229196286'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/08/another-death-in-family.html' title='Another Death in the Family'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-8208871592637324199</id><published>2007-08-22T14:40:00.001-04:00</published><updated>2010-03-18T13:07:20.680-04:00</updated><title type='text'>Eulogy for My Mother</title><content type='html'>(This is not about Haskell or even programming per se, but it is, in part, about the interaction between technology and human lives and the limits of that technology, and about focusing on what is important in life. So I thought the Haskell community might forgive me for posting it in this forum. I hope to get back to writing about Haskell soon).&lt;br /&gt;&lt;br /&gt;Dear Mom,&lt;br /&gt;&lt;br /&gt;In the past few years, whenever something happened in my life, good or bad, I always got the urge to call you and bring you up-to-date, reassure you, and get your reassurance and advice. For the past few weeks, I've had that urge to call you constantly, because a lot of big changes have been happening. Now I can't call you, but I can still write you a letter. I can't mail it to you, but here is what it says.&lt;br /&gt;&lt;br /&gt;The big news is that you have died. This was quite a shock to everyone. It happened very fast. You had a lot of things going on -- oxygen masks, IVs, tests, pain medication, sedatives, all kinds of doctors and nurses, and lots of family members with worried expressions on their faces. It must have been very confusing, especially in the last few days, so I thought I would explain to you what happened in case you were confused.&lt;br /&gt;&lt;br /&gt;About two years ago you were treated for breast cancer with a combination of surgery, chemotherapy and radiation. I know that was very hard on you, but the treatment seemed to be quite successful. You recovered some energy and were able to spend quite a bit of time in the last two years traveling with your husband. You were getting regular follow-up care to make sure the cancer did not come back.&lt;br /&gt;&lt;br /&gt;About three weeks ago, after a short trip to Chataqua, New York, you were exercising with your friends at the YMCA. Things didn't feel right, though; you had been complaining about a feeling of bloating and pain in your abdomen. You said that you must have eaten something that didn't agree with you. You were only a few days away from your regular follow-up visit with your doctor. But when you called and told him about the problem, he suggested you go to the Emergency Room immediately.&lt;br /&gt;&lt;br /&gt;From that point everything started moving with frightening speed. You had a CAT scan, and it showed tumors in your abdomen. It isn't exactly clear whether these might have been caused by cancer cells from the breast cancer or whether it was another, separate case of ovarian cancer. It doesn't really matter much at this point.&lt;br /&gt;&lt;br /&gt;It would be easy to get very angry at your doctors and blame them. I find it a bit hard to believe that oncologists screening someone regularly for cancer would fail to detect such an advanced case of cancer. It isn't like you came down with a rare tropical disease that was outside their specialty. If anything I would have expected them to suspect cancer and do extra tests to rule it out even when it wasn't there. However, it is important to note that this kind of cancer, in the abdominal cavity, often has no detectable symptoms at all until it is very advanced. And I remind myself that the treatment you got two years ago did restore your health and give you two good and enjoyable years you would not have had otherwise.&lt;br /&gt;&lt;br /&gt;Anyway, the next thing was that you went down to the Magee-Womens hospital in Pittsburgh for some tests. The plan then was to find out what was going on and make a treatment plan. But your pain got rapidly worse. You were admitted. I spoke to you on the phone each day for a couple of days. I was making plans to come and trying to arrange with my father and brother to come too. We got the word that you had been moved to the intensive care unit, and so everything went into high gear. We moved up our visit. My brother and my father arranged to fly out. We all got into Pittsburgh the evening of Thursday the 9th of August, just after a series of severe storms had produced tornadoes and flooding. When my father and brother got in by plane around midnight they immediately went to the hospital. Grace and the children and I all came to visit too, in the middle of the night.&lt;br /&gt;&lt;br /&gt;You were miserable and frightened in the ICU. You were curled up on your side, wearing an oxygen mask, with your eyes tightly closed. You were able to talk, but mostly we just wanted to hold your hand. It took a while for us to figure out exactly what was going on. You had a a partially collapsed lung, and fluid building up around your lung. It was hard for you to breathe. You had pneumonia in one lung. You also had some sort of kidney infection. But with tubes and antibiotics and a lot of moral support over the next day or so you improved. You got your eyes opened and we were able to sit and talk with you. We talked about how you were doing, what we knew and didn't know about your condition. We told you about our families and how well everyone was doing. We talked about dying and what we thought it might be like, and what you believed and we believed would happen to you after you died. We told you we loved you.&lt;br /&gt;&lt;br /&gt;You were moved back into a regular hospital room. This was still not a very comfortable environment but it was a far less frightening place than the ICU. Over the next couple of days you had a lot of visitors -- your husband Dick, your daughter-in-law Carolyn, my father Richard, my brother, your niece Linda, your nephew David, and Grace and the kids. We arranged for people to stay with you round-the-clock. Often one of us would be with you in your room while another one of us caught a quick nap in the waiting room next door.&lt;br /&gt;&lt;br /&gt;One night while my brother was sitting with you during the middle of the night you began fighting to get out of bed. My brother tried to use the call button to get help but it didn't work. He had to run out into the hall and yell for help. You managed to get partly out of bed and it is a miracle you didn't tear out an IV. But you had a breathing crisis and you had to go back onto the high-pressure oxygen mask. You hated that mask because it was painful; it rubbed your face raw and dried out your lips and mouth terribly. For a few days it went back and forth like that. You'd improve a little bit; you got a transfusion and some new drugs and that seemed to help. But you'd get worse in the middle of the night.&lt;br /&gt;&lt;br /&gt;The CAT scan and biopsy was postponed again and again. The doctors found that you had blood clots in your leg and also that something had gone wrong with your heart. It was very weak and it appears that you may have had a heart attack, or maybe it was damage from your previous chemo or radiation. The radiation in particular may have been poorly administered. Or maybe it was all three. They put you on heparin to thin your blood. They decided they could not do a biopsy. At one point the doctors were considering putting you back into the ICU but you did not want to go back. What you wanted was to leave the hospital, and to go up to a nursing home in Erie so that you could die in comfortable surroundings.&lt;br /&gt;&lt;br /&gt;This brings me to the point of talking about your wishes. You made clear both in your written directives that if there was no chance of recovery, you did not want invasive procedures or extreme measures taken that would just serve to prolong your life. You told these things to the doctors as well -- no tubes for breathing or feeding, and no zapping your heart with electricity if it stopped. It is one thing to check some boxes on a form, but I think it is quite another thing to realize that it is time for these directives to be carried out. I was, in fact, awed by your bravery in sticking to your principles.&lt;br /&gt;&lt;br /&gt;So, we next focused all our attention on trying to get you moved to Erie. I have to confess that I was terrified that you would die before we could carry out your wishes. But there was only one day's delay, and on the morning of Tuesday, August 14th, the ambulance crew came to take you to Erie. I rode in the front of the ambulance with the driver while you were in the back with the nurse. For me it was the longest chunk of uninterrupted quiet time I had gotten since leaving for Pittsburgh and I finally broke down crying for a while.&lt;br /&gt;&lt;br /&gt;I thought that the stress on the family was going to let up and that you would be in good care. But apparently hospice care in Michigan and Nevada and California is much different than the hospice care arrangement we had in Erie. They got you settled comfortably into a room at the Manchester Presbyterian Lodge. The social worker and hospice nurses and nursing home administrator and head nurse greeted us. But things did not go quite like we planned.&lt;br /&gt;&lt;br /&gt;All of your IVs and needles and big heavy oxygen masks were removed. Instead you just had a simple cannula in your nose for oxygen. Your pain medication was changed to liquid morphine by mouth. But after 24 hours it became clear that things weren't quite right. You went from being able to communicate to sleeping around the clock. You were over-medicated. It also became clear that without some orders from the doctor, guidance from the hospice organization, or specific requests from family, the nursing staff at the home was not going to give you special care. For example, they still had you on a regular diet. They would plunk down a meatball sub on your table and take it away an hour later. Because you were so heavily drugged they would not even try to get fluids into you. You asked for pen and paper to write some notes but you were so sedated that we could only read a few words of what you wrote. You wanted to communicate but you couldn't. The system was failing you again.&lt;br /&gt;&lt;br /&gt;So once again the family went into high gear. We started a round-the-clock visiting schedule with you. We had to feed you because the nurses were not trying hard enough. We got your diet changed to food that you were better able to eat. We started trying to get your doctor to change your prescription, but we were unable to get the doctor out to examine you in person and change your orders until the evening of your third day there. Your condition was changing for the worse so rapidly that we found this completely unacceptable. I began refusing part of your medication on your behalf.&lt;br /&gt;&lt;br /&gt;This was probably the most nerve-wracking experience of my life, because above all I did not want you to be in any pain, but I thought that you deserved to share your last days with your family and friends. I think it was the right decision, though. You became alert again, while reporting that you were not in any pain. You were able to visit with family and friends. We got round-the-clock visitation going again. Carolyn came back, and brought her daughter Alicia. You had live music. You had grandchildren visit. You had a couple of good days.&lt;br /&gt;&lt;br /&gt;We still felt like we had to watch over everything. Even after your doctor came back and changed your medication orders, although my father followed him down to the nurses station to see what he wrote, what he wrote was not what he had just agreed to write. Your doctor was literally attempting to euthanize you -- not to help you live out your last days as well as possible, but to drug you up and ignore you until you died.&lt;br /&gt;&lt;br /&gt;I felt like we were having to act as doctor and nurse and social worker ourselves, all the time. Between the lack of sleep and the nervousness, I completely exhausted myself, to the point where I could not walk and began having hallucinations from lack of sleep. I developed an ulcer. The rest of us were also exhausted. It was the single most stressful week of my life to date.&lt;br /&gt;&lt;br /&gt;You gradually became weaker. Your heart rate went up and your blood pressure went down. You began to accumulate more fluids in your lungs. We got your medication raised again so that there was no possibility you would be in any pain. The decision was made that you could not receive anything more by mouth to eat or drink. On Saturday evening at about 6:30 p.m. you died. It was as peaceful and graceful a death as we could make it. I was not there, but your husband and his daughter Alicia were there. Alicia was playing music.&lt;br /&gt;&lt;br /&gt;I just want to say a couple more things.&lt;br /&gt;&lt;br /&gt;First, that the way you faced your death was an inspiration to me and to everyone around you.&lt;br /&gt;&lt;br /&gt;Second, when my father and I were visiting you in the ICU, you said that you were very proud that you had always had the ability to forgive everyone who had harmed you. I would like to ask you one last favor. I want you to forgive the doctor in Erie who displayed such indifference to your condition. I want you to forgive the other doctors that failed to detect your cancer. I even want you to forgive the doctor in Pittsburgh who had such terrible bedside manner that he burst into your hospital room, explained loudly that your heart was failing and that there was nothing more they could do, and left. I will forgive all these people. It might take me a while longer, though. I'm not quite as good at it as you were.&lt;br /&gt;&lt;br /&gt;Third, I'd like you to remember that we had our share of doctors with poor bedside manner and nurses who treated you like an annoyance, there were also quite a few people who were very kind to you. The hospice nurse who was with you on your last day was wonderful. The palliative care physicians in Pittsburgh were wonderful. They spoke very calmly to you and asked you if you had any unfinished business. You said that you wanted everyone to know that you loved them.&lt;br /&gt;&lt;br /&gt;And last, I just want to thank you. You were a single mother in a difficult time. You had a hard and complicated life. You raised me and my brother. You did a great job. You re-married and brought new fathers into our lives. You cared for my stepfather Wence, and you cared for your mother, and you cared for your husband Dick. You enriched the lives of everyone around you. You had a lot of friends and you were well-loved, and you still are.&lt;br /&gt;&lt;br /&gt;We'll go on. We'll miss you terribly. I wish you had gotten more time to enjoy your grandchildren. I wish we had gotten more time to spend with you. You said that you were concerned about the state of the world. The world will go on. It will be OK. We'll be OK. And we know that you are OK now too.&lt;br /&gt;&lt;br /&gt;I'll see you again, before too long. And I'll be in touch.&lt;br /&gt;&lt;br /&gt;Love,&lt;br /&gt;&lt;br /&gt;Paul&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-8208871592637324199?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/8208871592637324199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=8208871592637324199' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8208871592637324199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8208871592637324199'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/08/eulogy-for-my-mother.html' title='Eulogy for My Mother'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7735780701596994822</id><published>2007-05-07T00:42:00.000-04:00</published><updated>2007-05-07T23:49:34.545-04:00</updated><title type='text'>A Hard Dive Headache</title><content type='html'>This isn't exactly programming-related per se, but I present henceforth my story demonstrating how hardware compatibility issues trump software compatibility any day!&lt;br /&gt;&lt;br /&gt;I have a PC and a Mac on my desk at home.&lt;br /&gt;&lt;br /&gt;I have a small handful of spare hard drives I use to back up these computers plus two laptops.&lt;br /&gt;&lt;br /&gt;I try to buy hard drives when they hit a price bang-for-buck "sweet spot" -- this year, that is in the 250G range; a couple of years ago, it was in the 40G range. So I have a couple of 250G La Cie enclosures. I also have a couple of fanless "Mad Dog Multimedia" enclosures which I bought empty and filled with Seagate 40G drives. They're both USB/FireWire, which is ideal for moving things around between Macs and PCs.&lt;br /&gt;&lt;br /&gt;All of them come with external power bricks. The power bricks for all four drives are nearly identical, physically, black boxes with removable AC cables and attached DC cables. The boxes have little green LEDs. They all have identical DIN-4 round 4-pin connectors. These have a little notch on one side and a flat spot on the other, to make sure you orient them correctly when you plug them in, and identical DIN-4 connectors that plug into the drives.&lt;br /&gt;&lt;br /&gt;They're all plugged in to power strips on my desk.&lt;br /&gt;&lt;br /&gt;The "Sunpro Powmax" bricks that came with the Mad Dog enclosures have a little diagram on them that looks like this (sorry, I don't have a digital camera that will zoom in close, or I'd take a picture).&lt;pre&gt;            _____ &lt;br /&gt;          /       \&lt;br /&gt;GND ---- | *     * | ---- GND&lt;br /&gt;+12V --- | *     * | ---- +5V&lt;br /&gt;          \       /&lt;br /&gt;           --__--&lt;/pre&gt;On the diagram above, the flat side of the connector is shown at the top, and the little "notch" is not shown, but it goes at the bottom.&lt;br /&gt;&lt;br /&gt;The LaCie bricks, on the other hand, made by "Sunfone" instead of "Sunpro," have a little diagram that look like this:&lt;pre&gt;     --  ---&lt;br /&gt;    /  \/   \&lt;br /&gt;2  | *     * | 1  PIN 1:5VDC&lt;br /&gt;4  | *     * | 3  PIN 2:12VDC&lt;br /&gt;    \_______/     PIN 3:GND&lt;br /&gt;                  PIN 4:GND&lt;/pre&gt;Where the flat part of the circle is at the bottom and the little notch is at the top, although this is actually pretty hard to distinguish in the diagram.&lt;br /&gt;&lt;br /&gt;I'll flip them around for you so the orientation of the circular connectors is the same, and label the pins more clearly:&lt;pre&gt;    __-----__           __-----__&lt;br /&gt;  /           \       /           \&lt;br /&gt; |   G     G   |     |    G    G   | &lt;br /&gt; |  +12V  +5V  |     |   +5V  +12V |&lt;br /&gt;  \           /       \           /&lt;br /&gt;    -___/\__-           -___/\__-&lt;/pre&gt;Just let that sink in for a moment.&lt;br /&gt;&lt;br /&gt;It took me a while to guess why my hard drive, a 250G La Cie drive, wouldn't mount. Finally I started looking at the power bricks. You know that feeling you get when you find out that you've just broken something expensive?&lt;br /&gt;&lt;br /&gt;I guess it could have been worse; it could have fried the PC's motherboard too, via the USB port. Who designs this crap? (I know who builds it, but I can't very well blame this on the manufacturers in China; it appears they both did a wonderful job manufacturing exactly what was specified).&lt;br /&gt;&lt;br /&gt;Both power supplies have all the appropriate regulatory agency approvals: CE, FCC, UL, and some others I don't recognize. But, of course, they don't actually conform to any particular wiring standard.&lt;br /&gt;&lt;br /&gt;After determining that the La Cie drive was out of warranty, and given that the warranty was unlikely to cover this kind of idiocy, I decided to try opening up the enclosure in the hopes that it might have some kind of fuse that I could replace, and that the drive itself was OK.&lt;br /&gt;&lt;br /&gt;Surely they must have some kind of fuse in the enclosure's circuitry, right?&lt;br /&gt;&lt;br /&gt;I'll bet you a new hard drive that they don't.&lt;br /&gt;&lt;br /&gt;Well, the La Cie enclosure is a pretty nice enclosure, but it isn't designed to come apart. They have part of the drive covered with an easily torn (yes, I should know) adhesive foil, and mounted on some kind of sticky silicone anti-vibration pad. I could try stuffing a new drive in it at some point.&lt;br /&gt;&lt;br /&gt;The dead drive smells like burning plastic. There's one little surface-mount component on the back that is visibly burnt. If this were 1980, with my knowledge I gained putting together Radio Shack 250-in-one electronic experiment kits, I would be able to tell you if it is a resistor or a capacitor or a diode. If this were 1980, I could probably even solder on a new part. But it is 2007 and all the little black parts look the same, and even if I could find a replacement component I doubt I could solder it on.&lt;br /&gt;&lt;br /&gt;Needless to say, the drive would not spin up when I put it in the "Mad Dog" enclosure.&lt;br /&gt;&lt;br /&gt;So I put the 40G drive back into the "Mad Dog" enclosure, and powered it up.&lt;br /&gt;&lt;br /&gt;I'll give you two guesses which kind of power brick I plugged it into.&lt;br /&gt;&lt;br /&gt;My office smells like burning surface-mount components. There's a nearly identical little burnt component on the other drive. It's in a slightly different place on the 40G drive.&lt;br /&gt;&lt;br /&gt;I had some files on those drives that I wanted. The 250G drive had mostly unimportant stuff, but a few gigabytes of important stuff.&lt;br /&gt;&lt;br /&gt;I'm no fool. I kept a backups of that handful of important files.&lt;br /&gt;&lt;br /&gt;On another hard drive. Guess which one?&lt;br /&gt;&lt;br /&gt;I've got a headache.&lt;br /&gt;&lt;br /&gt;I can't in good conscience ask Seagate to fix them under warranty. Can this kind of thing even be repaired any more? It seems like it should be possible. But I'll have to look into that later.&lt;br /&gt;&lt;br /&gt;I'm going to bed. Ever feel like you want to yell at someone for being an idiot, but the only one you can find is between your own chair and keyboard?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7735780701596994822?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7735780701596994822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7735780701596994822' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7735780701596994822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7735780701596994822'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/05/hard-dive-headache.html' title='A Hard Dive Headache'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-8566310372188541493</id><published>2007-04-09T23:11:00.000-04:00</published><updated>2007-04-09T23:19:27.305-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><title type='text'>A Wonderful Waste of Time</title><content type='html'>I just encountered this great &lt;a href="http://mathsnet.net/geometry/solid/houses.html"&gt;toy&lt;/a&gt; to challenge your three-dimensional geometry skills. The game in effect asks you to pretend you're creating an Escher-like puzzle, producing a an object that only looks right from three precise vantage points. Ever wanted to pretend to be a 3D rendering optimizer function? Now's your chance!&lt;br /&gt;&lt;br /&gt;Warning: if you start it, you won't be able to stop until you complete all the puzzles. Which I did, although it took me an embarassingly long time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-8566310372188541493?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/8566310372188541493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=8566310372188541493' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8566310372188541493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8566310372188541493'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/04/wonderful-waste-of-time.html' title='A Wonderful Waste of Time'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-2586088976799473149</id><published>2007-04-09T21:28:00.000-04:00</published><updated>2007-04-10T11:36:26.313-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Haskell for the Short Attention Span: A Simple File Filter</title><content type='html'>Well, there is more to say about run-length encoding and other interesting examples I was sent in response to my last article, but today I've been working on another little real-world problem. I've been able to spend a little bit of time on #haskell and the gang there has been extremely helpful. The task: filter a binary log file, turning it into a text representation, and do some stateful validation. I'm not going to show you all the code (it is pretty boring), but here are the minor pitfalls and helpful suggestions I encountered along the way. First, I started with a very basic file filter example from the Haskell 98 report:&lt;pre&gt;main = do&lt;br /&gt;        putStr "Input file: "&lt;br /&gt;        ifile &lt;- getLine &lt;br /&gt;        putStr "Output file: "&lt;br /&gt;        ofile &lt;- getLine &lt;br /&gt;        s &lt;- readFile ifile &lt;br /&gt;        writeFile ofile (filter isAscii s)&lt;br /&gt;        putStr "Filtering successful\n"&lt;/pre&gt;Pretty simple. As a sanity check, I wanted to run this example on a data file. The first thing I found is that isAscii is not in the default namespace. To use this program in GHC you'll need to import the module Char. You can learn this via Hoogle. I've started using Hoogle quite a bit; it is a great little tool! You can find Hoogle &lt;a href="http://haskell.org/hoogle/"&gt;here&lt;/a&gt;. You can also get to it directly through #haskell via LambdaBot. Or you can put it right in your GHCi. Lambdabot lives &lt;a href="http://www.cse.unsw.edu.au/%7Edons/lambdabot.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Anyway, the next thing I found was that, at least under Cygwin, unless you explicitly open a file in binary mode, you might encounter problems. One I should have anticipated -- you might see line feed translation. But there are apparently others -- like silent truncation of the data! Somewhere in the guts of Cygwin, or maybe Windows, control codes designed back in the Jurassic days of computing are still being honored. Input was terminating on (apparently) an EOF character in my binary file. Another suggestion from one of the very smart folks on #haskell.&lt;br /&gt;&lt;br /&gt;I'll just use &lt;span style="font-weight:bold;"&gt;readBinaryFile&lt;/span&gt; instead of &lt;span style="font-weight:bold;"&gt;readFile&lt;/span&gt;, right? Well, no, readBinaryFile is part of MissingH, a third-party library. Back to #haskell, where I was advised that I could roll my own. Importing &lt;span style="font-weight:bold;"&gt;System.IO&lt;/span&gt;, I use the following snippet:&lt;pre&gt;readBinaryFile s = System.IO.openBinaryFile s System.IO.ReadMode &gt;&gt;= System.IO.hGetContents&lt;/pre&gt;This works fine, although I would humbly suggest that GHC's standard library should provide easy access to binary files; while the solution is pretty trivial, it is a wart.&lt;br /&gt;&lt;br /&gt;I next stubbed my toe on &lt;span style="font-weight:bold;"&gt;printf&lt;/span&gt;. Printf is available in module Text.Printf and provides a type-safe version of C's printf. As a long-time C and C++ programmer, you'd think I'd know just about everything there is to know about printf. So, I rapidly gave it a format string "%02X" and passed it a char. Apparently the uppercase X to produce a hex representation with uppercase A-F is not supported (grrr). Another minor wart -- if you provide printf, it should behave like printf -- but we'll move on.&lt;br /&gt;&lt;br /&gt;Per more chatting on #haskell I was given this one liner to dump binary data in a nicely formatted way:&lt;pre&gt;writeFile ofile (concat $ zipWith (printf "%02x %s") s (cycle $ replicate 19 "" ++ ["\n"]))&lt;/pre&gt;I want to take a moment to talk about how it works. First, cycle $ replicate 19 "" ++ ["\n"]. The &lt;span style="font-weight:bold;"&gt;replicate&lt;/span&gt; function gives us a list of 19 empty strings, which we then concatenate with a newline. Applying &lt;span style="font-weight:bold;"&gt;cycle&lt;/span&gt; to this list treats it as an infinitely repeating circular list of strings, where every twentieth is a newline. These arguments are then fed to printf using &lt;span style="font-weight:bold;"&gt;zipWith&lt;/span&gt;. zipWith is an interesting function: while &lt;span style="font-weight:bold;"&gt;zip&lt;/span&gt; takes two lists and generates a list of pairs produced by assembling the list elements into tuples, zipWith doesn't tupleize the elements; instead it feeds the elements to the provided function, and makes a list of the results.&lt;br /&gt;&lt;br /&gt;While this worked, it was interesting enough that I wanted to play with it using GHCi. But I had to give up on that; I kept tripping over the type checker. While I appreciate the masochistic joys of programming and the safety that comes with it, it can be frustrating for programmers with experience in, say, Ruby, or even C.&lt;br /&gt;&lt;br /&gt;For example: &lt;pre&gt;let xs = [1..100]&lt;br /&gt;let ys = take 100 (cycle $ replicate 19 "" ++ ["\n"])&lt;br /&gt;zipWith (printf "%02x %s") xs ys&lt;/pre&gt;GHC replies:&lt;pre&gt;Ambiguous type variable `c' in the constraint:&lt;br /&gt;`PrintfType c' arising from use of `printf' at &lt;interactive&gt;:1:9-24&lt;br /&gt;Probable fix: add a type signature that fixes these type variable(s)&lt;/interactive&gt;&lt;/pre&gt;Ugh. Using the ":t" command in GHC it is easy to see that GHC thinks the type of xs is [Integer] and ys is [[Char]] (a list of list of chars, also known as a list of strings). If I put roughly the same code in a Literate Haskell source file and ask GHC to load it, I get:&lt;pre&gt;  Ambiguous type variable `a' in the constraints:&lt;br /&gt;    `Enum a'&lt;br /&gt;      arising from the arithmetic sequence `1 .. 100'&lt;br /&gt;      at E:\toy.lhs:3:5-12&lt;br /&gt;    `Num a' arising from the literal `100' at E:\toy.lhs:3:9-11&lt;br /&gt;    `PrintfArg a' arising from use of `printf' at E:\toy.lhs:5:18-33&lt;br /&gt;  Possible cause: the monomorphism restriction applied to the following:&lt;br /&gt;    xs :: [a] (bound at E:\toy.lhs:3:0)&lt;br /&gt;  Probable fix: give these definition(s) an explicit type signature&lt;br /&gt;                or use -fno-monomorphism-restriction&lt;/pre&gt;followed immediately by:&lt;pre&gt;  Ambiguous type variable `c' in the constraint:&lt;br /&gt;    `PrintfType c' arising from use of `printf' at E:\toy.lhs:5:18-33&lt;br /&gt;  Possible cause: the monomorphism restriction applied to the following:&lt;br /&gt;    result :: [c] (bound at E:\toy.lhs:5:0)&lt;br /&gt;  Probable fix: give these definition(s) an explicit type signature&lt;br /&gt;                or use -fno-monomorphism-restriction&lt;br /&gt;Failed, modules loaded: none.&lt;/pre&gt;Wow. I'd say that is not really a newbie-friendly error message. However, this printf works fine in my real program. I'm not certain why, and I'm not going to dive into it too deeply right now. But here's a simpler type checking example: while C is strongly typed, you can treat numbers as chars and vice-versa, as long as you keep integral promotion and sign extension in mind. GHC is a harsher mistress. Let's say we want to pattern-match on our binary data. The value 16 in my binary data is DLE, which stands for Data Link Escape; it is often used in serial data to indicate packet boundaries, while inside the payload, it will be escaped (doubled). So here's a little pattern to remove doubled DLEs:&lt;pre&gt;de_dle (16:16:xs) = ...&lt;/pre&gt;Simple enough, right? No, to Haskell a number and a Char are not interchangeable. Back to #haskell, where I got a quick explanation of the type checker's error messages. I turned the numbers into chars:&lt;pre&gt;de_dle ('\16':'\16':xs) = ...&lt;/pre&gt;And that works just beautifully.&lt;br /&gt;&lt;br /&gt;Anyway, to make a long story shorter, I was able to write my file filter, which does some nice pattern matching and formatted out. The problems I had while developing that were the kind I like: problems choosing my algorithm properly, not problems fighting with the language. The runtime was quite helpful here; while processing the file, if I hit a case at runtime which my patterns did not handle, I got a runtime warning about non-exhaustive patterns. That led me to reorganize my patterns, and the result was much clearer.&lt;br /&gt;&lt;br /&gt;There was one more minor pitfall remaining. I compiled my program using GHC, but when I ran it, instead of my prompts for input and output filenames, I got nothing! Haskell was silently waiting for input. Back to #haskell. To make the output show up, I had to &lt;span style="font-weight:bold;"&gt;import System.IO&lt;/span&gt; and do &lt;span style="font-weight:bold;"&gt;hSetBuffering stdout NoBuffering&lt;/span&gt;. (Alternately, I could flush stdout immediately after each &lt;span style="font-weight:bold;"&gt;putStr&lt;/span&gt;, but that seems even uglier). I hope that saves someone a little aggravation.&lt;br /&gt;&lt;br /&gt;Speaking of aggravation, how did it all come out? Well, the original binary log file is about six megabytes. Since I was doing this by hand, I was more concerned that the program ran correctly than that it ran fast; I would have been satisfied with anything under a half-hour. In fact, without any attempts at optimization at all, my filter ran in under thirty seconds, which is more than fast enough for an ad hoc little tool. I started out trying to do this task using some regular expressions in vi, and that was quickly going nowhere, and taking forever to do it. The vi that came with Cygwin doesn't support some of the more advanced regular expressions features (there is no {x,y} syntax for specifying the number of repeats of a pattern). Notepad++, my workhorse Windows text editor, also doesn't support this syntax. Without this the regexes were becoming hideous, although in (say) Perl they would have been rather simple. But I was able to use Haskell instead, thanks to GHC and the kind folks on #haskell!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2586088976799473149?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2586088976799473149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2586088976799473149' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2586088976799473149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2586088976799473149'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/04/haskell-for-short-attention-span-simple.html' title='Haskell for the Short Attention Span: A Simple File Filter'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4017885577779568121</id><published>2007-03-07T17:02:00.000-05:00</published><updated>2007-03-08T11:52:12.513-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Haskell for the Short Attention Span: Run-Length Encoding, Part 3</title><content type='html'>This isn't a big improvement, but it occurs to me that my implementation from last time:&lt;pre&gt;&gt;deRLE :: [Integer] -&gt; Bool -&gt; Integer -&gt; [Integer]&lt;br /&gt;&gt;deRLE [] False _ = []&lt;br /&gt;&gt;deRLE points False max = deRLEHelper points max&lt;br /&gt;&gt;deRLE points True max = deRLEHelper (0 : points) max&lt;br /&gt;&lt;br /&gt;&gt;deRLEHelper :: [Integer] -&gt; Integer -&gt; [Integer]&lt;br /&gt;&gt;deRLEHelper [] max = []&lt;br /&gt;&gt;deRLEHelper [unmatched] max = [unmatched..max]&lt;br /&gt;&gt;deRLEHelper (start:end:rest) max = [start..end - 1]&lt;br /&gt;&gt;  ++ deRLEHelper rest max&lt;/pre&gt;can be yet shorter; since deRLEHelper handles the empty list specially, deRLE doesn't need to:&lt;pre&gt;&gt;deRLE :: [Integer] -&gt; Bool -&gt; Integer -&gt; [Integer]&lt;br /&gt;&gt;deRLE points False max = deRLEHelper points max&lt;br /&gt;&gt;deRLE points True max = deRLEHelper (0 : points) max&lt;/pre&gt;That way only the function that actually recurses down to the empty list has to explicitly handle it.&lt;br /&gt;&lt;br /&gt;Can we make it even more concise and still retain the self-documenting aspects of the code? I'll have to come back to that question. It's time to respond to comments. When I first mentioned my &lt;span style="font-weight: bold;"&gt;triplify&lt;/span&gt; function, which breaks a string into strings of three characters, I wrote "I'm sure there is a very clever one-line fold that applies &lt;span style="font-weight: bold;"&gt;take 3&lt;/span&gt; in an mind-expanding manner, but I was unable to find it." I got some great suggestions. The first, due to Cale Gibbard, was:&lt;pre&gt;map (take 3) . takeWhile (not . null) . iterate (drop 3)&lt;/pre&gt;Let's look at it piecewise as a pipeline, from right to left.&lt;br /&gt;&lt;br /&gt;First, our list/string (for example, "ABCDEFG") is fed to the function &lt;span style="font-weight: bold;"&gt;iterate&lt;/span&gt; along with &lt;span style="font-weight: bold;"&gt;(drop 3)&lt;/span&gt;. Iterate is an interesting function. I tried to understand it a few months ago by reading the description at zvon.org, which says that iterate; &lt;blockquote&gt;creates an infinite list where the first item is calculated by applying the function on the secod [sic] argument, the second item by applying the function on the previous result and so on.&lt;/blockquote&gt;They give the following example:&lt;blockquote&gt;Input: take 10 (iterate (2*) 1)&lt;br /&gt;&lt;br /&gt;Output: [1,2,4,8,16,32,64,128,256,512]&lt;/blockquote&gt;Note that if the behavior followed the description, the output would be [2,4,8,16,32,64,128,256,512,1024]. Their description is wrong, although the output matches GHCi's output. What does &lt;span style="font-weight:bold;"&gt;iterate&lt;/span&gt; really do? I'll describe it in the form of a poem.&lt;pre&gt;&lt;span style="font-weight:bold;"&gt;iterate&lt;/span&gt; takes a function and a value, and returns a list consisting of:&lt;br /&gt;&lt;br /&gt;  the value&lt;br /&gt;&lt;br /&gt;  followed by&lt;br /&gt;    the value of applying the function to the value&lt;br /&gt;&lt;br /&gt;  followed by&lt;br /&gt;    the value of applying the function to&lt;br /&gt;      the value of applying the function to the value&lt;br /&gt;&lt;br /&gt;  followed by&lt;br /&gt;    the value of applying the function to&lt;br /&gt;      the value of applying the function to&lt;br /&gt;        the value of applying the function to the value&lt;br /&gt;&lt;br /&gt;  it will keep talking&lt;br /&gt;    even when&lt;br /&gt;      it has nothing&lt;br /&gt;        new to say&lt;br /&gt;          so please don't&lt;br /&gt;            ask it any&lt;br /&gt;              open-ended&lt;br /&gt;                questions...&lt;/pre&gt;That is, I can't evaluate&lt;pre&gt;iterate (drop 3) "ABCDEFG"&lt;/pre&gt;because even though the input is finite, the output isn't; there's no termination to the recursion. However, I can evaluate part of the result:&lt;pre&gt;take 4 (iterate (drop 3) "ABCDEFG")&lt;br /&gt;&lt;br /&gt;["ABCDEFG","DEFG","G",""]&lt;/pre&gt;And because of Haskell's lazy evaluation, we can feed this infinite result "upstream" to be used in the remainder of our calculation, and it will work fine as long as it doesn't evaluate the complete result. The next stage in our "points-free" pipeline is:&lt;pre&gt;takeWhile (not . null)&lt;/pre&gt;The &lt;span style="font-weight:bold;"&gt;takeWhile&lt;/span&gt; function operates on a list, returning a list made up of its values as long as they match the predicate supplied. This has the effect of squashing the overly talkative &lt;span style="font-weight: bold;"&gt;iterate&lt;/span&gt;, because we stop evaluating its results as soon as it returns the first null value. Lazy evaluation is so cool!&lt;br /&gt;&lt;br /&gt;Now, our finite list of strings is handed off to &lt;span style="font-weight:bold;"&gt;map (take 3)&lt;/span&gt;, which generates a list of 3-character prefixes. Here's the whole process:&lt;pre&gt;iterate (drop 3) "ABCDEFG"&lt;/pre&gt;yields an infinite list beginning ["ABCDEFG","DEFG","G",""];&lt;pre&gt;takeWhile (not . null)&lt;/pre&gt; applied to the above will take elements from the list until it hits the first null: ["ABCDEFG","DEFG","G"]&lt;pre&gt;map (take 3)&lt;/pre&gt;applied to the above will give us ["ABC","DEF","G"]. Note that the short remainder is preserved.&lt;br /&gt;&lt;br /&gt;That seems so useful, I'm surprised it isn't a function in the Standard Prelude, called &lt;span style="font-weight: bold;"&gt;groupsOf&lt;/span&gt;. Although it would also be nice to have a version which didn't keep the short remainder, perhaps &lt;span style="font-weight: bold;"&gt;groupsOfOnly&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I got another suggestion from a user called "kirby." He suggested the function&lt;pre&gt;takeWhile (\="") . List.unfoldr (Just . splitAt 3)&lt;/pre&gt;Wow, my first unfoldr! I'm going to have to stop there for today, while I learn a little something about Just, Nothing, and the Maybe warm fuzzy thing. My first funster!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4017885577779568121?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4017885577779568121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4017885577779568121' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4017885577779568121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4017885577779568121'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/03/haskell-for-short-attention-span-run_07.html' title='Haskell for the Short Attention Span: Run-Length Encoding, Part 3'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6198719775232347984</id><published>2007-03-06T11:02:00.000-05:00</published><updated>2007-03-07T12:17:23.281-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>English Majors as Programmers</title><content type='html'>The Embedded Muse is an e-newsletter edited by Jack Ganssle; see the &lt;a href="http://ganssle.com"&gt;Ganssle Group home page&lt;/a&gt;. In Issue 142 he writes:&lt;blockquote&gt;I've found that some of the best developers of all are English majors. They'll often graduate with no programming experience at all, and certainly without a clue about the difference between DRAM and EPROM.&lt;br /&gt;&lt;br /&gt;But they can write. That's the art of conveying information concisely and clearly. Software development and writing are both the art of knowing what you're going to do, and then lucidly expressing your ideas.&lt;br /&gt;&lt;br /&gt;The worst developers, regardless of background, fail due to their inability to be clear. Their thoughts and code tend to ramble rather than zero-in on the goal...&lt;br /&gt;&lt;br /&gt;Too many engineering-trained developers have a total disregard for stylistic issues in programming. Anything goes. Firmware is the most expensive thing in the universe, so it makes sense to craft it carefully and in accordance with a standard style guide. Make sure it clearly communicates its intent. This is where the English majors shine; they've spent 4 years learning everything there is to know about styles and communication.&lt;/blockquote&gt;As an English major who has programmed computers since the age of ten, and who also took every programming course I could manage, it's nice to hear a little love for English majors! But I should add that an English degree is not a requirement; I also know some excellent developers who majored in more technical subjects, such as anthropology and archaeology!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6198719775232347984?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6198719775232347984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6198719775232347984' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6198719775232347984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6198719775232347984'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/03/english-majors-as-programmers.html' title='English Majors as Programmers'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-1901822813467965692</id><published>2007-03-05T20:13:00.000-05:00</published><updated>2007-03-08T11:51:56.713-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Haskell for the Short Attention Span: Run-Length Encoding, Part 2</title><content type='html'>Greetings! Last time I introduced a piece of code to solve a small real-world problem: decoding a set of function IDs from a run-length-encoded list of change points. I received some excellent feedback. One of the most valuable suggestions was that I avoid unnecessarily taking the length of the list in my "triplify" function. That makes a great deal of sense, considering that ideally I'd like to be able to handle infinite lists, and of course it would be nice if the runtime of my algorithm did not spiral out of control quite so quickly!&lt;br /&gt;&lt;br /&gt;I also gave a little more thought to the various base cases. One of the nicest things about Haskell is its pattern matching. Indeed, even a simple function like "square a = a * a" makes use of pattern matching, where "a" on the left-hand side is irrefutable. My implementation last time failed to fully take advantage of pattern matching on multiple parameters, particularly to handle base cases, and did not even handle all the various termination conditions properly. So, here is a slightly condensed version of the code that makes the termination conditions much more explicit, and so I claim even though it is shorter, it is more self-exlanatory.&lt;pre&gt;&gt;import Char&lt;br /&gt;&gt;import Numeric&lt;br /&gt;&gt;rle_raw_str = "00 30 90 09 31 01 10 32 20 22 12 30 23 12 41 24" ++&lt;br /&gt;&gt;  "34 40 44 1C 0F C1 1D 00 D0 1D 03 D0 4D 05 D0 7D 0A D0 CD 10" ++&lt;br /&gt;&gt;    "D1 2D 20 D2 6D 30 D3 1D 40 D4 1D 50 D5 1F 00"&lt;/pre&gt;A new triplify:&lt;pre&gt;&gt;triplify :: String -&gt; [String]&lt;br /&gt;&gt;triplify [] = []&lt;br /&gt;&gt;triplify (x:y:z:rest) = [x, y, z] : triplify rest&lt;br /&gt;&gt;triplify str = error "Unexpected string length (trying to match 3 characters)"&lt;/pre&gt;Treating the input data as a list of 12-bit numbers:&lt;pre&gt;&gt;rle_change_points = map (fst . head . readHex)&lt;br /&gt;&gt;  (triplify (filter isHexDigit rle_raw_str))&lt;/pre&gt;The main function: given a list of change points, a hint as to whether we are initially presuming the decoder will output ones or zeroes, and a maximum value, decode RLE data from the change points. Return the indices of the one bits.&lt;pre&gt;&gt;deRLE :: [Integer] -&gt; Bool -&gt; Integer -&gt; [Integer]&lt;br /&gt;&gt;deRLE [] False _ = []&lt;br /&gt;&gt;deRLE points False max = deRLEHelper points max&lt;br /&gt;&gt;deRLE points True max = deRLEHelper (0 : points) max&lt;br /&gt;&lt;br /&gt;&gt;deRLEHelper :: [Integer] -&gt; Integer -&gt; [Integer]&lt;br /&gt;&gt;deRLEHelper [] max = []&lt;br /&gt;&gt;deRLEHelper [unmatched] max = [unmatched..max]&lt;br /&gt;&gt;deRLEHelper (start:end:rest) max = [start..end - 1] &lt;br /&gt;&gt;  ++ deRLEHelper rest max&lt;/pre&gt;This is more like it -- the kind of program that resembles a proof more than code. I'm starting to prefer this style!&lt;br /&gt;&lt;br /&gt;A brief explanation: if we're initially decoding zeroes, the empty list case can be disposed of quickly. The program filters this case out first so that the recursive helper function, which accumulates the output, doesn't need to handle this case. The next two lines handle non-empty lists. If we're initially decoding ones, we can still treat all cases the same if we just prepend a zero to "flip" the decoder. Our helper function then has only three cases: a termination case where an interval of ones is not closed (because we have a single change point left), in which case we spit out ones up to and including our maximum possible value; a termination case where we have two change points forming a closed interval, in which case we spit out an interval inclusive of the start and exclusive of the end, and a non-termination case in which we have more than two entries, which spits out a closed interval and continues the process.&lt;br /&gt;&lt;br /&gt;Let's look at some test cases. First, we confirm that if we're generating zeroes and we encounter no change points, our result set is empty:&lt;br /&gt;&lt;br /&gt;deRLE [] False 0xF&lt;br /&gt;&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;We confirm that if we hit a single change point, the result set will contain all the values up to and including the maximum possible:&lt;br /&gt;&lt;br /&gt;deRLE [0] False 0xF&lt;br /&gt;&lt;br /&gt;[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]&lt;br /&gt;&lt;br /&gt;deRLE [11] False 0xF&lt;br /&gt;&lt;br /&gt;[11,12,13,14,15]&lt;br /&gt;&lt;br /&gt;In the general case where our interval is closed, our result set is inclusive on the left and exclusive on the right:&lt;br /&gt;&lt;br /&gt;deRLE [5, 10] False 0xF&lt;br /&gt;&lt;br /&gt;[5, 6, 7, 8, 9]&lt;br /&gt;&lt;br /&gt;Closing one range and opening another without closing it works correctly:&lt;br /&gt;&lt;br /&gt;deRLE [5, 10, 11] False 0xF&lt;br /&gt;&lt;br /&gt;[5,6,7,8,9,11,12,13,14,15]&lt;br /&gt;&lt;br /&gt;If we begin assuming our decoder generates zeroes, an empty list of change points maps to all possible values:&lt;br /&gt;&lt;br /&gt;deRLE [] True 0xF&lt;br /&gt;&lt;br /&gt;[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]&lt;br /&gt;&lt;br /&gt;A single change point at zero toggles the state of the decoder and produces and empty result:&lt;br /&gt;&lt;br /&gt;deRLE [0] True 0xF&lt;br /&gt;&lt;br /&gt;[]&lt;br /&gt;&lt;br /&gt;A single change point greater than zero allows some values into our result set before it is closed:&lt;br /&gt;&lt;br /&gt;deRLE [5] True 0xF&lt;br /&gt;&lt;br /&gt;[0,1,2,3,4]&lt;br /&gt;&lt;br /&gt;Two change points defines a range to exclude from the results, and we get the rest of the values in the range:&lt;br /&gt;&lt;br /&gt;deRLE [5, 10] True 0xF&lt;br /&gt;&lt;br /&gt;[0,1,2,3,4,10,11,12,13,14,15]&lt;br /&gt;&lt;br /&gt;Three change points suppresses the rest of the result set:&lt;br /&gt;&lt;br /&gt;deRLE [5, 10, 13]&lt;br /&gt;&lt;br /&gt;[0,1,2,3,4,10,11,12]&lt;br /&gt;&lt;br /&gt;With these tests I'm satisified that deRLE works for all expected cases.&lt;br /&gt;&lt;br /&gt;I received more comments, including some recommendations for a nifty unfold. Thanks to everyone who made suggestions. Next time I'll take a look at how those work, talk about anything else that comes to mind, and then proceed to my next real-world problem!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-1901822813467965692?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/1901822813467965692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=1901822813467965692' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1901822813467965692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1901822813467965692'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/03/haskell-for-short-attention-span-run_05.html' title='Haskell for the Short Attention Span: Run-Length Encoding, Part 2'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-2374378518941627699</id><published>2007-03-01T22:47:00.000-05:00</published><updated>2007-03-05T13:16:57.979-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Haskell for the Short Attention Span: Run Length Encoding, Part 1</title><content type='html'>I'm a fortunate man. Some 50% of people who suffer herpes zoster infections involving the eye wind up with permanent eye damage. I seem to have escaped with little or no permanent damage. The nerves are not completely healed, and there is still visible damage under the skin, but it is no longer painful to work at the computer or read!&lt;br /&gt;&lt;br /&gt;It's time to jump back on the horse and risk looking foolish in public by writing some code. I still consider myself to be close to a rank beginner in Haskell, so you're reading my "finger exercises." To experienced functional programmers they will probably sound like a new violin student sawing away. However, since I haven't been a student for almost twenty years and there is no one to assign me homework but myself, this seems to be the next best way to force myself to learn something!&lt;br /&gt;&lt;br /&gt;With three children at home, two of them babies, I don't get a lot of unbroken free time; I've got a guaranteed short attention span. So consequently I'm going to look at some very small programs. However, rather than make up toy programs from scratch, I am now going to turn to a few real-world problems that I've stumbled across while doing embedded programming.&lt;br /&gt;&lt;br /&gt;OK. Consider a spherical cow of uniform density... wait, I mean, consider a black-box system with an outward-facing interface in which a number of functions are made available. Functions are accessed via a 12-bit unique ID. A client of that system doesn't know which functions are available. The client needs a method to retrieve a list of funciton IDs. Let's assume we don't have bandwidth to burn, so we don't want to send a complete list of all the function IDs. Let's further assume that the functions are organized into a small number of groups with consecutive IDs. In other words, this is data that is very amenable to a simple compression scheme.&lt;br /&gt;&lt;br /&gt;We're going to do it using Run-Length Encoding (RLE). Here is a brief informal explanation of RLE; if you are already know all about RLE, skip the next paragraph (but read the ones after that, please!)&lt;br /&gt;&lt;br /&gt;RLE is a commonly used technique for encoding bitmaps; a variant of RLE is even used in fax machines. Rather than store a bit for every bit in a bitmap, RLE records _runs_ of repeating data. If you have a raster image that you're scanning left to right, top to bottom, and that image has a lot of horizontal lines in it, or black and white rectangles, this might be a big win. The RLE encoding will record long alternating runs of ones and zeroes. If the image has a lot of vertical lines, this might not be much of a win. The worst-case scenario is a 50% checkerboard: in that case, we'll have to indicate runs of length 1, and the overhead will be far worse than just encoding the bits. For that kind of image you'd be better off using a means of compression that actually adapts to the frequency of occurrence of particular patterns in the data, such as Huffman coding or LZW.&lt;br /&gt;&lt;br /&gt;Now, there are several possible ways to represent the runs of RLE data. One scheme might use tuples consisting of the bit value and the number of occurrences of that value (the "run length"). For example, the tuples [(0, 14), (1, 28), (0, 3)] could represent a run of fifteen zeroes, followed by a run of twenty-nine ones, followed by four zeroes. Why are the values off by one? Because we would never need to encode a run of length zero, so we allow zero to represent one, and so on. A tuple like this could be encoded in a single byte, where the high-order bit represents the value and the remaining seven bits represented the run length - 1. This gives us the ability to represent runs of up to 128 bits. Of course, if we have a run of length 129 or greater, we'll need to represent it with multiple bytes. For degenerate cases where we encode very long runs, we'll have unnecessary redundancy.&lt;br /&gt;&lt;br /&gt;For that low-entropy bitmap, a better scheme might be to just record the points at which the data _changes_. We have to choose an initial state for decoding: should the decoder, prior to the first change point, produce ones, or zeroes? Once we know that, we don't need to encode the bit values at all. If we assume that our encoded data begins with a run of zeroes, we could represent the example above (fifteen zeroes, followed by twenty-nine ones, followed by four zeroes) by recording only [15, 44]. Let's say that we want our decoder to spit out the indices of the one bits. We'll get:&lt;pre&gt;[15,16,17,18,19,20,21,22,23,24,&lt;br /&gt;25,26,27,28,29,30,31,32,33,34,&lt;br /&gt;35,36,37,38,39,40,41,42,43]&lt;/pre&gt;Using this scheme, a bitmap of all zeroes would be represented by an empty list, while a bitmap of all ones would be represented by by a single [0]; it turns on the "ones" state and never turns it off, so we just generate ones until our range of values is exhausted. (This implies that, in addition to knowing what starting state it should assume, the decoder has to know the size of the bitmap we are representing). A bitmap consisting of all zeroes followed by a single one would be represented by [N - 1] where N is the number of bits in the bitmap.&lt;br /&gt;&lt;br /&gt;If, instead of assuming that our data starts with an implicit run of zeroes, we assume instead that it starts with an implicit run of ones, it should be obvious that we could encode the same example using [0, 15, 44]; in this case, a bitmap of all zeroes would be represented by [0], which would yield an empty list of one-bit indices, while a bitmap of all ones would be represented by an empty list, yielding a list [0..n - 1] of bit indices.&lt;br /&gt;&lt;br /&gt;We'll assume that our function IDs are represented this way: they are the one bits in the bitmap, and we want a list of their indices.  When we query our interface about its function IDs, we get back a response that consists of a short list of change points. Here are the data bytes:&lt;pre&gt;00 30 90 09 31 01 10 32 20 22 12 30 23 12 41 24 34 &lt;br /&gt;40 44 1C 0F C1 1D 00 D0 1D 03 D0 4D 05 D0 7D 0A D0 &lt;br /&gt;CD 10 D1 2D 20 D2 6D 30 D3 1D 40 D4 1D 50 D5 1F 00&lt;/pre&gt;The first time I encountered data like this, I wrote myself a little bit of Ruby code to decode it. Here's first part of the Ruby code, which turns these bytes into a series of 12-bit unsigned numbers by assembling three nybbles (half-bytes) at a time:&lt;pre&gt;rle_raw_list = gets.chomp.delete(" ")&lt;br /&gt;&lt;br /&gt;rle_change_func_ids = []&lt;br /&gt;0.step(rle_raw_list.length - 2, 3) { |nybble_idx|&lt;br /&gt;  rle_change_func_ids.push(rle_raw_list[nybble_idx..nybble_idx + 2].hex)&lt;br /&gt;}&lt;/pre&gt;Here's how it works. The first line reads data from standard input and, reading left to right, removes any end-of-line character and deletes spaces. We next create an empty list. "0.step" is cute little bit of idiomatic Ruby shorthand: everything is an object, including integers, and they have a "step" method, so by calling 0.step we loop from zero to the string length  - 2, incrementing by threes. We also provide a Ruby block, which is basically a closure that receives one parameter, the loop index, and which is bound to the name nybble_idx. Working inside-out, the body of this closure takes three-byte substrings of the raw data, passes them to the hex function to yield an integer, and then uses push, which treats the list like a stack and appends the new integer to the end. The result looks like this:&lt;pre&gt;[0x003, 0x090, 0x093, 0x101, 0x103 ...]&lt;/pre&gt;This is the list of change points. Once I have that, I can generate the runs of data. I'll assume that our data starts with an initial run of ones:&lt;pre&gt;rle_state = true&lt;br /&gt;MAX_FUNC_ID = 0xFFF&lt;br /&gt;current_func_id = 0&lt;br /&gt;&lt;br /&gt;for change_func_id in rle_change_func_ids&lt;br /&gt;  if rle_state == true&lt;br /&gt;    (current_func_id...change_func_id).each {|valid_func_id|&lt;br /&gt;      puts sprintf('0x%02X', valid_func_id)&lt;br /&gt;    }&lt;br /&gt;    rle_state = false&lt;br /&gt;  elsif rle_state == false&lt;br /&gt;    rle_state = true&lt;br /&gt;  end&lt;br /&gt;  current_func_id = change_func_id&lt;br /&gt;end&lt;/pre&gt;Now, I should mention that I like Ruby, and especially like its support for nice idioms like blocks and closures and iterators and chaining functions. But while this Ruby code worked well enough for my little task, you might notice that it doesn't actually handle all the termination cases properly. As I work with Haskell, I'm finding that I like it quite a bit more than Ruby. One of the reasons is that Haskell code, being less imperative, seems closer to a kind of abstract, platonic representation of the problem space. Problems such as the failure to properly handle various termination cases tend to look much more obvious, particularly when functions are broken down into pieces using pattern matching.&lt;br /&gt;&lt;br /&gt;Anyway, here's my Haskell version:&lt;pre&gt;&gt;import Char&lt;br /&gt;&gt;import Numeric&lt;br /&gt;&lt;br /&gt;&gt;rle_raw_str = "00 30 90 09 31 01 10 32 20 22 12 30 23 12 41 24" ++&lt;br /&gt;&gt;  "34 40 44 1C 0F C1 1D 00 D0 1D 03 D0 4D 05 D0 7D 0A D0 CD 10" ++&lt;br /&gt;&gt;  "D1 2D 20 D2 6D 30 D3 1D 40 D4 1D 50 D5 1F 00"&lt;/pre&gt;(My first opportunity to look silly: I'm sure there's a way to break a string across multiple lines with some sort of continuation character, but I could not get "\" to work together with Literate Haskell mode, so I'll just concatenate them and hope no one notices...)&lt;pre&gt;&gt;rle_bytes_str = filter isHexDigit rle_raw_str&lt;/pre&gt;That was easy!&lt;br /&gt;&lt;br /&gt;Now, my second opportunity to look silly: I'm sure there is a very clever one-line fold that applies "take 3" in an mind-expanding manner, but I was unable to find it. This was about as clever as I could manage, but it does have the advantage of checking for unexpected data length:&lt;pre&gt;&gt;triplify :: String -&gt; [String]&lt;br /&gt;&gt;triplify str | length str == 0 = []&lt;br /&gt;&gt;triplify str | length str `mod` 3 == 0 = ( take 3 str ) : triplify ( drop 3 str )&lt;br /&gt;&gt;triplify str = error "bad length (expected multiple of three)"&lt;/pre&gt;To see the results, evaluate "triplify rle_bytes_str." I get:&lt;pre&gt;["003","090","093","101","103","220","221","230","231","241",&lt;br /&gt;"243","440","441","C0F","C11","D00","D01","D03","D04","D05",&lt;br /&gt;"D07","D0A","D0C","D10","D12","D20","D26","D30","D31","D40",&lt;br /&gt;"D41","D50","D51","F00"]&lt;/pre&gt;Now I want to turn these into a list of numbers; these are the change points. Mumble, mumble...&lt;pre&gt;&gt;rle_change_points = map (fst . head . readHex) (triplify rle_bytes_str)&lt;br /&gt;&lt;br /&gt;[3,144,147,257,259,544,545,560,561,577,579,1088,1089,3087,3089,3328,3329,3331,3332,&lt;br /&gt;3333,3335,3338,3340,3344,3346,3360,3366,3376,3377,3392,3393,3408,3409,3840]&lt;/pre&gt;Our playing field is the range of integers 0x000..0xFFF or 0..4095 in decimal. We want to lazily generate a list of valid values using our RLE decoding scheme. Rather than walk the list of change points spitting out values using some kind of toggling state variable to keep track of whether the decoder is processing a run of ones or a run of zeroes, or walking all the possible values filtering it by the list of change points, we'll use two functions, one for extracting ranges, and one for generating values from ranges. Both functions receive a list representing "the rest of the work to do" in the form of the remainder of the list of change points, and so this is a _little_ bit like using continuation-passing style, or using a Monad to maintain the progress of the calculation. Maybe in Part 2 I'll have learned enough to explain what I mean by that!&lt;br /&gt;&lt;br /&gt;Our first function, getRangeFromChangePoints, has to handle some interesting cases. Assuming we are decoding RLE in the range of possible values [X..Y], what happens when our list contains a final value, N, that opens a final range but doesn't explicitly close it? Well, there are two approaches we could take. The more conservative approach is to assume that this was a harmless mistake and close the range [N..N + 1) so that it contains only the value N. (Note that I'm using interval notation in which a square bracket indicates that the range _includes_ the bound specified, and a parenthesis _excludes_ the bound specified). However, there is a problem with this approach: it means we can't generate a range that includes the maximum value, Y! That's no good, so we'll assume that a final range opening with N means that we really want [N..Y] (inclusive). In fact, since we treat ranges as exclusive at the end, this is actually the only way we can generate a range containing Y.&lt;br /&gt;&lt;br /&gt;For now, we also assume that running out of values is an error. We're assuming that our caller will handle the termination conditions.&lt;pre&gt;&gt;getRangeFromChangePoints :: [Integer] -&gt; (Integer, Integer, [Integer])&lt;br /&gt;&gt;getRangeFromChangePoints ([]) = error "getRangeFromRLE: no change points in list!"&lt;br /&gt;&gt;getRangeFromChangePoints (a:[]) = (a, max, []) where max = 0xFFF&lt;br /&gt;&gt;getRangeFromChangePoints (a:b:[]) = (a, b - 1, [])&lt;br /&gt;&gt;getRangeFromChangePoints (a:b:ls) = (a, b - 1, ls)&lt;/pre&gt;Wow, that's pretty wordy as Haskell code goes, but I kind of like the way the pattern-matching breaks down. Note that in particular it makes the termination conditions obvious. This helps me think about the problem domain, rather than the implementation, in a way that the imperative Ruby code did not.&lt;br /&gt;&lt;br /&gt;Next, here is the recursive function to generate values from ranges. We represent a range using the first two values of our tuple, while the third value is a list of the remaining ranges (sort of like our continuation). We handle the termination case, in which we have no more work to do, by just returning a list from our range, while the non-terminating case gets the next range (including the list representing our remaining work) and calls the function again to continue generating the list.&lt;pre&gt;&gt;genValuesFromRange :: (Integer, Integer, [Integer]) -&gt; [Integer]&lt;br /&gt;&gt;genValuesFromRange (first, last, []) = [first..last]&lt;br /&gt;&gt;genValuesFromRange (first, last, to_do) = [first..last] ++ &lt;br /&gt;&gt;  (genValuesFromRange (getRangeFromChangePoints to_do))&lt;/pre&gt;To generate the initial case we use a helper function called valuesFromRLE. In ddition to the change points list, it takes a Boolean value which indicates whether we are to assume that our RLE decoding is initially inclusive or initially exclusive: that is, whether the first value in our first range indicates that the range is starting or ending. If we want it to behave inclusively, we prepend a zero value to create a range starting with zero. Note that this will be harmless if our first range starts with zero, because we'll generate a range like [0..(-1)], which will contain no members.&lt;pre&gt;&gt;valuesFromRLE :: [Integer] -&gt; Bool -&gt; [Integer]&lt;br /&gt;&gt;valuesFromRLE change_points initially_inclusive = genValuesFromRange $ &lt;br /&gt;&gt;    if initially_inclusive then getRangeFromChangePoints (0 : change_points)&lt;br /&gt;&gt;        else getRangeFromChangePoints change_points&lt;/pre&gt;Note that we can evaluate the whole thing, but more interestingly, we can use "take" to produce only the first few elements:&lt;pre&gt;take 16 $ valuesFromRLE rle_change_points True&lt;br /&gt;&lt;br /&gt;[0,1,2,144,145,146,257,258,544,560,577,578,1088,3087,3088,3328]&lt;/pre&gt;And there you have it. If you like, play with the code. Next time we'll see if we can encode the function IDs back into change points, and confirm the round trip. As always, I appreciate your comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2374378518941627699?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2374378518941627699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2374378518941627699' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2374378518941627699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2374378518941627699'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/03/haskell-for-short-attention-span-run.html' title='Haskell for the Short Attention Span: Run Length Encoding, Part 1'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-9219583009447014715</id><published>2007-02-15T12:02:00.000-05:00</published><updated>2007-02-16T14:45:55.600-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Richard or Edna? (And Graham Hutton's Programming in Haskell)</title><content type='html'>For some reason, Richard Bird's Introduction to Functional Programming Using Haskell, 2nd Edition, is now listed on Amazon as written by "Edna Bird" (and coauthored by "Wadler" with no first name). Assuming Richard is not actually undergoing a transformation along the lines of Walter Carlos to Wendy, this looks like an error...&lt;br /&gt;&lt;br /&gt;Anyway, my copy of Graham Hutton's &lt;span style="font-style:italic;"&gt;Programming in Haskell&lt;/span&gt; arrived from Amazon. The first remarkable thing about this book is that it is the thinnest book on Haskell I've yet seen. The highest page number is 170. It is even thinner than &lt;span style="font-style:italic;"&gt;The C Programming Language, Second Edition&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;What does this mean? Well, for one thing, it means the chapters are very brief. It is a beginner's text aimed at novices, even those who may have not programmed (in any language). I would &lt;span style="font-style:italic;"&gt;definitely &lt;/span&gt;consider using it as a textbook for an introductory programming class. (I have a dream about teaching a programming class to gifted high school students or college first-year students before they have had their minds corrupted by too much Java or C++; we'd learn a little Haskell, Scheme, and Dylan, in that order, and then use our perspective gained to take a brief look at Java, Pascal, and BASIC. In that order, implementing a parser for Pascal and a complete implementation of BASIC. We'd start with this book. But anyway).&lt;br /&gt;&lt;br /&gt;The explanation of curried functions (or how "all functions with multiple arguments are curried") is the clearest I've seen. So is the explanation of basic types and classes. His chapter on recursion is also a model of clarity. (I'm pleased to see it goes above and beyond Fibonacci numbers). In general, Hutton seems to be encouraging his readers to think like programmers think, but he doesn't require very many words to get his ideas across.&lt;br /&gt;&lt;br /&gt;If you are busy like I am, you don't have time to read a long review, either, so I'll just conclude by saying that this looks like &lt;span style="font-style:italic;"&gt;the&lt;/span&gt; introductory Haskell text!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-9219583009447014715?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/9219583009447014715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=9219583009447014715' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/9219583009447014715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/9219583009447014715'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/02/richard-or-edna-and-graham-huttons.html' title='Richard or Edna? (And Graham Hutton&apos;s Programming in Haskell)'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7331428198275631126</id><published>2007-02-08T17:13:00.000-05:00</published><updated>2007-02-08T17:25:17.299-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Graham Hutton's Book has Shipped</title><content type='html'>Amazon tells me that my copy of Graham Hutton's &lt;span style="font-style:italic;"&gt;Programming in Haskell&lt;/span&gt; has shipped. Excellent!&lt;br /&gt;&lt;br /&gt;With the passage of time and the assistance of an acupuncturist, the nerve damage and eye sensitivity left in the wake of my shingles infection has healed, to the point where reading is no longer quite so painful. And I don't have to wear my sunglasses to work on the computer anymore!&lt;br /&gt;&lt;br /&gt;So, soon, hopefully back to actually writing some Haskell, as opposed to just reading about it. I have a couple of small real-world programs to try porting from Ruby, which should be educational. More soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7331428198275631126?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7331428198275631126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7331428198275631126' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7331428198275631126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7331428198275631126'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/02/graham-huttons-book-has-shipped.html' title='Graham Hutton&apos;s Book has Shipped'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-2968824836180638395</id><published>2007-01-17T11:42:00.000-05:00</published><updated>2007-02-08T18:15:55.877-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Haskell Books Piling Up, and Herpes Zoster Ophthalmicus at One Month</title><content type='html'>I've received a couple of Haskell-related books -- my Christmas presents to myself. I have only been able to skim these books, but here are my first impressions.&lt;br /&gt;&lt;br /&gt;The first book is Chris Okasaki's &lt;span style="font-style:italic;"&gt;Purely Functional Data Structures&lt;/span&gt;. When I was working on some code to solve Sudoku puzzles in Scheme, I became stymied because in the midst of my efforts to program in a function style, I kept slipping back into an imperative style. This book is the answer to the question "how do you manage data structures when you don't have mutable variables?" The answer, of course, is that you return new data structures based on the old ones. This is not necessarily as inefficient as you might expect, because the new data structure can frequently share content -- sometimes most of the content -- with the previous data structure. Okasaki's book is a model of clarity; on the back it indicates that it can be used for self-study. A lot of texts claim that, but this book seems to actually deliver it. The diagrams are marvelously clear and the learning curve is gentle. The body of the text uses Standard ML with extensions but there is an appendix containing Haskell code. I will have more to say about this book in future postings; I am really looking forward to trying out some of the ideas it contains.&lt;br /&gt;&lt;br /&gt;The second book is &lt;span style="font-style:italic;"&gt;The Haskell Road to Logic, Maths, and Programming&lt;/span&gt; by Kees Doets and Jan van Eijck. This is part of the King's College Texts in Computing series which includes &lt;span style="font-style:italic;"&gt;An Introduction to Lambda Calculi for Computer Scientists&lt;/span&gt;. That book is thin, while this one is fairly fat; this volume is bursting with exposition (and code) on logic, set theory, and other topics dear to my heart. It looks quite fascinating and again I hope to have more to say about it soon.&lt;br /&gt;&lt;br /&gt;It has been approximately a month since I was hit with the first symptoms of herpes zoster ophthalmicus (shingles infection involving the eye). The news is generally very good: there is little long-term damage to my cornea. My opthalmologist can see some slight scarring, but it should continue to improve. But the pain and hyper-sensitivity to light has persisted, and I have found it difficult to return to work because my eye tends to start watering madly or lose focus when I work at the computer for longer than a few minutes. The problem is in the branches of the trigeminal nerve, not the eyeball itself. Nerves heal slowly, so this is unfortunately not an illness for the impatient!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-2968824836180638395?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/2968824836180638395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=2968824836180638395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2968824836180638395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/2968824836180638395'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/01/haskell-books-piling-up-and-herpes.html' title='Haskell Books Piling Up, and Herpes Zoster Ophthalmicus at One Month'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-3386770064354422194</id><published>2007-01-02T10:48:00.000-05:00</published><updated>2007-01-02T12:06:50.629-05:00</updated><title type='text'>Shingles</title><content type='html'>Well, I had great plans for my ten days off -- work on the apartment, organize the office, deep-clean the kitchen, read, and study Haskell!&lt;br /&gt;&lt;br /&gt;So much for best-laid plans. Just before Christmas I came down with a shingles infection, which started in my right eye.&lt;br /&gt;&lt;br /&gt;Shingles is a reactivation of the herpes zoster or "varicella" virus, the same virus that causes chicken pox. I did a near all-nighter the Monday a week before Christmas, which might not have been too bad, but then the following night we had a sick baby and I was also unable to sleep. That was apparently enough stress to cause the virus to reactivate.&lt;br /&gt;&lt;br /&gt;Shingles is painful. I have become intimately familiar with two new types of pain, which I call the blowtorch and the nightstick. The blowtorch is a feeling like my skin is being burned by an open flame and is bubbling. That is the sensation of the blisters forming, although it comes at other random times too. The nightstick is deep pain along the nerves of my face, where they feel like I've been beaten. That produces a tremendous amount of muscle tension in my jaw, and around the base of my skull as well, where large areas are still hyper-sensitive to touch.&lt;br /&gt;&lt;br /&gt;Valtrex (an anti-retroviral drug) also has nasty side effects. I got waves of fever and chills, often back-to-back. It also caused nausea, diziness, and strange visions. I'm off the Valtrex now, so thankfully those side effects have gone away.&lt;br /&gt;&lt;br /&gt;For most of my ten days off work I was fairly incapacitated: unable to see, unable to read, lying in bed with fever or chills and with strange pains, covered with blisters and scabs. When I got out of bed, I was dizzy, stumbling around the house looking like a crazed sunburned pirate with an eye-patch on. &lt;br /&gt;&lt;br /&gt;Anyway, I am now back at work. The scabs are gone, although my face is still visibly splotchy. My right eye is still swollen and there is still some pain. I am still using an antibiotic gel in my eye, which means my right eye is still hazy, so I am not driving yet. I see my regular doctor today and the ophthalmologist again tomorrow. I think the likely outcome is that my vision will not be significantly damaged. It seems like the pain will persist at reduced level for at least a while longer.&lt;br /&gt;&lt;br /&gt;Dear reader, I sincerely hope you had a better holiday than mine. And if not, God bless you!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-3386770064354422194?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/3386770064354422194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=3386770064354422194' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3386770064354422194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/3386770064354422194'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2007/01/shingles.html' title='Shingles'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6879496760947038214</id><published>2006-12-22T10:20:00.000-05:00</published><updated>2006-12-22T14:27:47.655-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Happy Life Day and Wishing You Lots of Haskell in 2007</title><content type='html'>Let's remember the words of Princess Leia, in the Star Wars Holiday Special:&lt;blockquote&gt;We celebrate a day of peace. A day of harmony. A day of joy we can all share together joyously. A day that takes us through the darkness. A day that leads us into might. A day that makes us want to celebrate the light. A day that brings the promise that one day, we'll be free to live, to laugh, to dream, to grow, to trust, to love, to be.&lt;br /&gt;&lt;/blockquote&gt;Happy Life Day, everyone! Or whatever tradition you celebrate.&lt;br /&gt;&lt;br /&gt;I am not planning to work on any more entries until early January, so I just wanted say that I am extremely grateful for all the comments and suggestions I've received on my blog entries. With two babies at home I don't get much time to study textbooks or tutorials, although I try, and I don't get much dedicated coding time. But the suggestions and concrete examples have helped me make good use of what free time I do have. Thanks to all of you for your support learning this exciting language!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6879496760947038214?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6879496760947038214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6879496760947038214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6879496760947038214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6879496760947038214'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/happy-life-day-and-wishing-you-lots-of.html' title='Happy Life Day and Wishing You Lots of Haskell in 2007'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-8447012067148157459</id><published>2006-12-19T03:22:00.000-05:00</published><updated>2006-12-19T15:50:14.523-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>From Bits to Cells: Simple Cellular Automata in Haskell, Part Two</title><content type='html'>Let's get back to our CA generator. Literate Haskell follows:&lt;pre&gt;Last time we defined a function to generate the next state of a given cell &lt;br /&gt;in our cellular universe, given a rule number and a tuple consisting of &lt;br /&gt;the current state of the cell to the left, the cell itself, and the cell &lt;br /&gt;to the right.&lt;br /&gt;&lt;br /&gt;&gt;import Data.Bits&lt;br /&gt;&lt;br /&gt;&gt;genNextBit :: Int -&gt; ( Bool, Bool, Bool ) -&gt; Bool&lt;br /&gt;&gt;genNextBit rulenum ( left, center, right ) = rulenum `testBit` idx&lt;br /&gt;&gt;    where idx = ( if left then (4::Int) else (0::Int) ) .|. &lt;br /&gt;&gt;           ( if center then (2::Int) else (0::Int) ) .|. &lt;br /&gt;&gt;           ( if right then (1::Int) else (0::Int) )&lt;br /&gt;&lt;br /&gt;Recall that we can use automatic currying to make a rule-applying function &lt;br /&gt;like so:&lt;br /&gt;&lt;br /&gt;&gt;rule_30 = genNextBit 30&lt;br /&gt;&lt;br /&gt;We can ask GHCi for the type:&lt;br /&gt;&lt;br /&gt;:type rule_30&lt;br /&gt;&lt;br /&gt;rule_30 :: (Bool, Bool, Bool) -&gt; Bool&lt;br /&gt;&lt;br /&gt;I've put it off while I work on the rules, but it is time to figure out&lt;br /&gt;how to actually represent our CA universe. Let's start by using a list.&lt;br /&gt;I know that I'm going to write a number of inefficient functions, and&lt;br /&gt;do evil things like take the length of lists a lot, but let's suspend all &lt;br /&gt;concerns about efficiency over to a future discussion and consider this &lt;br /&gt;purely a proof-of-concept.&lt;br /&gt;&lt;br /&gt;Our inital universe at time zero has one cell set to True:&lt;br /&gt;&lt;br /&gt;&gt;initial_universe = [True]&lt;br /&gt;&lt;br /&gt;But that isn't quite the right representation for the universe, because &lt;br /&gt;it implies that our whole universe is one cell in size. We can't even &lt;br /&gt;apply our rule once because there is no left cell and right cell! &lt;br /&gt;Really, we want to pretend that we have an _infinite_ universe; at &lt;br /&gt;time zero, all the cells to the left and right hold False. Remember, &lt;br /&gt;Haskell is so powerful that it can traverse an infinite list in only &lt;br /&gt;0.0003 seconds! Well, if you don't evaluate the whole thing, that is.&lt;br /&gt;Taking advantage of lazy evaluation, you can define all kinds of &lt;br /&gt;infinite structures. This construct will give us an infinite list of &lt;br /&gt;False values:&lt;br /&gt;&lt;br /&gt;&gt;allFalse :: [Bool]&lt;br /&gt;&gt;allFalse = False : allFalse&lt;br /&gt;&lt;br /&gt;We don't want to evaluate allFalse, but we can partially evaluate it &lt;br /&gt;using a function like take. So can we represent our universe like this?&lt;br /&gt;&lt;br /&gt;&gt;genInfiniteUniverse :: [Bool] -&gt; [Bool]&lt;br /&gt;&gt;genInfiniteUniverse known_universe = allFalse ++ known_universe ++ allFalse&lt;br /&gt;&lt;br /&gt;Let's try it:&lt;br /&gt;&lt;br /&gt;take 10 ( genInfiniteUniverse initial_universe )&lt;br /&gt;&lt;br /&gt;[False,False,False,False,False,False,False,False,False,False]&lt;br /&gt;&lt;br /&gt;Nope! Since the left-hand side of the universe is infinite, we will never&lt;br /&gt;reach the middle element, no matter how far we travel from the start of the list! &lt;br /&gt;That's no good. However, we can do it another way. We'll allow our universe to&lt;br /&gt;be expanded on demand on the left and right sides:&lt;br /&gt;&lt;br /&gt;&gt;expandUniverse :: Int -&gt; [Bool] -&gt; [Bool]&lt;br /&gt;&gt;expandUniverse expand_by known_universe = &lt;br /&gt;&gt;   ( take expand_by allFalse ) ++ known_universe ++ ( take expand_by allFalse )&lt;br /&gt;&lt;br /&gt;expandUniverse 3 initial_universe&lt;br /&gt;&lt;br /&gt;[False,False,False,True,False,False,False]&lt;br /&gt;&lt;br /&gt;We can use the expandUniverse function to expand our initial universe out to&lt;br /&gt;a standardized width before we start applying the rules.&lt;br /&gt;&lt;br /&gt;First, here's a routine to stringify a universe for display:&lt;br /&gt;&lt;br /&gt;&gt;boolToChar :: Bool -&gt; Char&lt;br /&gt;&gt;boolToChar True = '#'&lt;br /&gt;&gt;boolToChar False = ' '&lt;br /&gt;&lt;br /&gt;&gt;stringifyUniverse :: [Bool] -&gt; String&lt;br /&gt;&gt;stringifyUniverse ls = map boolToChar ls&lt;br /&gt;&lt;br /&gt;Now our infrastructure is in place, so let's figure out how to apply our&lt;br /&gt;generator rule. We know that we want to start with our initial universe. Let's&lt;br /&gt;expand it to a fixed size. This will give us enough elements to start making&lt;br /&gt;left/center/right tuples out of each consecutive set of three cells. Each tuple &lt;br /&gt;is then used to look up the next state of the cell at the center; this will &lt;br /&gt;become an element in our next universe. Then we move to the next cell (not &lt;br /&gt;three cells down). This means that the tuples overlap.&lt;br /&gt;&lt;br /&gt;Let's make the tuples. We have to do some thinking here and consider all the&lt;br /&gt;cases; the behavior isn't immediately obvious. The following almost works:&lt;br /&gt;&lt;br /&gt;universeToTuples :: [Bool] -&gt; [(Bool, Bool, Bool)]&lt;br /&gt;universeToTuples universe | length universe &gt;= 3 =&lt;br /&gt;   ( universe !! 0, universe !! 1, universe !! 2 ) :&lt;br /&gt;   universeToTuples ( tail universe )&lt;br /&gt;universeToTuples universe = []&lt;br /&gt;&lt;br /&gt;universeToTuples [False, True, True, True, False]&lt;br /&gt;&lt;br /&gt;[(False,True,True),&lt;br /&gt;(True,True,True),&lt;br /&gt;(True,True,False)]&lt;br /&gt;&lt;br /&gt;But it isn't quite right; it leaves off the end cases; when we apply our rules,&lt;br /&gt;the intermediate representation of the universe as a list of tuples to look up&lt;br /&gt;cell mappings will shrink. We actually want the following tuples:&lt;br /&gt;&lt;br /&gt;[(False,False,True),&lt;br /&gt;(False,True,True),&lt;br /&gt;(True,True,True),&lt;br /&gt;(True,True,False),&lt;br /&gt;(True,False,False)]&lt;br /&gt;&lt;br /&gt;where the first element of the list is considered as if it was just to the&lt;br /&gt;right of an implied False, and the last element is considered as if it was&lt;br /&gt;just to the left of another implied False. This sounds like another place we&lt;br /&gt;can use our universe expander:&lt;br /&gt;&lt;br /&gt;&gt;universeToTuples :: [Bool] -&gt; [(Bool, Bool, Bool)]&lt;br /&gt;&gt;universeToTuples [] = []&lt;br /&gt;&gt;universeToTuples universe = tupleize $ expandUniverse 1 universe&lt;br /&gt;&gt;   where&lt;br /&gt;&gt;       tupleize xs = &lt;br /&gt;&gt;            if length xs &gt; 3 then tuple3 xs : tupleize ( tail xs )&lt;br /&gt;&gt;               else [ tuple3 xs ]&lt;br /&gt;&gt;       tuple3 xs = ( xs !! 0, xs !! 1, xs !! 2 )&lt;br /&gt;&lt;br /&gt;Why did I write it that way? Well, I tried to write tupleize using guards, &lt;br /&gt;special-casing length xs &gt; 3 followed by an unguarded case for all other &lt;br /&gt;possibilities, but GHC didn't like it -- it told me I had non-exhaustive &lt;br /&gt;patterns. There is probably a smarter way to write this, but note that we&lt;br /&gt;definitely don't want this version:&lt;br /&gt;&lt;br /&gt;universeToTuples universe = ( xs !! 0, xs !! 1, xs !! 2 ) &lt;br /&gt;    : universeToTuples ( tail xs )&lt;br /&gt;       where xs = expandUniverse 1 universe&lt;br /&gt;&lt;br /&gt;In that version, the universe keeps expanding as we walk down the list,&lt;br /&gt;and we never get to the end!&lt;br /&gt;&lt;br /&gt;OK, now that we have our tuples, we want to turn them into our new universe,&lt;br /&gt;given a cellular rule number:&lt;br /&gt;&lt;br /&gt;&gt;tuplesToUniverse :: Int -&gt; [(Bool, Bool, Bool)] -&gt; [Bool]&lt;br /&gt;&gt;tuplesToUniverse rule [] = []&lt;br /&gt;&gt;tuplesToUniverse rule (tup:tups) = genNextBit rule tup : tuplesToUniverse rule tups&lt;br /&gt;&lt;br /&gt;Note that we don't have to explicitly take the tail since we provide a name&lt;br /&gt;for it in the pattern. We're ready to define our genUniverses function that&lt;br /&gt;applies a given CA rule. We can express a given generation like this:&lt;br /&gt;&lt;br /&gt;&gt;nextUniverse :: Int -&gt; [Bool] -&gt; [Bool]&lt;br /&gt;&gt;nextUniverse rule universe = tuplesToUniverse rule $ universeToTuples universe&lt;br /&gt;&lt;br /&gt;Now, let's generalize it:&lt;br /&gt;&lt;br /&gt;&gt;genUniverses :: Int -&gt; Int -&gt; Int -&gt; [[Bool]]&lt;br /&gt;&gt;genUniverses rule width count = take count &lt;br /&gt;&gt;   ( iterate ( nextUniverse rule ) ( expandUniverse ( width `div` 2 ) initial_universe ) )&lt;br /&gt;&lt;br /&gt;(You could also use a fold, and I'm sure there are lots of other ways to do it,&lt;br /&gt;but iterate seems to work fine).&lt;br /&gt;&lt;br /&gt;And now, witness the unfolding of a universe! Note that the parameters that&lt;br /&gt;go to genUniverses are the rule number, the width for display, and the number&lt;br /&gt;of generations:&lt;br /&gt;&lt;br /&gt;putStr $ unlines $ map stringifyUniverse $ genUniverses 222 19 10&lt;br /&gt;&lt;br /&gt;          #&lt;br /&gt;         ###&lt;br /&gt;        #####&lt;br /&gt;       #######&lt;br /&gt;      #########&lt;br /&gt;     ###########&lt;br /&gt;    #############&lt;br /&gt;   ###############&lt;br /&gt;  #################&lt;br /&gt; ###################&lt;br /&gt; &lt;br /&gt;In general, a width of twice the number of generations - 1 will show all the &lt;br /&gt;transitions we are interested in; you could consider the diagonal area above &lt;br /&gt;to be the "light cone" of events causally connected to that single point (although&lt;br /&gt;some rules will generate True cells outside of that "light cone" based on the&lt;br /&gt;other False values in the initial universe). Let's make a helper function to &lt;br /&gt;choose a width for us:&lt;br /&gt;&lt;br /&gt;&gt;showRule rule gens = &lt;br /&gt;&gt;   putStr $ unlines $ map stringifyUniverse $ &lt;br /&gt;&gt;       genUniverses rule ( gens * 2 - 1 ) gens&lt;br /&gt;&lt;br /&gt;Let's try a few of the other rules:&lt;br /&gt;&lt;br /&gt;showRule 252 15&lt;br /&gt;              #&lt;br /&gt;              ##&lt;br /&gt;              ###&lt;br /&gt;              ####&lt;br /&gt;              #####&lt;br /&gt;              ######&lt;br /&gt;              #######&lt;br /&gt;              ########&lt;br /&gt;              #########&lt;br /&gt;              ##########&lt;br /&gt;              ###########&lt;br /&gt;              ############&lt;br /&gt;              #############&lt;br /&gt;              ##############&lt;br /&gt;              ###############&lt;br /&gt;&lt;br /&gt;showRule 78 15&lt;br /&gt;               #&lt;br /&gt;              ##&lt;br /&gt;             ###&lt;br /&gt;            ## #&lt;br /&gt;           ### #&lt;br /&gt;          ## # #&lt;br /&gt;         ### # #&lt;br /&gt;        ## # # #&lt;br /&gt;       ### # # #&lt;br /&gt;      ## # # # #&lt;br /&gt;     ### # # # #&lt;br /&gt;    ## # # # # #&lt;br /&gt;   ### # # # # #&lt;br /&gt;  ## # # # # # #&lt;br /&gt; ### # # # # # #&lt;br /&gt;&lt;br /&gt;And finally, my all-time favorite, which simulates a Sierpinski gasket:&lt;br /&gt;&lt;br /&gt;showRule 82 32&lt;br /&gt;                                #&lt;br /&gt;                               # #&lt;br /&gt;                              #   #&lt;br /&gt;                             # # # #&lt;br /&gt;                            #       #&lt;br /&gt;                           # #     # #&lt;br /&gt;                          #   #   #   #&lt;br /&gt;                         # # # # # # # #&lt;br /&gt;                        #               #&lt;br /&gt;                       # #             # #&lt;br /&gt;                      #   #           #   #&lt;br /&gt;                     # # # #         # # # #&lt;br /&gt;                    #       #       #       #&lt;br /&gt;                   # #     # #     # #     # #&lt;br /&gt;                  #   #   #   #   #   #   #   #&lt;br /&gt;                 # # # # # # # # # # # # # # # #&lt;br /&gt;                #                               #&lt;br /&gt;               # #                             # #&lt;br /&gt;              #   #                           #   #&lt;br /&gt;             # # # #                         # # # #&lt;br /&gt;            #       #                       #       #&lt;br /&gt;           # #     # #                     # #     # #&lt;br /&gt;          #   #   #   #                   #   #   #   #&lt;br /&gt;         # # # # # # # #                 # # # # # # # #&lt;br /&gt;        #               #               #               #&lt;br /&gt;       # #             # #             # #             # #&lt;br /&gt;      #   #           #   #           #   #           #   #&lt;br /&gt;     # # # #         # # # #         # # # #         # # # #&lt;br /&gt;    #       #       #       #       #       #       #       #&lt;br /&gt;   # #     # #     # #     # #     # #     # #     # #     # #&lt;br /&gt;  #   #   #   #   #   #   #   #   #   #   #   #   #   #   #   #&lt;br /&gt; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #&lt;br /&gt;&lt;br /&gt;Wow!&lt;/pre&gt;Followup: I had mentioned that my code had a bug, because some pictures, such as this one:&lt;pre&gt;showRule 29 11&lt;br /&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;#         #&lt;br /&gt;######### ###########&lt;br /&gt;#         #&lt;br /&gt;######### ###########&lt;br /&gt;#         #&lt;br /&gt;######### ###########&lt;br /&gt;#         #&lt;br /&gt;######### ###########&lt;br /&gt;#         #&lt;/pre&gt;look different than the way Wolfram's book and web site shows them, which is like this:&lt;pre&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;          #&lt;br /&gt;######### ###########&lt;br /&gt;          #&lt;/pre&gt;After a little investigation this seems to be because Wolfram's implementation wraps around; the left neighbor of the leftmost cell of a given universe is taken from the rightmost cell, and vice-versa, while my implementation pretends that there is always more empty space available to the left and right.&lt;br /&gt;&lt;br /&gt;Whether you consider this a bug or not is up to you. The wraparound behavior is probably considered more "canonical." You can compare the results from my program to the pictures at Wolfram's MathWorld site &lt;a href="http://mathworld.wolfram.com/ElementaryCellularAutomaton.html"&gt;here&lt;/a&gt;. If you replace my universeToTuples function with this one:&lt;pre&gt;universeToTuples :: [Bool] -&gt; [(Bool, Bool, Bool)]&lt;br /&gt;universeToTuples [] = []&lt;br /&gt;universeToTuples universe = tupleize $ wrapUniverse universe&lt;br /&gt;   where&lt;br /&gt;       wrapUniverse xs =  ( last xs ) : ( xs ++ [ head xs ] )&lt;br /&gt;       tupleize xs = &lt;br /&gt;           if length xs &gt; 3 then tuple3 xs : tupleize ( tail xs )&lt;br /&gt;               else [ tuple3 xs ]&lt;br /&gt;       tuple3 xs = ( xs !! 0, xs !! 1, xs !! 2 )&lt;/pre&gt;you will get the wraparound behavior.&lt;br /&gt;&lt;br /&gt;Thanks for reading and as always, I appreciate your comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-8447012067148157459?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/8447012067148157459/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=8447012067148157459' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8447012067148157459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/8447012067148157459'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/from-bits-to-cells-simple-cellular_19.html' title='From Bits to Cells: Simple Cellular Automata in Haskell, Part Two'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-6479529087542963807</id><published>2006-12-17T17:37:00.000-05:00</published><updated>2006-12-18T16:26:44.963-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>From Bits to Cells: Simple Cellular Automata in Haskell, Part One</title><content type='html'>The little Haskell toy I wrote to simulate a dot-matrix printhead was useful in one sense: it helped me learn a little more Haskell! I couldn't help noticing that the results look like the transformations you get when applying simple cellular automata rules. So my next experiment is to implement those rules, and see what else I can learn from the results. &lt;br /&gt;&lt;br /&gt;What follows is Literate Haskell, but there is no main program to run; it is for you to experiment with interactively, if you like.&lt;pre&gt;Some Haskell code to implement simple cellular automata (CA) rules:&lt;br /&gt;part one, round one.&lt;br /&gt;&lt;br /&gt;The simplest type of one-dimensional CA behaves as follows: &lt;br /&gt;&lt;br /&gt;- a cell may be on or off (one or zero). &lt;br /&gt;&lt;br /&gt;- time ticks by in discrete intervals.&lt;br /&gt;&lt;br /&gt;- at each tick, the state of each cell is updated using a function that&lt;br /&gt;maps the current state of the cell to the left, the cell itself, and&lt;br /&gt;the cell to the right to the new cell value.&lt;br /&gt;&lt;br /&gt;Because this value-generating function depends on 3 bits of input, a &lt;br /&gt;given CA rule actually consists of 2^3 = 8 possible mappings. The &lt;br /&gt;mappings can be represented by the binary values 0b000 to 0b111 &lt;br /&gt;(decimal 0..7). By Wolfram's numbering convention for these simple &lt;br /&gt;CA, we actually count down from 7 to 0. So, let's say we have a rule &lt;br /&gt;that maps each possible set of left, center, and right values:&lt;br /&gt;&lt;br /&gt;0b111, 0b110, 0b101, 0b100, 0b011, 0b010, 0b001, 0b000&lt;br /&gt;&lt;br /&gt;to the new cell value:&lt;br /&gt;&lt;br /&gt;0b0, 0b0, 0b0, 0b1, 0b1, 0b1, 0b1, 0b0&lt;br /&gt;&lt;br /&gt;We can treat the resulting number, in this case 0b00011110, as the&lt;br /&gt;rule number. This is rule 30 in Wolfram's schema; there are 2^8, &lt;br /&gt;or 256, possible rules, numbered from 0 to 255.&lt;br /&gt;&lt;br /&gt;First, let's make a function that, given a rule number and three&lt;br /&gt;values (left, center, and right), returns the new cell state. We&lt;br /&gt;turn the three values into an index to look up the appropriate bit&lt;br /&gt;in the rule number.&lt;br /&gt;&lt;br /&gt;&gt;import Data.Bits&lt;br /&gt;&lt;br /&gt;&gt;genNextBit :: Int -&gt; ( Bool, Bool, Bool ) -&gt; Bool&lt;br /&gt;&gt;genNextBit rulenum ( left, center, right ) = rulenum `testBit` idx&lt;br /&gt;&gt;    where idx = ( if left then (4::Int) else (0::Int) ) .|. &lt;br /&gt;&gt;           ( if center then (2::Int) else (0::Int) ) .|. &lt;br /&gt;&gt;           ( if right then (1::Int) else (0::Int) )&lt;br /&gt;&lt;br /&gt;Hmmm... it is lacking a certain elegance, and I don't quite like&lt;br /&gt;the way the indentation rules work in this case, but let's test it &lt;br /&gt;with a function that generates the 8 rule indices in the form of tuples:&lt;br /&gt;&lt;br /&gt;&gt;genRuleIndices :: [( Bool, Bool, Bool )]&lt;br /&gt;&gt;genRuleIndices = [ ( (val `testBit` 2), (val `testBit` 1),&lt;br /&gt;&gt;                   ( val `testBit` 0) ) | val &lt;- [(7::Int), &lt;br /&gt;&gt;                   (6::Int)..(0::Int)] ]&lt;br /&gt;&lt;br /&gt;Now if we write:&lt;br /&gt;&lt;br /&gt;genRuleIndices&lt;br /&gt;&lt;br /&gt;we get:&lt;br /&gt;&lt;br /&gt;[(True,True,True),&lt;br /&gt;(True,True,False),&lt;br /&gt;...&lt;br /&gt;(False,False,True),&lt;br /&gt;(False,False,False)]&lt;br /&gt;&lt;br /&gt;and if we write:&lt;br /&gt;&lt;br /&gt;map (genNextBit 30) genRuleIndices&lt;br /&gt;&lt;br /&gt;this expression curries us a function (mmm... curry!) which takes &lt;br /&gt;a starting state and applies rule 30, then feeds it the possible &lt;br /&gt;starting states. The result is:&lt;br /&gt;&lt;br /&gt;[False,False,False,True,True,True,True,False]&lt;br /&gt;&lt;br /&gt;That looks like the bit pattern for rule 30.&lt;br /&gt;&lt;br /&gt;Just for fun, let's confirm by making a function that will&lt;br /&gt;translate a list of output bit values back into a rule number.&lt;br /&gt;The signature should look like this:&lt;br /&gt;&lt;br /&gt;sumBitVals :: [Bool] -&gt; Int&lt;br /&gt;&lt;br /&gt;And we want the list&lt;br /&gt;&lt;br /&gt;&gt;test_bit_vals = [False,False,False,True,True,True,True,False]&lt;br /&gt;&lt;br /&gt;to map back to 30. Take a shot at it yourself; you might find&lt;br /&gt;that the result is instructional I'll wait.&lt;br /&gt;&lt;br /&gt;(Musical interlude).&lt;br /&gt;&lt;br /&gt;Did you try it? Let's look at some possible implementation strategies.&lt;br /&gt;We could make a list of the powers of two and then do some list &lt;br /&gt;manipulation to get the powers of two that correspond to our one-bits&lt;br /&gt;summed up:&lt;br /&gt;&lt;br /&gt;&gt;powers_of_two_8_bits = reverse ( take 8 (iterate (2 *) 1) )&lt;br /&gt;&lt;br /&gt;[128,64,32,16,8,4,2,1]&lt;br /&gt;&lt;br /&gt;(An aside: since this is generated by a function that takes no &lt;br /&gt;parameters at runtime, it would seem like a sufficiently smart &lt;br /&gt;compiler could generate this list and stick it in the resulting &lt;br /&gt;program so that no run-time calculation is required to generate &lt;br /&gt;it. Does GHC do this? I don't know.)&lt;br /&gt;&lt;br /&gt;Anyway, our implementation. We can tuple up our powers of two with&lt;br /&gt;our bit values:&lt;br /&gt;&lt;br /&gt;&gt;tups = zip powers_of_two_8_bits test_bit_vals &lt;br /&gt;&lt;br /&gt;[(128,False),(64,False),(32,False),(16,True),(8,True),(4,True),(2,True),(1,False)]&lt;br /&gt;&lt;br /&gt;Then we can turn this back into a list of only the powers of two that are &lt;br /&gt;"on," and sum the results:&lt;br /&gt;&lt;br /&gt;sum (map (\ tup -&gt; if snd tup then fst tup else 0) tups )&lt;br /&gt;&lt;br /&gt;30&lt;br /&gt;&lt;br /&gt;It seems like this should be simpler still. I looked in the standard &lt;br /&gt;library for a function to filter one list using a list of boolean &lt;br /&gt;values as a comb. Let's write one:&lt;br /&gt;&lt;br /&gt;&gt;combListWithList :: [a] -&gt; [Bool] -&gt; [a]&lt;br /&gt;&gt;combListWithList [] [] = []&lt;br /&gt;&gt;combListWithList ls comb = &lt;br /&gt;&gt;   if (head comb) then (head ls) : combListWithList (tail ls) (tail comb)&lt;br /&gt;&gt;       else combListWithList (tail ls) (tail comb)&lt;br /&gt;&lt;br /&gt;combListWithList powers_of_two_8_bits test_bit_vals&lt;br /&gt;&lt;br /&gt;[16,8,4,2]&lt;br /&gt;&lt;br /&gt;That seems good, although it doesn't express the idea that the lists&lt;br /&gt;have to be the same length. It still seems amazing to me that I can &lt;br /&gt;reel off functions like that in Haskell and have them work right the &lt;br /&gt;first time! Now we can produce our final function:&lt;br /&gt;&lt;br /&gt;&gt;sumBitVals :: [Bool] -&gt; Int&lt;br /&gt;&gt;sumBitVals ls = sum $ combListWithList powers_of_two_8_bits ls&lt;br /&gt;&lt;br /&gt;sumBitVals test_bit_vals&lt;br /&gt;&lt;br /&gt;30&lt;br /&gt;&lt;br /&gt;There is probably an elementary way to implement the above function&lt;br /&gt;using zipWith instead of my combList, but I'll leave that to you;&lt;br /&gt;leave a comment if you figure it out!&lt;br /&gt;&lt;br /&gt;As another aside, here is another function I came up with to generate &lt;br /&gt;this bit vals; it doesn't rely on a specific length.&lt;br /&gt;&lt;br /&gt;&gt;foldBitVals :: [Bool] -&gt; Int&lt;br /&gt;&gt;foldBitVals ls = snd (foldr &lt;br /&gt;&gt;   (\ flag tup -&gt; if flag then ((fst tup) * 2, (snd tup) + (fst tup)) &lt;br /&gt;&gt;                           else ((fst tup) * 2, snd tup) )&lt;br /&gt;&gt;   (1, 0) ls )&lt;br /&gt;&lt;br /&gt;foldBitVals test_bit_vals&lt;br /&gt;&lt;br /&gt;30&lt;br /&gt;&lt;br /&gt;Take a moment to understand the above function; it is a little strange.&lt;br /&gt;I perform a fold using a tuple. The first element is the power of two, &lt;br /&gt;so it keeps track of our place in the list, and the second is an &lt;br /&gt;accumulator as we add up our values. This is a trick for stashing&lt;br /&gt;a state that is more complex than a single value into a fold.&lt;/pre&gt;Anyway, that was a long diversion, so let's end for now. Next time we'll look at ways to represent our CA universe as it evolves by applying our rules. As always, your comments are welcome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-6479529087542963807?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/6479529087542963807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=6479529087542963807' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6479529087542963807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/6479529087542963807'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/from-bits-to-cells-simple-cellular.html' title='From Bits to Cells: Simple Cellular Automata in Haskell, Part One'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-5997106011461231166</id><published>2006-12-14T14:23:00.000-05:00</published><updated>2006-12-18T13:49:07.281-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Revised Dot-Matrix Printhead</title><content type='html'>It looks like this blog has been unceremoniously removed from Planet Scheme. I guess that's only fair, since I haven't written anything  specifically about Scheme in a while. Best of intentions, and all that. This blog probably belongs on "Planet Programming Language Dilettante." &lt;br /&gt;&lt;br /&gt;Anyway, I received some helpful feedback on the short program I wrote to print bitmaps of binary numbers. Jason Creighton in particular took a shot at a rewrite, and the result as highly enlightening. I also recieved two specific pieces of advice: use short function names, and don't write a comprehension like [a | a &lt;- [a..b]] when you can just write [a..b]. Oops. Check, and thanks!&lt;br /&gt;&lt;br /&gt;(Semi) or (Ill) Literate Haskell follows:&lt;pre&gt;Haskell Binary Printhead Toy, Second Round&lt;br /&gt;&lt;br /&gt;&gt;import Data.Bits&lt;br /&gt;&lt;br /&gt;Our functions to generate lists of signed and unsigned integers of&lt;br /&gt;numbits length, revised with names as suplied by Jason and error-&lt;br /&gt;catching as supplied by yours truly:&lt;br /&gt;&lt;br /&gt;&gt;unsignedInts :: Int -&gt; [Int]&lt;br /&gt;&gt;unsignedInts bits | (1 &lt;= bits) &amp;&amp; (bits &lt;= 16) = &lt;br /&gt;&gt;   [(0::Int)..(bound::Int)] &lt;br /&gt;&gt;   where bound = 2 ^ bits - 1&lt;br /&gt;&gt;unsignedInts bits = error "expected a value from 1 to 16"&lt;br /&gt;&lt;br /&gt;&gt;signedInts :: Int -&gt; [Int]&lt;br /&gt;&gt;signedInts bits | (1 &lt;= bits) &amp;&amp; (bits &lt;= 16) = &lt;br /&gt;&gt;   [(- (bound::Int)) - 1..(bound::Int)] &lt;br /&gt;&gt;   where bound = 2 ^ ( bits - 1 ) - 1&lt;br /&gt;&gt;signedInts bits = error "expected a value from 1 to 16"&lt;br /&gt;&lt;br /&gt;Jason came up with a considerably simpler way to map the bits of&lt;br /&gt;the binary numbers to the characters for printing:&lt;br /&gt;&lt;br /&gt;&gt;boolToChar :: Bool -&gt; Char&lt;br /&gt;&gt;boolToChar True = '#'&lt;br /&gt;&gt;boolToChar False = ' '&lt;br /&gt;&lt;br /&gt;I'm adopting that suggestion enthusiastically, since I don't think&lt;br /&gt;code can get much simpler than that!&lt;br /&gt;&lt;br /&gt;Jason then proceeded to turn my dog food into a much more flavorful &lt;br /&gt;wafter-thin after-dinner mint, leaving me struggling to understand&lt;br /&gt;just what he did:&lt;br /&gt;&lt;br /&gt;&gt;bitPicture :: (Int -&gt; [Int]) -&gt; Int -&gt; [Char]&lt;br /&gt;&gt;bitPicture intGen bits = unlines $ map stringAtIndex (reverse [0..(bits-1)])&lt;br /&gt;&gt;  where&lt;br /&gt;&gt;    stringAtIndex = map boolToChar . bitsAtIndex&lt;br /&gt;&gt;    bitsAtIndex idx = [ testBit n idx | n &lt;- intGen bits ]&lt;br /&gt;&lt;br /&gt;Wow. First off, Jason has supplied a type signature which expresses &lt;br /&gt;what the function actually _does_. The appropriate integer generator &lt;br /&gt;(the signed or unsigned version) comes in as a parameter; that's what &lt;br /&gt;(Int -&gt; [Int]) means. We next get an integer argument (the number of &lt;br /&gt;bits), and finally, we spit out a list of chars.&lt;br /&gt;&lt;br /&gt;Jason proceeds to use a couple of where clauses to set up some &lt;br /&gt;simplifying expressions. Let's look at the first one:&lt;br /&gt;&lt;br /&gt;StringAtIndex = map boolToChar . bitsAtIndex&lt;br /&gt;&lt;br /&gt;OK, this is slightly mind-twisting right off the bat. In the world &lt;br /&gt;of C and Java you can't write things like that. The dot is function &lt;br /&gt;composition expressed naturally; instead of something like&lt;br /&gt;&lt;br /&gt;stringOfBoolsFromBitsAtIndex idx = map boolToChar (bitsAtIndex idx)&lt;br /&gt;&lt;br /&gt;we can just get Haskell to chain the functions together for us. &lt;br /&gt;No fuss, no muss. But this function makes a forward reference to &lt;br /&gt;bitsAtIndex, which we haven't seen yet (completely illegal in C &lt;br /&gt;and Java). Let's make sure we understand what bitsAtIndex does:&lt;br /&gt;&lt;br /&gt;bitsAtIndex idx = [ testBit n idx | n &lt;- intGen bits ]&lt;br /&gt;&lt;br /&gt;That's definitely more dense than the way I wrote it (and that's a &lt;br /&gt;good thing). To break down the list comprehension, the expression on &lt;br /&gt;the right hand side of the vertical bar says that we feed the supplied &lt;br /&gt;integer generator function the number of bits to use. That gives us a &lt;br /&gt;list. From that list we will draw our "n"s and test bit idx on them. &lt;br /&gt;By doing it this way, Creighton has pulled an act of Haskell sleight-&lt;br /&gt;of-hand: instead of generating the bitmaps for each integer value, &lt;br /&gt;like I did, and then using "transpose" to rearrange them, this version &lt;br /&gt;accesses the "columns" of the table directly! With those two &lt;br /&gt;expressions, we've got our string representing all the bits at a &lt;br /&gt;given index _for the whole supplied set of integers_.&lt;br /&gt;&lt;br /&gt;Wow. I feel like an audience member watching a magician smash up my &lt;br /&gt;watch and then give it back to me rebuilt as a marvelous whirring &lt;br /&gt;gyroscope.&lt;br /&gt;&lt;br /&gt;There's more, but this part is relatively simple:&lt;br /&gt;&lt;br /&gt;bitPicture intGen bits = unlines $ map stringAtIndex (reverse [0..(bits-1)])&lt;br /&gt;&lt;br /&gt;We already know what unlines does; it turns our list of strings into a&lt;br /&gt;properly line-broken string. We've just described how stringAtIndex works.&lt;br /&gt;and map stringAtIndex (reverse [0..(bits-1)[) just feeds stringAtIndex a&lt;br /&gt;set of indices mapped from high to low, so that our most significant bit&lt;br /&gt;comes out leftmost. But what does "$" do?&lt;br /&gt;&lt;br /&gt;My reference at zvon.org says this is the "right-associating infix &lt;br /&gt;application operator (f $ x = f x), useful in continuation-passing style."&lt;br /&gt;I'm not sure I fully understand, and I'm not going to go into the meaning&lt;br /&gt;of "continuation-passing style" right now, but I guess it saves us from &lt;br /&gt;having to write:&lt;br /&gt;&lt;br /&gt;unlines $ map (stringAtIndex (reverse [0..(bits-1)]))&lt;br /&gt;&lt;br /&gt;to get the right order of operations, which is nice. So I'll try to &lt;br /&gt;incorporate it into my own Haskell.&lt;br /&gt;&lt;br /&gt;Anyway, let's try it. We need to drive the function:&lt;br /&gt;&lt;br /&gt;&gt;main :: IO ()&lt;br /&gt;&gt;main = do&lt;br /&gt;&gt;   print "Unsigned values (6 bits)"&lt;br /&gt;&gt;   putStr $ bitPicture unsignedInts 6 &lt;br /&gt;&gt;   print "Signed values (6 bits)"&lt;br /&gt;&gt;   putStr $ bitPicture signedInts 6&lt;br /&gt;&lt;br /&gt;After using GHCi's :cd and :load command to read this file, just&lt;br /&gt;type:&lt;br /&gt;&lt;br /&gt;main&lt;br /&gt;&lt;br /&gt;"Unsigned values (6 bits)"&lt;br /&gt;                                 ################################&lt;br /&gt;                 ################                ################&lt;br /&gt;         ########        ########        ########        ########&lt;br /&gt;     ####    ####    ####    ####    ####    ####    ####    ####&lt;br /&gt;   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##&lt;br /&gt;  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #&lt;br /&gt;"Signed values (6 bits)"&lt;br /&gt; ################################&lt;br /&gt;                 ################                ################&lt;br /&gt;         ########        ########        ########        ########&lt;br /&gt;     ####    ####    ####    ####    ####    ####    ####    ####&lt;br /&gt;   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##&lt;br /&gt;  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #&lt;/pre&gt;Excellent. I laughed; I cried; I learned something today. I hope you did, too. Thanks, Jason! And thanks to the other people who commented!&lt;br /&gt;&lt;br /&gt;Followup: for those following along the discussion in the comments, here is an alternate implementation of the bitPicture function:&lt;pre&gt;bitPicture intGen bits = unlines $ map stringAtIndex $ [bits - 1, bits - 2..0]&lt;br /&gt;  where&lt;br /&gt;    stringAtIndex = map boolToChar . bitsAtIndex&lt;br /&gt;    bitsAtIndex idx = map (flip testBit idx) (intGen bits)&lt;/pre&gt;Note that using [bits - 1, bits - 2..0] in the first line allows us to avoid the list reversal, so that seems like a clear win. The method of expressing bitsAtIndex above is one of several that were suggested. The idea behind the flip is that the return value of intGen should become the first parameter to bitsAtIndex, not the second. You can also express this by forcing stringAtIndex to be treated as an infix operator:&lt;pre&gt;bitsAtIndex idx = map (`testBit` idx) (intGen bits)&lt;/pre&gt;Both of these alter the behavior of Haskell's automatic currying so that it replaces the second parameter instead of the first, leaving the first as the sole parameter to the resulting curried function; in Common Lisp, you might do this explicitly using rcurry. And don't forget the original, using a list comprehension:&lt;pre&gt;bitsAtIndex idx = [ testBit n idx | n &lt;- intGen bits ]&lt;/pre&gt;Assuming there is not a specific concern about efficiency, it seems like the choice between these versions might be a matter of style. Thanks again to everyone who made suggestions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-5997106011461231166?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/5997106011461231166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=5997106011461231166' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5997106011461231166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5997106011461231166'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/revised-dot-matrix-printhead.html' title='The Revised Dot-Matrix Printhead'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-5773124163893370921</id><published>2006-12-12T12:20:00.000-05:00</published><updated>2006-12-18T13:11:53.122-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Dot-Matrix Printhead: a Haskell Toy</title><content type='html'>The body of this article is a literate Haskell program. You can extract the text, then save it as a file with the extension .lhs, then execute it using GHCi.&lt;pre&gt;This is a Haskell toy to visualize twos-complement binary numbers.&lt;br /&gt;In my previous articles on the subject of integer division, I alluded&lt;br /&gt;two underflow and overflow and the "weird number" -- well, now you&lt;br /&gt;can see them! &lt;br /&gt;&lt;br /&gt;Almost 30 years ago I wrote code on my Radio Shack TRS-80 to make my &lt;br /&gt;dot-matrix printer spit out bitmaps of binary numbers, which made &lt;br /&gt;pretty recursive patterns. This program commemorates that long-ago &lt;br /&gt;geekery from my early teenage hacking days.&lt;br /&gt;&lt;br /&gt;First, we need the bits library:&lt;br /&gt;&lt;br /&gt;&gt;import Data.Bits&lt;br /&gt;&lt;br /&gt;We'll also need the list library later:&lt;br /&gt;&lt;br /&gt;&gt;import List&lt;br /&gt;&lt;br /&gt;Let's simulate n-bit binary number in both a signed and unsigned&lt;br /&gt;interpretation. Given a number of bits, we want a function to make&lt;br /&gt;a list of the possible values. For example, in unsigned form 8 bits &lt;br /&gt;will give us a list of the values 0..255; in signed form, it will be &lt;br /&gt;an asymmetrical list from -128..127. Note that this function generates&lt;br /&gt;the whole list, so if you give it a numbits value higher than, say,&lt;br /&gt;16, you might regret it.&lt;br /&gt;&lt;br /&gt;Our calculation fails for values of numbits &lt;= 0, so we put in a&lt;br /&gt;guard case for that. We also want to discourage creating very large&lt;br /&gt;lists, so we put in a guard case for numbits &gt; 16.&lt;br /&gt;&lt;br /&gt;&gt;gen_n_bit_nums_unsigned numbits | numbits &lt;= 0 = []&lt;br /&gt;&gt;gen_n_bit_nums_unsigned numbits | numbits &gt; 16 = error "too many bits!"&lt;br /&gt;&gt;gen_n_bit_nums_unsigned numbits = &lt;br /&gt;&gt;   [ n | n &lt;- [(0::Int)..((2::Int)^numbits - 1)] ]&lt;br /&gt;&lt;br /&gt;&gt;gen_n_bit_nums_signed numbits | numbits &lt;= 0 = [] &lt;br /&gt;&gt;gen_n_bit_nums_signed numbits | numbits &gt; 16 = error "too many bits!"&lt;br /&gt;&gt;gen_n_bit_nums_signed numbits = &lt;br /&gt;&gt;   [ n | n &lt;- [-(2::Int)^(numbits - 1)..((2::Int)^(numbits - 1) - 1)] ]&lt;br /&gt;&lt;br /&gt;To test this we can execute:&lt;br /&gt;&lt;br /&gt;gen_n_bit_nums_unsigned 4&lt;br /&gt;[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]&lt;br /&gt;&lt;br /&gt;gen_n_bit_nums_signed 4&lt;br /&gt;[-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]&lt;br /&gt;&lt;br /&gt;That looks about right.&lt;br /&gt;&lt;br /&gt;Now we want a function to access the bits of those numbers from most &lt;br /&gt;significant to least significant and build a list of corresponding &lt;br /&gt;boolean values. This would be expressed more naturally if EnumFromTo&lt;br /&gt;operated descending sequences. I'm sure there's a better way, but for&lt;br /&gt;now I will just reverse the resulting list:&lt;br /&gt;&lt;br /&gt;&gt;rightmost_bits num_bits val | num_bits &gt; 16 = error "too many bits"&lt;br /&gt;&gt;rightmost_bits num_bits val | num_bits &lt;= 0 = error "too few bits"&lt;br /&gt;&gt;rightmost_bits num_bits val = &lt;br /&gt;&gt;   reverse [ testBit (val::Int) bit_idx | bit_idx &lt;- [0..(num_bits - 1)] ]&lt;br /&gt;&lt;br /&gt;Once we have a function which will do it with one number, doing it with a &lt;br /&gt;whole list of numbers is very easy. We will make a curried function and&lt;br /&gt;use map. Currying in Haskell is very easy, which makes sense given that&lt;br /&gt;the operation, "to curry" and the language, Haskell, are both named after&lt;br /&gt;Haskell Curry!&lt;br /&gt;&lt;br /&gt;Our rightmost_bits function takes two arguments, but we want to make a &lt;br /&gt;new function which we can hand off as an argument to map, along with a &lt;br /&gt;list. This new function will only take one parameter. We can ask GHCi &lt;br /&gt;what it thinks the type of the rightmost_bits function is:&lt;br /&gt;&lt;br /&gt;:type rightmost_bits&lt;br /&gt;&lt;br /&gt;It says:&lt;br /&gt;&lt;br /&gt;rightmost_bits :: Int -&gt; Int -&gt; [Bool]&lt;br /&gt;&lt;br /&gt;We can make a new function out of it by doing partial application:&lt;br /&gt;instead of supplying all its arguments, we just supply the first one.&lt;br /&gt;&lt;br /&gt;gen_rightmost_bits 4&lt;br /&gt;&lt;br /&gt;If you do this in GHCi, you'll get an error message because the&lt;br /&gt;result is not printable (GHCi can't apply show to the result). &lt;br /&gt;But you can bind it:&lt;br /&gt;&lt;br /&gt;let bit_generator_4 = gen_rightmost_bits 4&lt;br /&gt;&lt;br /&gt;And then ask GHCi what its type is:&lt;br /&gt;&lt;br /&gt;:type bit_generator_4&lt;br /&gt;bit_generator_4 :: [Int] -&gt; [[Bool]]&lt;br /&gt;&lt;br /&gt;Take a moment to make sure you understand what we've done here: &lt;br /&gt;Haskell has made us a curried function which takes a list of values &lt;br /&gt;instead of a single value, and generates a list of lists. This&lt;br /&gt;seems pretty close to magic! Let's make another function that&lt;br /&gt;takes the number of bits and a list, generates the curried&lt;br /&gt;function, then maps the list to the curried function:&lt;br /&gt;&lt;br /&gt;&gt;gen_rightmost_bits num_bits ls = &lt;br /&gt;&gt;   map (rightmost_bits num_bits) ls&lt;br /&gt;&lt;br /&gt;As you can see, working with curried functions is completely&lt;br /&gt;effortless in Haskell. Here's a general function to generate&lt;br /&gt;a list of all the bit values for unsigned numbers of num_bits &lt;br /&gt;size:&lt;br /&gt;&lt;br /&gt;&gt;gen_all_bits_unsigned num_bits = &lt;br /&gt;&gt;   gen_rightmost_bits num_bits (gen_n_bit_nums_unsigned num_bits)&lt;br /&gt;&lt;br /&gt;&gt;gen_all_bits_signed num_bits = &lt;br /&gt;&gt;   gen_rightmost_bits num_bits (gen_n_bit_nums_signed num_bits)&lt;br /&gt;&lt;br /&gt;If we execute:&lt;br /&gt;&lt;br /&gt;gen_all_bits_unsigned 4&lt;br /&gt;&lt;br /&gt;We get back the following (I have reformatted the output for clarity):&lt;br /&gt;&lt;br /&gt;[[False, False, False, False], &lt;br /&gt;[False, False, False, True], &lt;br /&gt;[False, False, True, False],&lt;br /&gt;[False, False, True, True],&lt;br /&gt;[False, True, False, False],&lt;br /&gt;[False, True, False, True],&lt;br /&gt;[False, True, True, False],&lt;br /&gt;[False, True, True, True],&lt;br /&gt;[True, False, False, False],&lt;br /&gt;[True, False, False, True],&lt;br /&gt;[True, False, True, False],&lt;br /&gt;[True, False, True, True],&lt;br /&gt;[True, True, False, False],&lt;br /&gt;[True, True, False, True],&lt;br /&gt;[True, True, True, False],&lt;br /&gt;[True, True, True, True]]&lt;br /&gt;&lt;br /&gt;This is recognizably a table of the unsigned binary values 0..15.&lt;br /&gt;This approach doesn't seem very "Haskell-ish" yet -- instead of &lt;br /&gt;generating the combinations as needed, I'm producing them all &lt;br /&gt;ahead of time. It also feels to me like I'm pushing uphill on &lt;br /&gt;the syntax, and having to use parentheses to force the order &lt;br /&gt;of evaluation. We can think more about that later, but let's &lt;br /&gt;get our pretty-printing working first.&lt;br /&gt;&lt;br /&gt;How can I turn all those boolean values into a string I can print?&lt;br /&gt;Well, we can take advantage of the fact that in Haskell, strings can&lt;br /&gt;be treated as lists, and the same methods apply. This is not efficient,&lt;br /&gt;but it allows us to use some of the standard functional techniques.&lt;br /&gt;One of these is "fold."&lt;br /&gt;&lt;br /&gt;Fold is a technique for boiling down a list into some kind of summary&lt;br /&gt;form. Just what form this summary takes is up to you, since you can&lt;br /&gt;supply your own function and a starting value. For example, to sum&lt;br /&gt;the elements in a list, I could use foldl like this:&lt;br /&gt;&lt;br /&gt;foldl (\ x y -&gt; x + y) 0 [0, 1, 2]&lt;br /&gt; &lt;br /&gt;The first parameter to foldl is a function. In this case I'll use&lt;br /&gt;a lambda expression, which gives me a function I won't bother to&lt;br /&gt;name. The second paramter is the starting value. The starting value&lt;br /&gt;and the next item in the list are repeatedly passed to the function,&lt;br /&gt;which accumulates a value. In this case, the final result is 3.&lt;br /&gt;&lt;br /&gt;I can give foldl an empty string as the starting accumulator value&lt;br /&gt;and my function can concatenate strings onto it: &lt;br /&gt;&lt;br /&gt;&gt;stringify_vals =&lt;br /&gt;&gt;   foldl (\ x y -&gt; if y then x ++ "#" else x ++ " ") ""&lt;br /&gt;&lt;br /&gt;Now you might want to try to apply our list of lists to this&lt;br /&gt;function:&lt;br /&gt;&lt;br /&gt;stringify_vals (gen_all_bits_unsigned num_bits)&lt;br /&gt;&lt;br /&gt;If you do that, though, you'll get a type error like this:&lt;br /&gt;&lt;br /&gt;"Couldn't match expected type `Bool' against inferred type `[Bool]'"&lt;br /&gt;&lt;br /&gt;The reason can be seen if we examine the types:&lt;br /&gt;&lt;br /&gt;:type (gen_all_bits_unsigned 4) :: [[Bool]]&lt;br /&gt;(gen_all_bits_unsigned 4) :: [[Bool]]&lt;br /&gt;&lt;br /&gt;:type stringify_vals&lt;br /&gt;stringify_vals :: [Bool] -&gt; [Char]&lt;br /&gt;&lt;br /&gt;We have a list of lists of bools, but we want to feed our&lt;br /&gt;stringification function a list of bools. To apply each&lt;br /&gt;element of (gen_all_bits_unsigned 4) to our stringification&lt;br /&gt;function, we can use map again:&lt;br /&gt;&lt;br /&gt;&gt;stringify_all_unsigned_vals num_bits =&lt;br /&gt;&gt;   map stringify_vals (gen_all_bits_unsigned num_bits)&lt;br /&gt;&lt;br /&gt;&gt;stringify_all_signed_vals num_bits =&lt;br /&gt;&gt;   map stringify_vals (gen_all_bits_signed num_bits)&lt;br /&gt;&lt;br /&gt;This will give us a list of strings, one for each list of boolean&lt;br /&gt;values. (I've reformatted the output).&lt;br /&gt;&lt;br /&gt;["    ",&lt;br /&gt;"   #",&lt;br /&gt;"  # ",&lt;br /&gt;"  ##",&lt;br /&gt;" #  ",&lt;br /&gt;" # #",&lt;br /&gt;" ## ",&lt;br /&gt;" ###",&lt;br /&gt;"#   ",&lt;br /&gt;"#  #",&lt;br /&gt;"# # ",&lt;br /&gt;"# ##",&lt;br /&gt;"##  ",&lt;br /&gt;"## #",&lt;br /&gt;"### ",&lt;br /&gt;"####"]&lt;br /&gt;&lt;br /&gt;That's nice: we can start to see our recursive structure! But&lt;br /&gt;we really want that value to be turned into a single printable&lt;br /&gt;string. To achieve that, we can use the unlines function.&lt;br /&gt;&lt;br /&gt;&gt;prettyprint_unsigned num_bits =&lt;br /&gt;&gt;   unlines (stringify_all_unsigned_vals num_bits)&lt;br /&gt;&lt;br /&gt;&gt;prettyprint_signed num_bits =&lt;br /&gt;&gt;   unlines (stringify_all_signed_vals num_bits)&lt;br /&gt;&lt;br /&gt;When we interpret &lt;br /&gt;&lt;br /&gt;prettyprint_unsigned 3&lt;br /&gt;&lt;br /&gt;we see a single string with newline characters escaped, like so:&lt;br /&gt;&lt;br /&gt;"   \n  #\n # \n ##\n#  \n# #\n## \n###\n"&lt;br /&gt;&lt;br /&gt;This will give the results we want when we pass it to putStr, like so:&lt;br /&gt;&lt;br /&gt;putStr (prettyprint_unsigned 8)&lt;br /&gt;&lt;br /&gt;        #&lt;br /&gt;       #&lt;br /&gt;       ##&lt;br /&gt;      #&lt;br /&gt;      # #&lt;br /&gt;      ##&lt;br /&gt;      ###&lt;br /&gt;     #&lt;br /&gt;     #  #&lt;br /&gt;     # #&lt;br /&gt;     # ##&lt;br /&gt;     ##&lt;br /&gt;     ## #&lt;br /&gt;     ###&lt;br /&gt;     ####&lt;br /&gt;&lt;br /&gt;    (etc.)&lt;br /&gt;    &lt;br /&gt;Hmmm. That's nice, but it would be really cool if the results&lt;br /&gt;were rotated, so that we could see what it would look like if&lt;br /&gt;a printhead moving horizontally was printing out these values.&lt;br /&gt;To do this, we can actually start with our intermediate list of&lt;br /&gt;lists. If our four-bit numbers give us&lt;br /&gt;&lt;br /&gt;[[False, False, False, False], &lt;br /&gt;[False, False, False, True], &lt;br /&gt;[False, False, True, False],&lt;br /&gt;etc.&lt;br /&gt;&lt;br /&gt;we can see the values the other way using transpose. Let's write&lt;br /&gt;rotated versions of gen_all_bits_unsigned and gen_all_bits_signed:&lt;br /&gt;&lt;br /&gt;&gt;gen_all_bits_unsigned_rot num_bits = &lt;br /&gt;&gt;   transpose&lt;br /&gt;&gt;   (gen_rightmost_bits num_bits (gen_n_bit_nums_unsigned num_bits))&lt;br /&gt;&lt;br /&gt;&gt;gen_all_bits_signed_rot num_bits = &lt;br /&gt;&gt;   transpose&lt;br /&gt;&gt;   (gen_rightmost_bits num_bits (gen_n_bit_nums_signed num_bits))&lt;br /&gt;&lt;br /&gt;And make a new stringify function to play with:&lt;br /&gt;&lt;br /&gt;&gt;stringify_all_unsigned_vals_rot num_bits =&lt;br /&gt;&gt;   map stringify_vals (gen_all_bits_unsigned_rot num_bits)&lt;br /&gt;&lt;br /&gt;&gt;prettyprint_unsigned_rot num_bits =&lt;br /&gt;&gt;   unlines (stringify_all_unsigned_vals_rot num_bits)&lt;br /&gt;&lt;br /&gt;Now&lt;br /&gt;&lt;br /&gt;putStr (prettyprint_unsigned_rot 6)&lt;br /&gt;&lt;br /&gt;will give us:&lt;br /&gt;&lt;br /&gt;                                 ################################&lt;br /&gt;                 ################                ################&lt;br /&gt;         ########        ########        ########        ########&lt;br /&gt;     ####    ####    ####    ####    ####    ####    ####    ####&lt;br /&gt;   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##&lt;br /&gt;  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #&lt;br /&gt; &lt;br /&gt;Now that's what I'm talking about!&lt;br /&gt; &lt;br /&gt;We can use the unsigned version to see the interesting transition&lt;br /&gt;point between negative and positive values:&lt;br /&gt; &lt;br /&gt;&gt;stringify_all_signed_vals_rot num_bits =&lt;br /&gt;&gt;   map stringify_vals (gen_all_bits_signed_rot num_bits)&lt;br /&gt;&lt;br /&gt;&gt;prettyprint_signed_rot num_bits =&lt;br /&gt;&gt;   unlines (stringify_all_signed_vals_rot num_bits)&lt;br /&gt;&lt;br /&gt;Now&lt;br /&gt;&lt;br /&gt;putStr (prettyprint_signed_rot 6)&lt;br /&gt;&lt;br /&gt;will give us:&lt;br /&gt;&lt;br /&gt; ################################&lt;br /&gt;                 ################                ################&lt;br /&gt;         ########        ########        ########        ########&lt;br /&gt;     ####    ####    ####    ####    ####    ####    ####    ####&lt;br /&gt;   ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##&lt;br /&gt;  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #&lt;br /&gt;&lt;br /&gt;Now let's give our program a main function using the IO monad and&lt;br /&gt;have it print out several of our results:&lt;br /&gt;&lt;br /&gt;&gt;main :: IO ()&lt;br /&gt;&gt;main = do&lt;br /&gt;&gt;   print "Unsigned values (8 bits)"&lt;br /&gt;&gt;   putStr (prettyprint_unsigned 8) &lt;br /&gt;&gt;   print "Signed values (8 bits)"&lt;br /&gt;&gt;   putStr (prettyprint_signed 8) &lt;br /&gt;&gt;   print "Unsigned values (6 bits) rotated"&lt;br /&gt;&gt;   putStr (prettyprint_unsigned_rot 6) &lt;br /&gt;&gt;   print "Signed values (6 bits) rotated"&lt;br /&gt;&gt;   putStr (prettyprint_signed_rot 6)&lt;br /&gt;&lt;br /&gt;After using GHCi's :cd and :load command to read this file, just&lt;br /&gt;type:&lt;br /&gt;&lt;br /&gt;main&lt;/pre&gt;I would invite any readers to play around with the code, and if you can make it more concise and/or more "Haskellish," please leave a comment.&lt;br /&gt;&lt;br /&gt;Now if only we could get Haskell to generate the appropriate sound! My dot-matrix printer was loud. But that's a task for another day.&lt;br /&gt;&lt;br /&gt;NOTE: there is a followup aticle to this one which develops the code further; see http://praisecurseandrecurse.blogspot.com/2006/12/revised-dot-matrix-printhead.html&lt;br /&gt;&lt;br /&gt;Also, make sure to take a look at the comments on both this posting and the followup.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-5773124163893370921?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/5773124163893370921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=5773124163893370921' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5773124163893370921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/5773124163893370921'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/dot-matrix-printhead-haskell-toy.html' title='The Dot-Matrix Printhead: a Haskell Toy'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4592522237309067731</id><published>2006-12-08T12:31:00.000-05:00</published><updated>2006-12-22T15:13:44.422-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Divisive Aftermath</title><content type='html'>Antti-Juhani pointed out to me that Haskell provides the &lt;span style="font-weight:bold;"&gt;quot&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;rem&lt;/span&gt; pair of operations in addition to &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;mod&lt;/span&gt;. The difference is that while both satisify the identity involving division, multiplication, and the remainder, &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;mod&lt;/span&gt; round down (towards -infinity), while &lt;span style="font-weight:bold;"&gt;quot&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;rem&lt;/span&gt; round towards zero (truncating the fractional part).&lt;br /&gt;&lt;br /&gt;That's great! (Besides the fact that I displayed my ignorance in public, that is). It means I really can use GHCi to model my functions for testing! And I was getting worked up to write a C version of Plauger's &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; which rounded away from zero for negative quotients so I could have some guaranteed-consistent behavior. Instead I can use the C standard function &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and Haskell's &lt;span style="font-weight:bold;"&gt;quot&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;rem&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;So, this sort of begs the question: is there a good reason to prefer one method of integer division rounding to another? Yes. It comes down to this question: do you want your algorithms to behave &lt;span style="font-style:italic;"&gt;smoothly across&lt;/span&gt; the origin, or to behave &lt;span style="font-style:italic;"&gt;symmetrically around&lt;/span&gt; the origin?&lt;br /&gt;&lt;br /&gt;Let's briefly consider some Haskell code for mapping a range of fractions onto a range of integers again.&lt;blockquote&gt;let gen_nths denom = [ (numer, denom::Int) | numer &lt;- [ (-denom::Int)..(denom::Int) ] ]&lt;br&gt;&lt;br&gt;let div_map m1 m2 = map (\ tup -&gt; fst tup * ( ( (m2::Int) - (m1::Int) ) `div` 2 ) `div` snd tup )&lt;br&gt;&lt;br&gt;div_map (-10) 10 ( gen_nths 3 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-10, -7, -4, 0, 3, 6, 10]&lt;/span&gt;&lt;/blockquote&gt;Notice something about those values: the distances between them follow a consistent pattern. Reading the list left to right, we have distances of 3, 3, 4, 3, 3, 4. This pattern repeats. It is &lt;span style="font-style:italic;"&gt;smooth across&lt;/span&gt; the origin.&lt;br /&gt;&lt;br /&gt;Now let's change our &lt;span style="font-weight:bold;"&gt;div_map&lt;/span&gt; function to use &lt;span style="font-weight:bold;"&gt;quot&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;rem&lt;/span&gt;:&lt;blockquote&gt;let quot_map m1 m2 = map ( \tup -&gt; fst tup * ( ( (m2::Int) - (m1::Int) ) `quot` 2) `quot` snd tup )&lt;br&gt;&lt;br&gt;quot_map (-10) 10 ( gen_nths 3 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-10, -6, -3, 0, 3, 6, 10]&lt;/span&gt;&lt;/blockquote&gt;Looking at the differences between values, from left to right, we find that they are 4, 3, 3, 3, 3, 4. The function is &lt;span style="font-style:italic;"&gt;symmetric around&lt;/span&gt; the origin.&lt;br /&gt;&lt;br /&gt;Does this matter in practice? Of course! Let's say that we have a mapping using a non-origin-crossing version of our quot_map function:&lt;blockquote&gt;let gen_non_negative_nths denom = [ (numer, denom::Int) | numer &lt;- (0::Int)..(denom::Int) ] ]&lt;br&gt;&lt;br&gt;let quot_map_2 m1 m2 = map ( \tup -&gt; fst tup * ( (m2::Int) - (m1::Int) ) `quot` snd tup )&lt;br&gt;&lt;br&gt;quot_map_2 0 20 ( gen_non_negative_nths 6 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[0, 3, 6, 10, 13, 16, 20]&lt;/span&gt;&lt;/blockquote&gt;Shiny. The intervals go 3, 3, 4, 3, 3, 4. But if we shift the values:&lt;blockquote&gt;let gen_non_positive_nths denom = [ (numer, denom::Int) | numer &lt;- [ (-denom::Int)..(0::Int) ] ]&lt;br&gt;&lt;br&gt;quot_map_2 0 20 ( gen_non_positive_nths 6 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-20, -16, -13, -10, -6, -3, 0]&lt;/span&gt;&lt;/blockquote&gt;The intervals go 4, 3, 3, 4, 3, 3 -- they are backwards. In other words, the effect of integer rounding on the values of the codomain changes if you shift the domain of the denominator across the origin: the ordering of the pattern is reversed.&lt;br /&gt;&lt;br /&gt;If we do the same thing using div:&lt;blockquote&gt;let div_map_2 m1 m2 = map (\ tup -&gt; fst tup * ( (m2::Int) - (m1::Int) ) `div` snd tup )&lt;br&gt;&lt;br&gt;div_map_2 0 20 ( gen_non_negative_nths 6 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[0, 3, 6, 10, 13, 16, 20]&lt;/span&gt;&lt;br&gt;&lt;br&gt;div_map_2 0 20 ( gen_non_positive_nths 6 )&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-20, -17, -14, -10, -7, -4, 0]&lt;/span&gt;&lt;/blockquote&gt;we get a pattern of intervals (the effect of rounding) which remains the same: 3, 3, 4, 3, 3, 4.&lt;br /&gt;&lt;br /&gt;Now, smoothness across the origin is is what I want, at least for the kinds of functions I am working on now. But your problem domain may lend itself to writing functions which involve rotations, or mapping values across the origin: in that case, you're going to want the symmetry. The important thing is to know what strategy you are using and apply it consistently. I'm really impressed that Haskell give me so many interesting options.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4592522237309067731?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4592522237309067731/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4592522237309067731' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4592522237309067731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4592522237309067731'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/divisive-aftermath.html' title='The Divisive Aftermath'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7349922647502758411</id><published>2006-12-07T19:51:00.001-05:00</published><updated>2008-02-27T10:44:03.015-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Division Bell Tolls for Me, Part Four (Conclusion)</title><content type='html'>Well, this was initially going to be a three-part article, but things have become more interesting. The situation is not unlike picking up a log in the forest and finding all kinds of nifty crawlies living under it. "Interesting" to certain geeky people like myself, at least! It's about to get geekier. If you are allergic to ANSI or ISO standards, you'd better stop reading now. But I claim the payoff is worth it, if you can make it through to the end. At least, for some value of "worth it."&lt;br /&gt;&lt;br /&gt;In the last installment we were exploring the behavior of integer division in Haskell. I want to get back to C now. We learned that the behavior of integer division involving negative results is not strictly defined for C. The behavior of % (mod) is also not very strictly defined.&lt;br /&gt;&lt;br /&gt;Let's start with Kernighan and Ritchie's &lt;span style="font-style:italic;"&gt;The C Programming Language&lt;/span&gt;, Second Edition (I'm not even going to &lt;span style="font-style:italic;"&gt;try&lt;/span&gt; to figure out rules for pre-ANSI/ISO C). K&amp;amp;R tell us on p. 10 that &lt;blockquote&gt;...integer division &lt;span style="font-style:italic;"&gt;truncates&lt;/span&gt;; any fractional part is discarded.&lt;/blockquote&gt;That isn't very detailed, but on p. 41 they tell us &lt;blockquote&gt;the direction of truncation for &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; and the sign of the result for &lt;span style="font-weight:bold;"&gt;%&lt;/span&gt; are machine-dependent for negative operands, as is the action taken on overflow or underflow.&lt;/blockquote&gt; OK, but that doesn't describe exactly what the options are. Things get a little bit more detailed on p. 205, where we read that no guarantees are made about the sign of the remainder!&lt;blockquote&gt;...if the second operand is zero, the result is undefined. Otherwise, it is always true that &lt;span style="font-weight:bold;"&gt;(a/b)*b + a%b&lt;/span&gt; is equal to &lt;span style="font-weight:bold;"&gt;a&lt;/span&gt;. If both operands are non-negative, then the remainder is non-negative and smaller than the divisor; if not, it is guaranteed only that the absolute value of the remainder is smaller than the absolute value of the divisor.&lt;/blockquote&gt; This isn't actually internally consistent, because if the sign of the remainder is not correct, then the identity for division doesn't work for negative values unless the sign of the quotient is allowed to be incorrect! I've never seen it suggested anywhere else that division could be &lt;span style="font-style:italic;"&gt;that&lt;/span&gt; loosely defined. But K&amp;amp;R isn't the formal standard, so let's move on.&lt;br /&gt;&lt;br /&gt;The reason for the "looseness" that exists in the C standard, of course, is that the standard was originally written to, as much as possible, codify existing practice, and C has a strong bias towards efficiency. Since (apparently) different hardware division algorithms had different behavior, the standards committee did not feel that it was appropriate to require existing implementations to change behavior. Doing so might have required existing architectures to have to replace hardware division with software division, which could have inflicted an enormous efficiency cost.&lt;br /&gt;&lt;br /&gt;According to ISO/IEC 9899:1990 (known as C90)&lt;blockquote&gt;When integers are divided and the division is inexact, if both operands are positive the result of the &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; operator is the largest integer less than the algebraic quotient and the result of the &lt;span style="font-weight:bold;"&gt;%&lt;/span&gt; operator is positive. If either operand is negative, whether the result of the &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; operator is the largest integer less than or equal to the algebraic quotient or the smallest integer greater than or equal to the algebraic quotient is implementation-defined, as is the sign of the result of the &lt;span style="font-weight:bold;"&gt;%&lt;/span&gt; operator. If the quotient &lt;span style="font-weight:bold;"&gt;a/b&lt;/span&gt; is representable, the expression &lt;span style="font-weight:bold;"&gt;(a/b)*b + a%b&lt;/span&gt; shall equal &lt;span style="font-weight:bold;"&gt;a&lt;/span&gt;.&lt;/blockquote&gt;So we know that there are two options for rounding. In order to maintain the identity involving integer division and mod, though, the value of mod has to be consistent with the rounding strategy, even if the sign does not have to be consistent.&lt;br /&gt;&lt;br /&gt;There is a back door that lets us get to defined behavior. Apparently the &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; function &lt;span style="font-style:italic;"&gt;does&lt;/span&gt; have strictly defined rounding. In section 7.10.6.2 of the standard, we read:&lt;blockquote&gt;If the division is inexact, the resulting quotient is the integer of lesser magnitude that is the nearest to the algebraic quotient.&lt;/blockquote&gt;That's interesting -- this is rounding towards zero. The &lt;span style="font-weight:bold;"&gt;div &lt;/span&gt;function returns a structure of type &lt;span style="font-weight:bold;"&gt;div_t&lt;/span&gt; that contains both the integer quotient and integer remainder. It is provided in the &amp;lt;stdlib&amp;gt; header, available in C++ as &amp;lt;cstdlib&amp;gt;. In his book &lt;span style="font-style:italic;"&gt;The Standard C Library&lt;/span&gt;, P. J. Plauger provides an implementation for &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt;. It looks like this:&lt;pre&gt;div_t (div)(int numer, int denom)&lt;br /&gt;    {        /* compute int quotient and remainder */&lt;br /&gt;    div_t val;&lt;br /&gt;&lt;br /&gt;    val.quot = numer / denom;&lt;br /&gt;    val.rem = numer - denom * val.quot;&lt;br /&gt;    if (val.quot &amp;lt; 0 &amp;amp;&amp;amp; 0 &amp;lt; val.rem)&lt;br /&gt;        {    /* fix remainder with wrong sign */&lt;br /&gt;        val.quot += 1;&lt;br /&gt;        val.rem -= denom;&lt;br /&gt;        }&lt;br /&gt;    return (val);&lt;br /&gt;    }&lt;/pre&gt;We can see what he is doing: for negative quotients that are inexact answers to the division problem, he shifts the quotients up towards zero and the remainders get reversed. Note that he does not use the built-in &lt;span style="font-weight:bold;"&gt;%&lt;/span&gt; facility, presumably since its behavior does not have very strong guarantees placed on it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;C: A Reference Manual&lt;/span&gt; (5th Edition) by Harbison and Steele seems to indicate that the semantics are a little more rigorously defined. We read there that&lt;blockquote&gt;For integral operands, if the mathematical quotient of the operands is not an exact integer, then the fractional part is discarded (truncation toward zero). Prior to C99, C implementations could choose to truncate toward or away from zero if either of the operands were negative. The &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt; library functions were always well defined for negative operands.&lt;/blockquote&gt;That seems pretty unambiguous, but then on page 419, when describing the &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt; function, the authors write &lt;blockquote&gt;The returned quotient &lt;span style="font-weight:bold;"&gt;quot&lt;/span&gt; is the same as &lt;span style="font-weight:bold;"&gt;n/d&lt;/span&gt;, and the remainder &lt;span style="font-weight:bold;"&gt;rem&lt;/span&gt; is the same as &lt;span style="font-weight:bold;"&gt;n%d&lt;/span&gt;.&lt;/blockquote&gt;But that ignores the possibility of a pre-C99 implementation where &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; rounds away from zero for negative values, as does GHCi in my tests. So again we have a lack of rigorous internal consistency. It is worth noting here that K&amp;amp;R don't make any extra statements about the required rounding behavior of &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt;, and since K&amp;amp;R is still considered the "bible" by many C programmers, the guarantees on the &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt; function may not be very well-known -- or properly implemented.&lt;br /&gt;&lt;br /&gt;Does C99 clarify this at all? ISO/IEC 9899:1999(E), Second Edition 1999-12-01, tells us that "the result of the &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; operator is the algebraic quotient with any fractional part discarded" and a footnote indicating that this is often called "truncation towards zero."&lt;br /&gt;&lt;br /&gt;How about C++? ISO/IEC 14882, Second Edition (2003-10-15) does not actually say how rounding is performed, although it says that "If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined." There is a footnote indicating that "According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard" (rounding towards zero). When we try to look up information about &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt;, we find that the C++ standard just refers us to the Standard C library.&lt;br /&gt;&lt;br /&gt;OK, all the standards language is giving me a headache; let's take a look at some code. To begin with, let's confirm the way my C implementation does rounding of integer quotients. We took a look at 6/5, -6/5, 5/6, and -5/6 in Haskell; let's look at the same quotients in C:&lt;pre&gt;&lt;br /&gt;int val_1 = 6;&lt;br /&gt;int val_2 = 5;&lt;br /&gt;int val_3 = -6;&lt;br /&gt;int val_4 = -5&lt;br /&gt;int result_1 = val_1 / val_2;&lt;br /&gt;int result_2 = val_3 / val_2;&lt;br /&gt;int result_3 = val_2 / val_1;&lt;br /&gt;int result_4 = val_4 / val_1;&lt;br /&gt;printf("result_1 = %d, result_2 = %d, result_3 = %d, result_4 = %d\n", result_1, result_2, result_3, result_4);&lt;/pre&gt;This gives me:&lt;pre&gt;result_1 = 1, result_2 = -1, result_3 = 0, result_4 = 0&lt;/pre&gt;Yep, I'm getting rounding towards zero for both positive and negative values. Next, some Haskell. Let's bring back our algorithm from part 2:&lt;blockquote&gt;let gen_nths denom = [(numer, denom::Int) | numer &amp;lt;- [(-denom::Int)..(denom::Int)] ]&lt;br&gt;&lt;br&gt;let div_map m1 m2 = map (\tup -&gt; (fst tup + snd tup) * (((m2::Int) - (m1::Int)) `div` 2) `div` snd tup + m1)&lt;br&gt;&lt;br&gt;div_map (-10) 10 (gen_nths 3)&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-10,-7,-4,0,3,6,10]&lt;/span&gt;&lt;/blockquote&gt;And now let's write up my C algorithm again. This time we'll use &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; instead of &lt;span style="font-weight:bold;"&gt;long&lt;/span&gt; since we don't need big numbers (although on my target, ints are actually 32 bits long).&lt;pre&gt;unsigned int denom = 3;&lt;br /&gt;int numer;&lt;br /&gt;for ( numer = -3; numer &amp;lt;= 3; numer++ )&lt;br /&gt;{&lt;br /&gt;    int quot = numer * 10 / denom;&lt;br /&gt;    printf("quotient %d\n", quot);&lt;br /&gt;}&lt;/pre&gt;Go ahead and try it on your platform.&lt;br /&gt;&lt;br /&gt;Whoah! What happened? You might have noticed something very odd about the first few quotients. They are monstrously large! On my target I get:&lt;pre&gt;quotient 1431655755&lt;br /&gt;quotient 1431655758&lt;br /&gt;quotient 1431655762&lt;br /&gt;quotient 0&lt;br /&gt;quotient 3&lt;br /&gt;quotient 6&lt;br /&gt;quotient 10&lt;/pre&gt;What happened is that I injected a bug to point out yet another possible way your C code can fail catastrophically. This behavior can surprise even experienced programmers. Note that since my denominator is always a positive value, I declared it as an unsigned int instead of an int. So what went wrong?&lt;br /&gt;&lt;br /&gt;Let's look at the first example: -3/3 yielding 1431655755. The behavior you are looking at is actually mandated by the C standard. When mixing signed and unsigned types, the compiler is required to promote (that is, widen) the actual type of the calculation to an unsigned type. So, internally, if we are performing the calulation -22 (signed) &lt;span style="font-weight:bold;"&gt;/&lt;/span&gt; 7 (unsigned), the compiler is required to notice that both a signed and unsigned long value are presented to the integer division operator. The 32-bit twos-complement representation of -3 is 0xFFFFFFFD (the conversion to an unsigned intermediate value changes the meaning, not the representation). I multiply this value by 10, yielding 0xFFFFFFE2, and then divide it by 3, yielding 0x5555554B, or a decimal value of 1431655755. The compiler treats sticks this unsigned value right into the signed result variable. The signed or unsigned status of the destination variable has absolutely no effect; it does not dissuade the compiler from deciding to treat the values as unsigned. (It is a common misconception to think that the destination value influences the type of the calculation in C).&lt;br /&gt;&lt;br /&gt;If you have a target with 16-bit ints, your rolled-over values will be different (0xFFFD, 0xFFE2, and 0x554B, or decimal 21835). So the mixing of signed and unsigned values has not only given us the wrong answer, but made the code that generates the wrong answer produce inconsistent results depending on the size of int, even when the values we start with are not actually too big to fit into 16 bits.&lt;br /&gt;&lt;br /&gt;If that wasn't perfectly clear, and even if it was, if you are really trying to write portable numeric code in C that has to be correct, I urge to consider purchasing the MISRA (Motor Industry Software Reliability Association) book &lt;span style="font-style:italic;"&gt;MISRA-C:2004, Guidelines for the Use of the C language in Critical Systems&lt;/span&gt;. It has the most detailed explanation of C's arithmetic type conversions, and more importantly, the implications of these type conversions in real code. The crux of the biscuit is that C is hard to get right, even for good programmers.&lt;br /&gt;&lt;br /&gt;OK, so let's change my denominator back to a signed long and try it again. This time the results look more reasonable: -10, -6, -3, 0, 3, and 6.&lt;br /&gt;&lt;br /&gt;Are things any different if we use &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt;?&lt;pre&gt;int denom = 3;&lt;br /&gt;int numer;&lt;br /&gt;for ( numer = -3; numer &amp;lt;= 3; numer++ )&lt;br /&gt;{&lt;br /&gt;    div_t val = div(numer * 10, denom);&lt;br /&gt;    printf("quotient %d\n", val.quot);&lt;br /&gt;}&lt;/pre&gt;In my case, no, since on my compiler and target, / already seems to round towards zero (asymmetrically) while Haskell rounds symmetrically downwards (floor behavior).&lt;br /&gt;&lt;br /&gt;By the way, while we're at it, let's see what C has to say about the "weird" number divided by -1:&lt;pre&gt;long most_negative_long = -2147483648;&lt;br /&gt;long minus_one = -1;&lt;br /&gt;long result = most_negative_long / minus_one;&lt;br /&gt;ldiv_t ldiv_result = ldiv(most_negative_long, minus_one);&lt;br /&gt;printf("results: %lX, %lX\n", result, ldiv_result.quot);&lt;/pre&gt;What do you get? I get zero as the result of both the / and ldiv.&lt;br /&gt;&lt;br /&gt;I also get GCC telling me "warning: this decimal constant is unsigned only in ISO C90." What does &lt;span style="font-style:italic;"&gt;that&lt;/span&gt; mean? The compiler is apparently warning us that in C99 we won't be getting an implicitly unsigned value out of the constant -2147483648, in case we might have wanted to use this constant in an expression involving signed types to force the calculation to be promoted to an unsigned type. But why would we get an unsigned value in the first place? Apparently in C90, the number's magnitude is interpreted first, and the value is negated. 2147483648 is too large (by one) to fit into a signed long, so the compiler promotes the type to an unsigned long, then negates it.&lt;br /&gt;&lt;br /&gt;I have been trying to come up with an example of an expression that behaves differently when I use -2147483648 as a constant, as opposed to 0x80000000, but so far I haven't been able to come up with one. This may be because my compiler is already operating under C99 rules and so I never get the implicit promotion to an unsigned value.&lt;br /&gt;&lt;br /&gt;Anyway, be that as it may, some parting advice and conclusions:&lt;br /&gt;&lt;br /&gt;- GHCi (on the PC and Mac) and C (Visual C++ 6.0 and GCC on the PC and Mac) yield distinctly different rounding behavior for integer division. C90 allows this behavior. Does Haskell? Would it make sense for Haskell to define integer division more strictly, the way that C99 does?&lt;br /&gt;&lt;br /&gt;- Division by zero is never OK; neither is taking &lt;span style="font-weight:bold;"&gt;%&lt;/span&gt; zero. Both are a fatal error in GHCi. The results are undefined in C (but a fatal error is generated by most implementations).&lt;br /&gt;&lt;br /&gt;- Overflow (which, in the case of integer division, occurs only when the "weird number" is divided by -1) produces undefined results, and your code should avoid it, both in Haskell and in C.&lt;br /&gt;&lt;br /&gt;- Operations on unsigned values are guaranteed to produce results that are consistent from platform to platform, assuming the integer size is the same. Operations on signed values don't have this guarantee.&lt;br /&gt;&lt;br /&gt;- The rounding (truncation) of inexact quotients may be either towards zero in all cases, or towards zero for positive quotients and away from zero when the results are negative. If your implementation follows the newer C99 standard rounding should always be towards zero.&lt;br /&gt;&lt;br /&gt;- Mixing signed and unsigned values in C expressions is very dangerous. If you do so, your implementation may have errors far more severe than differences in rounding behavior.&lt;br /&gt;&lt;br /&gt;- Consider avoiding signed division of negative values in C altogether, if your algorithm allows it. Either implement the algorithm using entirely unsigned integral types, or shift the domain of your function so that you are operating on non-negative signed values, and shift it back (using subtraction, which has well-defined semantics) when your division is done.&lt;br /&gt;&lt;br /&gt;- Algorithms which feed a range of values which cross the origin to integer division may vary between GHCi and C implementations. Because GHCi does not provide guaranteed rounding towards zero as C99 and the &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ldiv&lt;/span&gt; functions require, it is difficult to prototype in GHCi and expect to get the same results in C.&lt;br /&gt;&lt;br /&gt;And, finally,&lt;br /&gt;&lt;br /&gt;- Make sure your implementation actually works the way it is supposed to. Only testing can truly accomplish this.&lt;br /&gt;&lt;br /&gt;Interesting, isn't it, how studying one language can enrich your understanding of another! At least, it works for me!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7349922647502758411?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7349922647502758411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7349922647502758411' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7349922647502758411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7349922647502758411'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/division-bell-tolls-for-me-part-four.html' title='The Division Bell Tolls for Me, Part Four (Conclusion)'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-7453959291813412883</id><published>2006-12-07T15:49:00.000-05:00</published><updated>2006-12-08T02:06:27.975-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Division Bell Tolls for Me, Part Three</title><content type='html'>In the last installment, I pointed out a discrepancy between the way that Haskell does integer division and the way that some C code does it. Let's look at just how integer division behaves in Haskell a little more closely. You can type these expressions into GHCi:&lt;pre&gt;6 / 5&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1.2&lt;/span&gt;&lt;br /&gt;5 / 6&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;0.8333333333333334&lt;/span&gt;&lt;br /&gt;(6::Int) `div` (5::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1&lt;/span&gt;&lt;br /&gt;(5::Int) `div` (6::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;0&lt;/span&gt;&lt;/pre&gt;Integer division in the positive numbers always rounds down: 1.2 rounds down to 1, and 0.8333... rounds down to 0. In fact, it looks like the fractional part is just truncated. But let's check some negative values to be sure:&lt;pre&gt;-6 / 5&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-1.2&lt;/span&gt;&lt;br /&gt;(-6::Int) `div` (5::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-2&lt;/span&gt;&lt;br /&gt;-5 / 6&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-0.8333333333333334&lt;/span&gt;&lt;br /&gt;(-5::Int) `div` (-6::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-1&lt;/span&gt;&lt;/pre&gt;That's interesting; clearly it is not strictly truncation (rounding towards zero) that is happening, or else -5/6 would give us zero, not -1. And we clearly aren't getting "rounding" in the usual sense of rounding to the nearest integer (although there is no universal rounding algorithm to round to the nearest integer; there are lots of different variations in practice). &lt;br /&gt;&lt;br /&gt;It looks like we have floor() behavior, which in the case of negative values means rounding away from zero. To state it slightly more rigidly, if the result of the div operation is a whole number, we get the whole number, otherwise we get an integer that represents the exact answer minus the fractional part.&lt;br /&gt;&lt;br /&gt;If you learned integer division the old-fashioned way, on paper, you know what remainders are. The remainder is the leftover part of the process, and represents the numeator of the fractional part of the quotient. In Haskell, &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; gives you the whole number result of integer division, and &lt;span style="font-weight:bold;"&gt;mod&lt;/span&gt; will give you the remainder. So, for example,&lt;pre&gt;(2::Int) `div` (3::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;0&lt;/span&gt;&lt;br /&gt;(2::Int) `mod` (3::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2&lt;/span&gt;&lt;/pre&gt;In fact, what this points to is that there is a relationship between the result of &lt;span style="font-weight:bold;"&gt;div&lt;/span&gt; and the result of &lt;span style="font-weight:bold;"&gt;mod&lt;/span&gt;. It should hold true in all cases, actually; in C, it is part of the ISO standard. The relatioship is this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;For any quotient o = m `div` n where n is not zero, and the remainder p = m `mod` n, o * n + p = m.&lt;/span&gt; In other words, you can reverse the integer division by multiplication as long as you add the remainder back in.&lt;br /&gt;&lt;br /&gt;This relationship should be obviously true for any non-negative n and m. But I'll go further and say that while the exact meaning of mod for negative numbers varies from language to language, and perhaps from implementation to implementation, this relationship should still hold true, with the possible exception of cases involving overflow (which I'll discuss further below).&lt;br /&gt;&lt;br /&gt;We can represent the relationship in Haskell like this:&lt;pre&gt;10 `div` 3&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3&lt;/span&gt;&lt;br /&gt;10 `mod` 3&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1&lt;/span&gt;&lt;br /&gt;let undivide n o p = o * n + p&lt;br /&gt;undivide 3 ( 10 `div` 3 ) ( 10 `mod` 3 )&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;10&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;In fact, let's test it for a few values of n and m:&lt;pre&gt;&lt;br /&gt;let check_divide m n = ( undivide n ( m `div` n ) ( m `mod` n ) ) == m&lt;br /&gt;[ check_divide m n | m &lt;- [(-5::Int)..(5::Int)], n &lt;- [(-5::Int)..(-1::Int)] ]&lt;br /&gt;[ check_divide m n | m &lt;- [(-5::Int)..(5::Int)], n &lt;- [(-5::Int)..(-1::Int)] ]&lt;br /&gt;&lt;/pre&gt;Try out the results for yourself; again, not a rigorous proof, but suggestive.&lt;br /&gt;&lt;br /&gt;But what about the overflow cases? Let's examine them. If Haskell's Int type is a 32-bit signed int, then we should be able to represent the values −2,147,483,648 (corresponding to 10000000000000000000000000000000 in binary or 0x80000000 in hexadecimal), to +2,147,483,647 (corresponding to 01111111111111111111111111111111 in binary or 0x7FFFFFFF in hexadecimal). Let's ask Haskell what happens when we try to exceed our largest positive number:&lt;pre&gt;(2147483647::Int) + (1::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-2147483648&lt;/span&gt;&lt;/pre&gt;Yep, we overflow; we get the largest negative number. Conversely, we can underflow:&lt;pre&gt;(-2147483648::Int) - (1::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2147483647&lt;/span&gt;&lt;/pre&gt;We don't get run-time error checking (and probably don't want it, for the sake of efficiency, when using mahine types). Of course, division by zero is still considered a run-time error:&lt;pre&gt;(2147483648::Int) `div` (0::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;*** Exception: divide by zero&lt;/span&gt;&lt;/pre&gt;What about overflow or underflow in the results of division? With multiplication, it is very easy to overflow; multiplying two large numbers can easily exceed the width of a 32-bit signed value. You can come pretty close with:&lt;pre&gt;(46341::Int) * (46340::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2147441940&lt;/span&gt;&lt;/pre&gt;because 46340 is the next-lowest integer value to the square root of 2,147,483,647. Generate a result just slightly higher and you will roll over to a large negative:&lt;pre&gt;(46341::Int) * (46341::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-2147479015&lt;/span&gt;&lt;/pre&gt;With multiplication there are lots of combinations of values that will overflow, but with division it is a little bit harder to trigger overflow or underflow. There is one way, though. While 2,147,483,647 divided by any lesser value will be a lesser value, and divided by itself will equal one, recall that twos-complement representation gives us a slightly &lt;span style="font-style:italic;"&gt;asymmetric &lt;/span&gt;set of values: the largest representable negative number is one larger, in absolute magnitude, than the largest representable positive value. Thus:&lt;pre&gt;(214483647::Int) `div` (1::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;214483647&lt;/span&gt;&lt;br /&gt;(214483647::Int) `div` (-1::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-214483647&lt;/span&gt;&lt;br /&gt;(-214483648::Int) `div` (1::Int)&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;-214483648&lt;/span&gt;&lt;/pre&gt;In 32 bits of twos-complement, -2,147,483,648 is the "weird number." As a general rule, if you take a twos-complement number, flip all the bits, and add one, you get the negative of that number. The only exception is the weird number. Let's see what happens when we try to divide the weird number by -1:&lt;pre&gt;(-2147483648::Int) `div` (-1::Int)&lt;/pre&gt;Now, I would like to tell you what GHCi says when I ask it to divide the weird number by -1. I'd also like to see what it says about the &lt;span style="font-weight:bold;"&gt;mod&lt;/span&gt;. But I can't. GHCi crashes when I type in those expressions.&lt;br /&gt;&lt;br /&gt;So, I can't tell you what Haskell says. But I can tell you what the C standard says. Here's a hint: not only is it not defined, but in fact the result of any overflow that occurs with arithmetic operations on signed integral types&lt;span style="font-style:italic;"&gt;is not defined&lt;/span&gt; by the language standard. Only the results of arithemtic operations on unsigned integers have defined semantics for overflow, making them portable -- assuming that the size of the type in question is the same. More on that next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-7453959291813412883?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/7453959291813412883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=7453959291813412883' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7453959291813412883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/7453959291813412883'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/division-bell-tolls-for-me-part-three.html' title='The Division Bell Tolls for Me, Part Three'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4049759409356333902</id><published>2006-12-05T18:44:00.000-05:00</published><updated>2006-12-07T18:48:53.629-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Division Bell Tolls for Me, Part Two</title><content type='html'>OK. In our last installment I started talking about using Haskell one-liners to calculate some functions. The function in question was designed to map a set of fractions in the range -7/7 to 7/7 to the machine integers 0..65536. The function itself, along with a wrapper to test, it fits neatly into a Haskell one-liner (well, it might be more than one line, depending on your terminal width). You can use GHCi to evaluate it:&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) * 32768 `div` snd tup) [(numer, 7) | numer &lt;- [(-7::Int)..(7::Int)] ]&lt;/blockquote&gt;I showed in the last installment that this function gave me the results I wanted:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold;"&gt;[0, 4681, 9362, 14043, 18724, 23405, 28086, 32768, 37449, 42130, 46811, 51492, 56173, 60854, 65536]&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;Let's play with that function a little more, and then I want to talk about division (hence the title of the entry). In particular, integer division.&lt;br /&gt;&lt;br /&gt;First, let's simplify our expressions by breaking them down and establishing some bindings. We can also get rid of the presumption that our output range starts at zero:&lt;br /&gt;&lt;blockquote&gt;let gen_nths denom = [(numer, denom::Int) | numer &lt;- [(-denom::Int)..(denom::Int)] ]&lt;br&gt;&lt;br&gt;let div_map m1 m2 = map (\tup -&gt; (fst tup + snd tup) * (((m2::Int) - (m1::Int)) `div` 2) `div` snd tup + m1)&lt;/blockquote&gt;And now we can test it. Note that we need to add a few parentheses:&lt;blockquote&gt;div_map (-32768) 32768 (gen_nths 11)&lt;br&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;[-32768, -29790, -26811, -23832, -20853, -17874, -14895, -11916, -8937, -5958, -2979, 0, 2978, 5957, 8936, 11915, 14894, 17873, 20852, 23831, 26810, 29789, 32768]&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;OK. Now what is it we've done exactly? Well, we've generated some test values, and an algorithm, for distributing a fractional range onto a machine integer range. For our purposes, think of it as a little machine for testing division.&lt;br /&gt;&lt;br /&gt;To see just why I chose this algorithm to play with Haskell, we have to go back and consider some C code. It's quite a headache-inducing paradigm shift to go back to C/C++, but bear with me. Let's just start with the simplest thing: we'll create the same mapping we just generated, hard-coding the values:&lt;blockquote&gt;&lt;pre&gt;long denom = 11;&lt;br /&gt;long numer;&lt;br /&gt;for ( numer = -11; numer &lt;= 11; numer++ )&lt;br /&gt;{&lt;br /&gt;    long val = numer * 32768 / denom;&lt;br /&gt;    printf("%d\n", val);&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;And the results:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;-32768&lt;br /&gt;-29789&lt;br /&gt;-26810&lt;br /&gt;-23831&lt;br /&gt;-20852&lt;br /&gt;-17873&lt;br /&gt;-14894&lt;br /&gt;-11915&lt;br /&gt;-8936&lt;br /&gt;-5957&lt;br /&gt;-2978&lt;br /&gt;0&lt;br /&gt;2978&lt;br /&gt;5957&lt;br /&gt;8936&lt;br /&gt;11915&lt;br /&gt;14894&lt;br /&gt;17873&lt;br /&gt;20852&lt;br /&gt;23831&lt;br /&gt;26810&lt;br /&gt;29789&lt;br /&gt;32768&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Hmmm... wait a minute, let's compare the results:&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;Haskell            C&lt;br /&gt;-32768             same&lt;br /&gt;-29790             -29789&lt;br /&gt;-26811             -26810&lt;br /&gt;-23832             -23831&lt;br /&gt;-20853             -20852&lt;br /&gt;-17874             -17873&lt;br /&gt;-14895             -14894&lt;br /&gt;-11916             -11915&lt;br /&gt;-8937              -8936&lt;br /&gt;-5958              -5957&lt;br /&gt;-2979              -2978&lt;br /&gt;0                  same&lt;br /&gt;2978               same&lt;br /&gt;5957               same&lt;br /&gt;8936               same&lt;br /&gt;11915              same&lt;br /&gt;14894              same&lt;br /&gt;17873              same&lt;br /&gt;20852              same&lt;br /&gt;23831              same&lt;br /&gt;26810              same&lt;br /&gt;29789              same&lt;br /&gt;32768              same&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;It looks like every single one of the negative values is off by one! In our third and final installment I'll dive a little deeper into the semantics of integer division.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4049759409356333902?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4049759409356333902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4049759409356333902' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4049759409356333902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4049759409356333902'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/division-bell-tolls-for-me-part-two.html' title='The Division Bell Tolls for Me, Part Two'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-4534291116920245758</id><published>2006-12-05T15:20:00.000-05:00</published><updated>2006-12-08T14:47:57.157-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>The Division Bell Tolls for Me, Part One</title><content type='html'>With apologies to both Pink Floyd and John Donne.&lt;br /&gt;&lt;br /&gt;I've been toying with Haskell. I wish I had enough free time for a systematic study of Richard Bird's &lt;span style="font-style: italic;"&gt;Introduction to Functional Programming Using Haskell, Second Edition&lt;/span&gt;, but for now I have to content myself with dipping into it in small scraps of free time when both babies are asleep and the dishes are done. In addition, I'm using Haskell to model the behavior of some functions that I'm actually writing in C++.&lt;br /&gt;&lt;br /&gt;One of the reasons I like Haskell is that with a tool like GHCi, which gives me a REPL (a Read, Evaluate, Print loop for interactive development), I can write toy one-liners that do something useful, and since Haskell supports typing, I can test how machine types behave. With an important exception, which I will discuss.&lt;br /&gt;&lt;br /&gt;Let's say I want to try out a function that maps the fractional values -7/7 through 7/7 to unsigned integers in the range 0..65536 (the range of values representable by 16 bits, plus one). In Haskell I can try this out using a one-liner (typed into GHCi). Let's build it up. First, the range of input values. Ignore for now the possibility of using or introducing a true rational number type; instead we'll generate a set of tuples. In Haskell you can express this very concisely using a list comprehension:&lt;br /&gt;&lt;blockquote&gt;[(numer, 7) | numer &lt;- [-7..7] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[(-7,7),(-6,7), (-5,7), (-4,7), (-3,7), (-2,7), (-1,7), (0,7), (1,7), (2,7), (3,7), (4,7), (5,7), (6,7), (7,7)]&lt;/span&gt;&lt;/blockquote&gt;The list comprehension can be (roughly) read as "Make a list of tuples out of numer, 7 where numer takes on the values from the list -7 to 7." Think for a moment about how you could do this in your favorite language.&lt;br /&gt;&lt;br /&gt;Now let's do our math on the resulting list. We can use &lt;span style="font-style: italic;"&gt;map&lt;/span&gt; to apply a function to the list. We can use &lt;span style="font-style: italic;"&gt;fst&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;snd&lt;/span&gt; to get to the values in the tuple; for example, to look at the numerators, do this:&lt;br /&gt;&lt;blockquote&gt;map fst [(numer, 7) | numer &lt;- [-7..7] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]&lt;/span&gt;&lt;/blockquote&gt;Let's go ahead and do our scaling. We want to describe a single function to pass each tuple to; in fact we want a lambda abstraction, a function that we don't bother to name:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; fst tup / snd tup * 65536 ) [(numer, 7) | numer &lt;- [-7..7] ]   &lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[-65536.0, -56173.71428571428, -46811.42857142857, -37449.142857142855, -28086.85714285714, -18724.571428571428, -9362.285714285714, 0.0, 9362.285714285714, 18724.571428571428, 28086.85714285714, 37449.142857142855, 46811.42857142857, 56173.71428571428, 65536.0]&lt;/span&gt;&lt;/blockquote&gt;Whoops, that's not quite right. We want to map to only the positive values. We have to shift the domain (the incoming numerators) so they are non-negative:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) / snd tup * 65536 ) [(numer, 7) | numer &lt;- [-7..7] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[0.0, 9362.285714285714, 18724.571428571428, 28086.85714285714, 37449.142857142855, 46811.42857142857, 56173.71428571428, 65536.0,  74898.28571428571, 84260.57142857143, 93622.85714285714, 102985.14285714286, 112347.42857142857, 121709.71428571429, 131072.0]&lt;/span&gt;&lt;/blockquote&gt;But now the codomain is too big; we have to cut it in half:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) / snd tup * 65536 / 2) [(numer, 7) | numer &lt;- [-7..7]]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[0.0, 4681.142857142857, 9362.285714285714, 14043.42857142857, 18724.571428571428, 23405.714285714286, 28086.85714285714, 32768.0, 37449.142857142855, 42130.28571428572, 46811.42857142857, 51492.57142857143, 56173.71428571428, 60854.857142857145, 65536.0]&lt;/span&gt;&lt;/blockquote&gt;That looks about right. Now let's apply a type. Because I'm eventually going to be implementing this without floating-point, I want the math to be done on machine integers. There are some exceptions, but most target architectures these days give you 32 bits for int, so Haskell's Int, which is defined to be 32 bits, should yield approximately what I want. To introduce typing, all I have to do is add a type to the list values. Type inferencing will do the rest. Oh, and since division by slash is not defined on Int, I have to change it to `div` (infix division):&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) `div` snd tup * 65536 `div` 2) [(numer, (7::Int)) | numer &lt;- [(-7::Int)..(7::Int)] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[0, 0, 0, 0, 0, 0, 0, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 65536]&lt;/span&gt; &lt;/blockquote&gt;Whoah. Something has gone disastrously long. Take a moment to figure out what it is. I'll wait.&lt;br /&gt;&lt;br /&gt;Did you figure it out?&lt;br /&gt;&lt;br /&gt;The problem is that when I use integer division in an expression, the result is truncated (the fractional part is lost). If the division occurs before any of the other operations, most of the significant bits of the math are lost! I can fix this by making sure to do the division last:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) * 65536 `div` snd tup `div` 2) [(numer, (7::Int)) | numer &lt;- [(-7::Int)..(7::Int)] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[0, 4681, 9362, 14043, 18724, 23405, 28086, 32768, 37449, 42130, 46811, 51492, 56173, 60854, 65536]&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;That's better. While I'm at it, I can simplify out that factor of 2 by using half of 65536:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) * 32768 `div` snd tup) [(numer, (7::Int)) | numer &lt;- [(-7::Int)..(7::Int)] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;[0, 4681, 9362, 14043, 18724, 23405, 28086, 32768, 37449, 42130, 46811, 51492, 56173, 60854, 65536]&lt;/span&gt;&lt;/blockquote&gt;In fact, I can ask GHC to verify that the results are the same:&lt;br /&gt;&lt;blockquote&gt;map (\tup -&gt; (fst tup + snd tup) * 65536 `div` snd tup `div` 2) [(numer, (7::Int)) | numer &lt;- [(-7::Int)..(7::Int)] ] == map (\tup -&gt; (fst tup + snd tup) * 32768 `div` snd tup) [(numer, (7::Int)) | numer &lt;- [(-7::Int)..(7::Int)] ]&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;True&lt;/span&gt;&lt;/blockquote&gt;Very cool! Of course, this is not a rigorous proof, but I'm satisfied that my function is correct for the given inputs, and sometimes that's enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-4534291116920245758?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/4534291116920245758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=4534291116920245758' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4534291116920245758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/4534291116920245758'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/12/division-bell-tolls-for-me.html' title='The Division Bell Tolls for Me, Part One'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-1143546443024333129</id><published>2006-11-27T18:45:00.000-05:00</published><updated>2006-11-27T19:41:47.828-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Some Very Basic Haskell and Thoughts on Error Diagnosis</title><content type='html'>So, yesterday I attempted to write a very simple Haskell one-liner. I wanted to use a list comprehension to dump the results of some simple math on a range of numbers. Something like this:&lt;br /&gt;&lt;blockquote&gt;[n / 5 | n &lt;- [0..1024] ]&lt;/blockquote&gt;That's a tremendously concise program. You could read it as follows: "generate a list of n divided by 5 where n is drawn from the enumerated list of numbers 0 to 1024." Type this into GHCi (that's GCH in interactive mode) and it instantly spits out [0.0, 0.2, 0.4 through 204.8].&lt;br /&gt;&lt;br /&gt;That's cool, but the reason I was writing this little program was actually to look at rounding behavior when doing division on hardware-sized integers. The '/' operator is not defined on  the Int type, so if I ask the list comprehension to operate on a list of Int-typed values I understandably get an error:&lt;br /&gt;&lt;blockquote&gt;Prelude&gt; [n / 5 | n &lt;- [(0::Int)..(1024::Int)] ]&lt;br /&gt;&amp;lt;interactive&amp;gt;:1:1:&lt;br /&gt;   No instance for (Fractional Int)&lt;br /&gt;     arising from use of `/' at &lt;interactive&gt;:1:1-5&lt;br /&gt;   Possible fix: add an instance declaration for (Fractional Int)&lt;br /&gt;   In the expression: n / 5&lt;br /&gt;   In the expression: [n / 5 | n &lt;- [(0 :: Int) .. (1024 :: Int)]]     In the definition of `it':         it = [n / 5 | n &lt;- [(0 :: Int) .. (1024 :: Int)]]&lt;/blockquote&gt;GHCi is giving me a lot of context here; that's nice. The message indicates the definition of "it." Apparently "it" is the way GHCi implements a REPL; my expression gets bound to "it" and evaluated. Then it zooms in on what goes wrong. Understanding this error message completely requires an understanding of type classes; I'm not fully up on type classes yet, but it obviously has something to do with type. The suggestion in this case is probably not what I want: I think it is suggesting that I could extend the slash operator to handle integer arguments. That would be a sensible suggestion if I was doing something a little more sophisticated with my own classes. But instead let's try div, which is supposed to do integer division, instead of the slash operator:&lt;br /&gt;&lt;blockquote&gt;Prelude&gt; [n div 5 | n &lt;- [(0::Int)..(1024::Int)] ]&lt;br /&gt;&amp;lt;interactive&amp;gt;:1:1:&lt;br /&gt;   Couldn't match expected type `(a -&gt; a -&gt; a) -&gt; t1 -&gt; t'&lt;br /&gt;          against inferred type `Int'&lt;br /&gt;   In the expression: n div 5&lt;br /&gt;   In the expression: [n div 5 | n &lt;- [(0 :: Int) .. (1024 :: Int)]]     In the definition of `it':         it = [n div 5 | n &lt;- [(0 :: Int) .. (1024 :: Int)]]&lt;/interactive&gt;&lt;/blockquote&gt;Whoah. Now the error message is different, but I'm doing something wrong. Let's see if we can decode it. It says that in "n div 5" it is expecting the type (a -&gt; a -&gt; a) -&gt; t1 -&gt; t. What does that mean?&lt;br /&gt;&lt;br /&gt;I think it means that div takes two values and returns a third, and I'm then trying to apply two arguments to the resulting value. Or something like that. This error message may have everything I need to know; maybe after studying my copy of Bird's &lt;span style="font-style: italic;"&gt;Introduction to Functional Programming Using Haskell&lt;/span&gt;, which should be arriving in the mail any day now, I'll be able to decipher this; but then again, maybe not. Time to do some Googling. Googling complete, with no answer; time to ask for help.&lt;br /&gt;&lt;br /&gt;I got a very quick and helpful reply on fa.haskell. (The newsgroup comp.lang.haskell supposedly has been created, but it doesn't seem to show up in Google Groups yet). The helpful reader suggested that I use `div` (note that those are backticks, not single quotation marks). What this really means is that div in Haskell is a prefix operator, not an infix operator like the slash. It expects its arguments to come afterwards. The magic backticks allow transforming a prefix operator into an infix operator. That works great.&lt;br /&gt;&lt;br /&gt;My larger topic is error messages. Having tried to contribute just a little tiny bit on d2c, the Dylan to C compiler, motivated by stumbling across bugs and places where error messages were a bit weak, I can attest to the following principle. Since I've never heard it expressed anywhere else, I'm going to call it Potts' First Principle of Programming Language Implementation. Here it is:&lt;br /&gt;&lt;blockquote&gt;A compiler implementation will require several times more code to provide a helpful diagnostic message than it does to detect a failure, issue a cryptic message, and exit. The diagnostic-generating code will be complicated, difficult to understand, and inelegant. It is nevertheless worth writing.&lt;br /&gt;&lt;br /&gt;The difference between the ugly implementation which is helpful to the end user and the wonderfully elegant implementation that produces a cryptic failure message is that the former will be adopted and the latter will not.&lt;br /&gt;&lt;br /&gt;Consider writing two methods, one that compiles good code quickly but doesn't give you much help when a failure is detected, and another fully instrumented method that diagnoses the problem in English.&lt;br /&gt;&lt;/blockquote&gt;Having worked with a large number of different tools, I've found that the primary difference between a truly usable tool and one that is not so usable is the quality of the diagnostics.&lt;br /&gt;&lt;br /&gt;A quick example from Dylan: Dylan allows multiple inheritance. Multiple inheritance introduces means that the inheritance graph of a given class can be not just a list but a DAG (a directed acyclic graph). This means that it is possible that you can have a diamond-shaped inheritance graph, in which one or more base classes is included via more than one path. This presents a problem when searching for the next applicable method. The rule, expressed informally, is this: the different &lt;span style="font-style: italic;"&gt;partial orderings&lt;/span&gt; of the inherited classes, from child to parent to nth-generation ancestor, can't contradict each other. You can't have a class which is both a sports car first and a fire truck second, as well as a fire truck first and a sports car second. If you do, you don't know what is going to happen when you try to shift it into gear.&lt;br /&gt;&lt;br /&gt;The d2c compiler complained about this situation with an error message that was, on the positive side, concise. It said "Inconsistent CPL" and quit.&lt;br /&gt;&lt;br /&gt;The code in the compiler that &lt;span style="font-style: italic;"&gt;detected&lt;/span&gt; this condition was a model of elegance. In order for it to &lt;span style="font-style: italic;"&gt;display&lt;/span&gt; a much more detailed message, something like "&lt;span style="font-weight: bold;"&gt;class wonderCar: the partial class precedence list (sportsCar, fireTruck) reached via base class superClassTypeA contradicts the partial class precedence list (fireTruck, sportsCar) reached via base class superClassTypeB,&lt;/span&gt;" some much uglier code has to be inserted, or wrapped around, that model of elegance, to accumulate the information to display to the end user. It's worth writing that method. It could even be implemented as a kind of exception handler when the elegant version fails.&lt;br /&gt;&lt;br /&gt;Diagnostic messages: they're what's for breakfast.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-1143546443024333129?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/1143546443024333129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=1143546443024333129' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1143546443024333129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/1143546443024333129'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/11/some-very-basic-haskell-and-thoughts-on.html' title='Some Very Basic Haskell and Thoughts on Error Diagnosis'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-116181872767090719</id><published>2006-10-25T19:21:00.000-04:00</published><updated>2006-12-05T16:35:56.331-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Exploring Haskell</title><content type='html'>Having gotten somewhat stalled on learning more advanced Scheme programming paradigms, I have decided to try learning Haskell. In particular, I want to use Haskell to get both more lazy and more functional. It is all too easy for me to write Scheme programs which use recursion and lists but are basically translations of the way I would write things in Pascal. I can build my little closures, and do maps and folds, but the programs still evaluate everything, still compute everything, and still use a lot of mutation. My Scheme functions often aren't referentially transparent; they're often really methods to mutate objects.&lt;br /&gt;&lt;br /&gt;It is reasonably legitimate to use Scheme that way, but I'm not learning much. &lt;br /&gt;&lt;br /&gt;In particular I'd love to use something more advanced for my embedded work, but it seems to me that  using Scheme is just going to turn compile-time errors into run-time errors, with its lack of typing, and although my programs might be shorter, they won't really be any more explicit.&lt;br /&gt;&lt;br /&gt;In particular, although I have become reasonably facile with s-expressions and tend to be able to see "past" the parentheses, Haskell confirms my belief that it isn't actually necessary for the programmer to play compiler and write the abstract syntax tree him or herself. There's a little bit of buzz beginning about how Haskell is easier for beginners, and my experience with Dylan leads me to believe that typing is actually valuable; in Dylan, for example, it can make a difference between code that uses full runtime dispatch and takes twenty minutes to run, or a version that takes a few seconds.&lt;br /&gt;&lt;br /&gt;I'd also like to better understand the lazy paradigm, where a very large or infinite list or tree does not have to be fully generated or fully evaluated in order to be useful. I'd like to understand Monads, or at least how to use them.&lt;br /&gt;&lt;br /&gt;A lot of my programming work involves explicit or implicit state machines and plumbing to manage state changes. To improve this I really just need something a lot more concise and expressive than C++. I need leverage, not totally new programming paradigms, at least not at first. So we'll see if Haskell can help me there.&lt;br /&gt;&lt;br /&gt;I've been faintly interested in learning languages like Clean, or ML, or Miranda, or Ocaml. But so far what I'm reading leads me to think that it may not be worth my time to bother with these and that Haskell has absorbed a lot of the things that are cool about these languages and may, in fact, be the shit. A large amount of material is being written about Haskell, and the stable base/experimental extensions approach seems like the right thing. In other words, Haskell seems like a language upon which a lot of smart people are converging.&lt;br /&gt;&lt;br /&gt;And if it isn't, maybe I can take some of what I learned using it back to Scheme, or maybe Kernel. &lt;br /&gt;&lt;br /&gt;More to come!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-116181872767090719?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/116181872767090719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=116181872767090719' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/116181872767090719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/116181872767090719'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/10/exploring-haskell.html' title='Exploring Haskell'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-115705213165445117</id><published>2006-08-31T13:14:00.001-04:00</published><updated>2010-03-18T13:33:05.877-04:00</updated><title type='text'>Generic Functions and Pointers to Member Functions</title><content type='html'>People who know me know that I still carry a torch for a wonderfully-designed but little-used programming language called &lt;span style="font-style:italic;"&gt;Dylan&lt;/span&gt;. In my arrogant opinion Dylan took much of the best of Common Lisp and CLOS, regularized and streamlined it, and gave it a syntax more acceptable (due to familiarity) to programmers from the C and C++ world (although this annoyed some prefix syntax fans in the process). Dylan is a multi-paradigm language, where "everything is an object," designed to support functional styles, object-oriented styles, and procedural styles.&lt;br /&gt;&lt;br /&gt;Dylan is still alive and kicking with several impressive implementations available &lt;a href="http://opendylan.org"&gt;here&lt;/a&gt; including &lt;span style="font-weight:bold;"&gt;d2c&lt;/span&gt;, an amazing compiler that generates C code from Dylan source, and which is written primarily in Dylan itself, and the formerly commercial Functional Objects compiler, which generates native machine code. I have not studied the Functional Objects codebase very much, but I have spent time with &lt;span style="font-weight:bold;"&gt;d2c&lt;/span&gt;. It is an amazing piece of code. Studying it makes me wish I was able to strap on an auxilliary brain or two and take a pill that gave me a post-graduate education in language implementation without all that tedious mucking about in graduate school, so I could contribute something &lt;span style="font-style:italic;"&gt;useful&lt;/span&gt; to the project instead of just an occasional bug report or ignorant question.&lt;br /&gt;&lt;br /&gt;In Dylan, and in Dylan's sire Common Lisp with CLOS, classes contain &lt;span style="font-style:italic;"&gt;data&lt;/span&gt;. Classes don't contain methods. Methods are implemented using a construct known as a &lt;span style="font-style:italic;"&gt;generic function&lt;/span&gt;. A generic function lets you define several &lt;span style="font-style:italic;"&gt;specialized&lt;/span&gt; functions to operate on objects of different classes. A variety of functions with the same name are bundled together; as you define additional functions, they get added to the generic function. At run-time, when you make a call to the generic function, the &lt;span style="font-style:italic;"&gt;specific&lt;/span&gt; function chosen can depend on the &lt;span style="font-style:italic;"&gt;actual&lt;/span&gt; run-time type (the class) of the object you send to it. Classes can inherit from one or more other classes; this inheritance tree is used to make the decision about which actual method to call for a given object. Generic functions can be specialized in other ways; they are extraordinarily flexible and powerful. But I'm only going to touch today on generic function dispatch specialized on the class of the incoming object, incoming parameters, and return type.&lt;br /&gt;&lt;br /&gt;In his article "A First Look at Dylan: Classes, Functions, and Modules," Steve Strassmann &lt;a href="http://devworld.apple.com/dev/techsupport/develop/issue21/21strassman.html"&gt;writes&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Object-oriented languages, including Dylan, provide polymorphic functions, which means a given function may be executed as one of several possible implementations of that function, called methods... when Dylan sees a call to name(x), depending on what type of object is, one of several methods is selected and executed. In Dylan, name is called a generic function, consisting of a family of name methods that implement the functionality of name for various classes (see Figure 2). Each of these methods "belongs to" its generic function (in this case, name) rather than to a class. This is a key point; it's the core difference between C++'s object model and Dylan's.&lt;/blockquote&gt;In terms of implementation, this means that when you make a generic function call, the generic function isn't a "standard" function; a dispatch mechanism comes into play to select the proper generic function based on the call's arguments. The run-time context contained in the object is &lt;span style="font-style:italic;"&gt;explicitly&lt;/span&gt; passed to the function.&lt;br /&gt;&lt;br /&gt;Strassmann gives examples generic function; I have stripped down one of his examples somewhat here:&lt;br /&gt;&lt;pre&gt;// No type declaration, works on any type of object&lt;br /&gt;define method double (x)&lt;br /&gt;   pair(x, x);&lt;br /&gt;end method double;&lt;br /&gt;&lt;br /&gt;// Works on all numbers&lt;br /&gt;define method double (x :: &amp;lt;number&amp;gt;)&lt;br /&gt;   2 * x;&lt;br /&gt;end method double;&lt;br /&gt;&lt;br /&gt;// Works on all strings&lt;br /&gt;define method double (x :: &amp;lt;string&amp;gt;)&lt;br /&gt;   concatenate(x, x);&lt;br /&gt;end method double;&lt;/pre&gt;&lt;blockquote&gt;When double is invoked on an argument, the most specific method is invoked... for example, double("foo") would invoke the third method, because &amp;lt;string&amp;gt; is more specific than &amp;lt;object&amp;gt;, which is what the first method is specialized to. If no match is found, Dylan will catch it and signal an error.&lt;/blockquote&gt;Besides a plethora of different ways to specialize generic functions, Dylan supplies various forms of &lt;span style="font-style:italic;"&gt;introspection&lt;/span&gt;; if you want to extend or alter the run-time dispatch, you can do so.&lt;br /&gt;&lt;br /&gt;To C++ programmers, this is inside-out. In C++, classes "contain" methods, known more commonly as "member functions" because they are "members" of the class. C++ supports polymorphism and dispatch based on run-time type. I'm going to talk a little bit about how objects and member functions work together in C++ and how you can use them, and how, when we look at C++ in light of Dylan or CLOS, C++ actually gives us a &lt;span style="font-style:italic;"&gt;subset&lt;/span&gt; of object dispatch, presented in an &lt;span style="font-style:italic;"&gt;obfuscated&lt;/span&gt; form.&lt;br /&gt;&lt;br /&gt;Let's say you don't want to just make a new subclass with specialized methods and allow polymorphic dispatch to operate based on run-time type, but instead you want to handle your own run-time dispatch. In Dylan you can do this using introspection and some handlers that allow you to override the standard generic function dispatch. Since you have the object and the generic function and can get at specific functions, you can just call them, passing the object.&lt;br /&gt;&lt;br /&gt;To do the same thing in C++ you need to work around the fact that C++ obfuscates what is actually going on when you call a method. You can do this by using a slightly obscure C++ construct called the &lt;span style="font-style:italic;"&gt;pointer to member&lt;/span&gt;. For the present discussion the member in question will always be a member function, but keep in mind that pointers to members can work with data members as well. This use is probably even less common since if you have an object, or a pointer or reference to an object you can access public members directly as you would access members of a struct, or via an accessor function; I would think that pointers to data members are necessary only for serious runtime hacking or compiler implementation. But the key point here is that C++ pretends that both data members and member functions are part of classes, while CLOS and Dylan much more explicitly separate these concepts.&lt;br /&gt;&lt;br /&gt;Pointers to member functions are uncommonly used, probably in part because of its somewhat obscure syntax. The only place I've seen them used, in fact, is the Darwin kernel's IOKit source code. Recently I've had a need to customize class behaviors at runtime without subclassing and without a complete refactoring of a class into modular pieces, so I've been investigating the construct again.&lt;br /&gt;&lt;br /&gt;The syntax is awkward, but it is consistent with the general C school of thought which says that declarations are read backwards (right to left). In C, if you have an integer variable:&lt;br /&gt;&lt;pre&gt;int i;&lt;/pre&gt;to make a pointer out of it, you insert an asterisk to the left of the variable name:&lt;br /&gt;&lt;pre&gt;int * i;&lt;/pre&gt;Similarly, if you have a prototype for a function returning &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; and taking an &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; parameter:&lt;br /&gt;&lt;pre&gt;int fn ( int );&lt;/pre&gt;to take a pointer to it, you insert an asterisk to the left of the name:&lt;br /&gt;&lt;pre&gt;int * fn ( int );&lt;/pre&gt;but the order of evaluation means that the parser reads it as a function returning a pointer to &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt;. So you have to change the order of evaluation using parentheses:&lt;br /&gt;&lt;pre&gt;int ( *fn ) ( int );&lt;/pre&gt;Now fn means a pointer to a function, not a function returning a pointer.&lt;br /&gt;&lt;br /&gt;A member function is basically the same, with the addition of the class name and the scope resolution operator (::). When you are declaring your class, this prefix is not wanted or needed (it is implicit within the class declaration's curly braces), but when you define your methods, you do so like this:&lt;br /&gt;&lt;pre&gt;int my_class::my_member_func( int )&lt;br /&gt;{&lt;br /&gt;   /* function body */&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-style:italic;"&gt;Another aside: the separation between the class declaration and class definition is just one of the speed bumps you have to live with when using C++; it is there to support separate compilation, but if you've ever made the switch from C++ to Java you know that giving up the need to keep header files and implementation files in perfect synchronization gives you an immediate productivity boost.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If we want to make a variable that can point to that member function, we put an asterisk to the left of the name:&lt;br /&gt;&lt;pre&gt;int my_class::*my_member_func_ptr( int );&lt;/pre&gt;The precedence rules get confused by this (during parsing, it probably looks like a collision between a definition of a member function and a conventional function returning a pointer with no type attached, or some such nonsense), so again we have to use parentheses:&lt;br /&gt;&lt;pre&gt;int ( my_class::*my_member_func_ptr )( int );&lt;/pre&gt;and this gives us a variable, &lt;span style="font-weight:bold;"&gt;my_member_func_ptr&lt;/span&gt;, which can hold a pointer to a member function with the signature "returns &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; and takes one &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; parameter." Note that the parameter list, as in a function prototype or member function declaration, only requires the types of the parameters and not the names, although you can supply names for documentation purposes if you want.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;An aside: it would be easy to ridicule this syntax, but ridiculing the syntax of C++ is kind of like shooting fish in a barrel. I've shown that the syntax is at least somewhat consistent with the other C++ syntactical forms. Because of that, this particular syntax doesn't really bother me; if I can't remember it off the top of my head, I can mentally follow this derivation path and reason it out. This isn't necessarily true of a lot of other pieces of C++ syntax which do bother me and which I'm quite happy to rant about; see my piece on &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A pointer to member function does not have a standard implementation; the implementation (size, etc.) may differ between implementations; you should probably treat it as an opaque data structure and make no assumptions about what it actually looks like inside, unless you want to write very non-portable code. There's nothing in the standard that says that pointers to member functions have to be the same size, for example, and the standard specifically says they are _not_ just specially typed pointers; they are not convertible to and from &lt;span style="font-weight:bold;"&gt;void*&lt;/span&gt; by casting, as other pointer types are, using either the old-style or new-style casts.&lt;br /&gt;&lt;br /&gt;This is because pointer to member function is not a usable &lt;span style="font-style:italic;"&gt;pointer&lt;/span&gt; by itself; instead it contains whatever extra information is needed to represent a specific member function for a given class, probably an index or offset of some sort. You can imagine that the compiler needs a mechanism like this for its own use, so that it can turn&lt;br /&gt;&lt;pre&gt;object.member_function(...)&lt;/pre&gt;or&lt;br /&gt;&lt;pre&gt;object_pointer-&gt;member_function(...)&lt;/pre&gt;into C-style function calls with the addition of a hidden parameter:&lt;br /&gt;&lt;pre&gt;looked_up_member_function( this, ... )&lt;/pre&gt;Remember our discussion on generic function dispatch? You might notice that when you rewrite the code to explicitly pass in the contest (the "this"), it starts to look like Dylan (or, ignoring the difference between infix and prefix notation, CLOS). You can actually think of the C++ object model as a much more limited and &lt;span style="font-style:italic;"&gt;obfuscated&lt;/span&gt; form of CLOS generic function dispatch. How weird is that?&lt;br /&gt;&lt;br /&gt;The "this" pointer allows the function body access to the specific object instance variables, and can also be passed on to any subsidiary member function calls on the same object. In Dylan or CLOS you would access the data members (in slots) of the incoming object &lt;span style="font-style:italic;"&gt;explicitly&lt;/span&gt;; C++ gives you access to the data members and member functions of "this" implicitly, although you can still use this-&gt; as a prefix if you want to make very clear what you are doing, or protect against accidentally accessing something global or local in the member function's namespace that might inadvertently shadow a member. This merging of namespaces is another rich source of potential errors (remember my comment about how C++ is like &lt;span style="font-style:italic;"&gt;obfuscated&lt;/span&gt; Dylan?)&lt;br /&gt;&lt;br /&gt;Note that our pointer to member function is not defined to refer to &lt;span style="font-style:italic;"&gt;a&lt;/span&gt; member function in the given class. It can have assigned to it &lt;span style="font-style:italic;"&gt;any&lt;/span&gt; member function that is part of the class (or a derived class), and that has the same &lt;span style="font-style:italic;"&gt;signature&lt;/span&gt; (that is, matching return type and parameter types). This, as you might imagine, allows the compiler to do dynamic dispatch based on runtime type; you can do the same thing, based on any criteria you choose.&lt;br /&gt;&lt;br /&gt;Note also that the variable you've created is &lt;span style="font-style:italic;"&gt;not yet initialized&lt;/span&gt;. There's that obfuscation again! In a language where everything is done by reference, that isn't even quite possible; your reference will wind up referring to &lt;span style="font-style:italic;"&gt;something&lt;/span&gt;. But pointers enable whole new classes of errors, and there is unfortunately no such thing as a "reference to member function" in C++. Be careful to make certain you initialize it before use, preferably at the point the variable is defined! Not doing so will cause you severe tire damage!&lt;br /&gt;&lt;br /&gt;And, in fact, the compiler may not help you avoid this. I tested GCC by writing a call to an uninitialized regular function pointer:&lt;br /&gt;&lt;pre&gt;void ( *fptr ) ( void );&lt;br /&gt;fptr();&lt;/pre&gt;and it generated a helpful warning for this case. When I wrote a similar call using an uninitialized pointer to a member function, like so:&lt;br /&gt;&lt;pre&gt;void ( Class_c::*mptr ) ( void );&lt;br /&gt;( this-&gt;*mptr ) ();&lt;/pre&gt;GCC produced no warning at all, and as you might expect, the call caused an immediate crash. This is the likely outcome, but according to the C++ standard the behavior is &lt;span style="font-style:italic;"&gt;undefined&lt;/span&gt; (this is very bad; it means the program is not required by the standard to catch this as an error; it is free to silently fail in some insidious way, or destroy your hard drive, or electrify your keyboard). &lt;br /&gt;&lt;br /&gt;You can initialize them to zero, the &lt;span style="font-style:italic;"&gt;null pointer constant&lt;/span&gt; (there is an explicitly allowed conversion), but the results of calling a null pointer to member function are &lt;span style="font-style:italic;"&gt;also&lt;/span&gt; undefined, so this doesn't buy you anything; you are better off initializing them at the point where they are defined. Here is an example of how to do so:&lt;br /&gt;&lt;pre&gt;void ( my_class::*mp ) ( void ) = &amp;amp;my_class::member_function;&lt;/pre&gt;Since pointers to member functions are hard to read, especially for member functions that that accept a long list of parameters, it is valuable to make the construct into a type using &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt;. I recommend using the naming convention&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;class name + the _kind_ of member func + "_pm_t"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But follow your own convention, or your team's convention, if you like. Keep in mind that the type can be used to represent &lt;span style="font-style:italic;"&gt;any&lt;/span&gt; member function of the class (or a derived class) that matches the signature. The member function will probably represent a &lt;span style="font-style:italic;"&gt;handler&lt;/span&gt; of some kind, or in design pattern terms a specific &lt;span style="font-style:italic;"&gt;strategy&lt;/span&gt;. Describe what it handles, or what the strategies are trying to accomplish.&lt;br /&gt;&lt;br /&gt;When you write the &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt;, keep in mind that it looks just like the variable definition, except that the type name replaces the variable name and you put &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt; in front. To define a type called &lt;span style="font-weight:bold;"&gt;my_class_SomethingHandler_pm_t&lt;/span&gt;, use the form:&lt;br /&gt;&lt;pre&gt;typedef int ( my_class::*my_class_SomethingHandler_pm_t ) ( int );&lt;/pre&gt;Once you have a type, the following definition creates a variable with the new type and initializes it with a specific member function:&lt;br /&gt;&lt;pre&gt;my_class_SomethingHandler_pm_t pm = &amp;amp;my_class::my_member_func;&lt;/pre&gt;This assignment can also take place in &lt;span style="font-style:italic;"&gt;parameter binding&lt;/span&gt;. This means you can write a standalone function, member function, or static member function that accepts any pointer to member function matching the specified signature, and then pass it a specific one at run-time.&lt;br /&gt;&lt;br /&gt;Once you have a pointer to member function, you can call that member function, but to do this you need an &lt;span style="font-style:italic;"&gt;object&lt;/span&gt; (the "this" that will be in effect for the duration of the call). If you have a &lt;span style="font-style:italic;"&gt;pointer&lt;/span&gt; to the object (which could be "this"), use &lt;br /&gt;the syntax:&lt;br /&gt;&lt;pre&gt;( object_ptr-&gt;*mp )( params );&lt;/pre&gt;If you have a local or global variable holding an object or a &lt;span style="font-style:italic;"&gt;reference&lt;/span&gt; to an object, use the syntax:&lt;br /&gt;&lt;pre&gt;( object.*mp ) ( params );&lt;/pre&gt;Note that the parentheses around the first part are mandatory, to help the parser. If your object pointer or pointer to member function is stored in a structure or you are accessing it via pointer you will probably have to introduce more parentheses to make sure the parts of the expression are evaluated in the right order. This kind of construct can get ugly fast, so be careful.&lt;br /&gt;&lt;br /&gt;In his C++ FAQ Lite section on pointers to member functions available &lt;a href="http://www.parashift.com/c++-faq-lite/pointers-to-members.html"&gt;here&lt;/a&gt; Marshall Cline suggest that when making calls using pointers to member functions, you always define a calling macro like this:&lt;br /&gt;&lt;pre&gt;#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))&lt;/pre&gt;and then do the call like this:&lt;br /&gt;&lt;pre&gt;result = CALL_MEMBER_FN(PO,PM)( PL );&lt;/pre&gt;but I wouldn't necessarily recommend that; C-style macros are still quite evil, and can make it very hard to find out what the compiler is complaining about, or even what it actually compiled that you didn't intend.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-115705213165445117?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/115705213165445117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=115705213165445117' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115705213165445117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115705213165445117'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/08/generic-functions-and-pointers-to.html' title='Generic Functions and Pointers to Member Functions'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-115696234657667165</id><published>2006-08-30T13:30:00.001-04:00</published><updated>2010-03-18T12:24:46.471-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='Kernel'/><title type='text'>The Kernel Programming Language and the Quest for Simplicity</title><content type='html'>I've been reading with considerable interest about the Kernel programming language under development by John Shutt. Information and a PDF file are available &lt;a href="http://web.cs.wpi.edu/~jshutt/kernel.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I am not sure I fully understand the implications and details of his $vau and $wrap constructions, but I strongly support his goals, and the rest of his report kept me, literally, awake half the night reading it. Shutt writes:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;...the mandate of the Kernel language is to have a clean design, flowing from a broad design philosophy as refined by a series of more specific design guidelines --- just one of which is that all manipulable entities should be first-class.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;He is trying to create a Scheme-like language which is even more uniform, predictable, and configurable than R5RS Scheme.&lt;br /&gt;&lt;br /&gt;I don't have a Ph.D. in the programming language field, so bear with me if my terminology is a little vague. It seems that the &lt;span style="font-style:italic;"&gt;big thing&lt;/span&gt; Shutt is attempting is to give fine-grained control over evaluation, essentially separating out the parameter-evaluation stage of a lambda call into a distinct and fully configurable stage. This means you can do more clever things with objects without evaluating them. I think it also points you towards macro-like constructions that don't lead off into the existing slightly swampy maze of different Scheme macro implementations. It also could be a more explicit and flexible means of handling the need for quoting.&lt;br /&gt;&lt;br /&gt;On top of that he is also doing a number of &lt;span style="font-style:italic;"&gt;slightly smaller&lt;/span&gt; things (on the scale of theoretical complexity), but which I think are great.&lt;br /&gt;&lt;br /&gt;For instance, Shutt has in his design very explicit rules for what to do with cyclic structures, a.k.a. infinite lists. While in some situations creating these would be considered an error, in others they make perfect sense: for example, in creating trees that describe recursive-descent parsing. Therefore, giving a sensible semantics to handling cyclic structures is a sensible and intriguing thing to do. If you want to write functions which aren't willing to handle cyclic structures, you can use one of his predicates to check for that possibility.&lt;br /&gt;&lt;br /&gt;He also has addressed a number of minor irritants which don't require a deep understanding of the lambda calculus to appreciate. For instance, he proposes that boolean evaluation should never be implicit: that is, if you want to evaluate something as a boolean value, you have to use a predicate on it to &lt;span style="font-style:italic;"&gt;generate&lt;/span&gt; a boolean value, and compare it to &lt;span style="font-weight:bold;"&gt;true&lt;/span&gt; or &lt;span style="font-weight:bold;"&gt;false&lt;/span&gt;. In other words, no more "anything not explicitly false is not true" or "false is false, and nil is false, but anything else is true, and true is true" or other bizarre variant on this theme.&lt;br /&gt;&lt;br /&gt;As someone who switches languages a lot, I have always tried to make my boolean evaluations absolutely explicit to avoid the potential confusion that implicit evaluation can bring. For example, I always write (pedantically) in C++:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;if ( false == stack.full() ) {&lt;br /&gt;   push()...&lt;br /&gt;}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In addition, he has addressed the question "if everything in Scheme has a value, what is the value of a control structure?" To make this explicit he proposes an immutable value called &lt;span style="font-weight:bold;"&gt;inert&lt;/span&gt;, somewhat analagous to &lt;span style="font-weight:bold;"&gt;void&lt;/span&gt; in C/C++, and which is an explicit type and which even has explict external representation.&lt;br /&gt;&lt;br /&gt;There's lots more great stuff in Shutt's draft report and it addresses many of the weaknesses that make Scheme implementations so maddeningly inconsistent. Read it, study it, live it. I am looking forward to Shutt's doctoral thesis and I hope that there is one day very soon a freely available implementation of Kernel to try out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-115696234657667165?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/115696234657667165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=115696234657667165' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115696234657667165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115696234657667165'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/08/kernel-programming-language-and-quest.html' title='The Kernel Programming Language and the Quest for Simplicity'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-115585847487898026</id><published>2006-08-17T19:47:00.003-04:00</published><updated>2010-03-18T13:22:23.123-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>A Rant about Const</title><content type='html'>WARNING: THE FOLLOWING MAY CAUSE BRAIN DAMAGE&lt;br /&gt;&lt;br /&gt;This is an unfinished essay that sat in draft form in my bog, unpublished, for several years. It seems very unfinished, but I decided to go ahead and publish it anyway. I'm not sure it actually makes any damned sense; it certainly needs some revision. There may indeed be a point buried in here somewhere, if only I can determine what it is!&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;I looked this up in the comp.lang.c++ newsgroups. What I keep reading is that returning a const value, when the value is int or float or some other plain built-in data type, as opposed to a class type, is not "meaningful."&lt;br /&gt;&lt;br /&gt;Either I'm too dumb to understand this argument or the argument isn't actually coherent, it is just widely propagated because everyone mistakes the existing C/C++ runtime behavior for a sensible model of language semantics, which it isn't.&lt;br /&gt;&lt;br /&gt;What they seem to be actually saying is "according to the language standard, C++ is not allowed to enforce meaningful const semantics on return types that are not reference or pointer types. And pointer types are hopelessly unsafe. But references can be pretty unsafe too."&lt;br /&gt;&lt;br /&gt;There was a thread about this on comp.lang.c++, specifically about why you can't return a const int. One of the comments was:&lt;br /&gt;&lt;br /&gt;"A value returned by a function is a rvalue, unless it is a reference.&lt;br /&gt;The notion of being (or not being) const-qualified is not applicable to&lt;br /&gt;rvalues of non-class types ('int' in your case). A rvalue cannot be modified just because it is a rvlaue. That's it. It doesn't make any difference whether you const-qualify it or not. That's what your compiler is trying to tell you."&lt;br /&gt;&lt;br /&gt;http://groups.google.com/group/comp.lang.c++/browse_thread/thread/4e50f8abf9c11f71/6039d5b2e6612df0%236039d5b2e6612df0&lt;br /&gt;&lt;br /&gt;As far as I can tell, the C++ standard specifies this because of the way returning values from functions has usually been _implemented_ in C/C++ (by copying on the stack). So the caller isn't _actually_ getting the "same" object or integer value, and in fact the original will be gone.&lt;br /&gt;&lt;br /&gt;What this means is actually that you can freely change the return value:&lt;br /&gt;&lt;br /&gt;int y = f(x);&lt;br /&gt;y = y + 1;&lt;br /&gt;&lt;br /&gt;But this is not actually "changing the rvalue" because the rvalue was actually copied into y; you're just changing a copy. So the statement above is correct in that the rvalue "cannot be modified." (It means that only indirectly).&lt;br /&gt;&lt;br /&gt;In cases even when the compiler puts the return values in registers, or wherever, the standard rules about lvalues and rvalues still apply, for sanity and safety and consistency.&lt;br /&gt;&lt;br /&gt;But it is not what I want to _express_ when I use const with a return value.&lt;br /&gt;&lt;br /&gt;In the methods that generated warnings, I was using const return values to mean:&lt;br /&gt;&lt;br /&gt;Case 1: what I'm returning is the result of a mathematical function call: f(x) is always y for the given x, so it wouldn't make sense for you to _change_ the value I'm returning to you. If my function f is f(x) = 1 + x, then f(1) = 2. It doesn't make any sense to then say f(1) = 3 later.&lt;br /&gt;&lt;br /&gt;Case 2: what I'm returning is the result of an iterator and represents the state of another object at a given moment in the life of the program. Therefore, you shouldn't change _the value itself_; if you want to update it, call the iterator to get a new updated value. I say iterator_state = iterator:GetNextValue() and get iterator_state back; it doesn't make any sense to say iterator_state = iterator_state + 1 without calling the method.&lt;br /&gt;&lt;br /&gt;I ought to be able to _say_ that the caller should not update the object I'm returning, whether "returning" means binding it via a pointer, a reference (hidden pointer), _or_ by copying the rvalue.&lt;br /&gt;&lt;br /&gt;If it is a const u32_t I'm returning, the compiler should insist that the value be assigned only to a const u32_t. (It doesn't). &lt;br /&gt;&lt;br /&gt;If I'm returning a const object, the compiler should enforce assigning it to a const variable. (It doesn't, but at least it doesn't generate the warning in those cases). This is because returning an _object_ on the stack does not constitute returning an "rvalue."&lt;br /&gt;&lt;br /&gt;This is, as far as I can tell, a completely arbitrary distinction, with the sole exception that copying an object gets to invoke the copy constructor (default or provided) where copying a built-in type just does it for you.&lt;br /&gt;&lt;br /&gt;In a similar thread Greg Comeau wrote:&lt;br /&gt;&lt;br /&gt;"Also, returning a const T, where T IS NOT A BUILTIN TYPE many not be meaningless, because you may end up calling member functions on that object, and the member function may need to be a const member function."&lt;br /&gt;&lt;br /&gt;It is "meaningful" in the sense that you may want to put the returned object into a const variable to _prevent_ calling any non-const member functions. But Greg phrased it backwards. You can always call const member functions on non-const objects. He should have said "you may end up calling member functions on that object, and you might want to prevent the calling of non-const member functions."&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;static AZMMultiZoneRef_c const MakeFromZonesBitmap( u32_t zones_bmp );&lt;br /&gt;&lt;br /&gt;const AZMMultiZoneRef_c zones_ref = AZMMultiZoneRef_c::MakeFromZonesBitmap( p_data-&gt;zones_bitmap );&lt;br /&gt;&lt;br /&gt;u32_t AZMMultiZoneRef_c::MutateMe( void_t );&lt;br /&gt;&lt;br /&gt;zones_ref.MutateMe();&lt;br /&gt;&lt;br /&gt;The compiler will (rightly) complain about this. But it will not complain about calling const member functions on a non-const object.&lt;br /&gt;&lt;br /&gt;The intent is that you should not be able to mutate an object that is const, except using the "mutable" workaround to allow hidden state changes.&lt;br /&gt;&lt;br /&gt;However, the rules for returned objects let us completely get around this! If I don't like that restriction, I can just assign the return value to a non-const object. So this is legal:&lt;br /&gt;&lt;br /&gt;AZMMultiZoneRef_c zones_ref = AZMMultiZoneRef_c::MakeFromZonesBitmap( p_data-&gt;zones_bitmap );&lt;br /&gt;&lt;br /&gt;zones_ref_2.MutateMe();&lt;br /&gt;&lt;br /&gt;Not much of a restriction, then, is it?&lt;br /&gt;&lt;br /&gt;OK, so let's say we're more serious about enforcing const. So, we'll use a pointer or reference instead, because that will maintain the const enforcement restrictions, right? BUT... the semantics are actually quite different, and there is a serious safety hole introduced:&lt;br /&gt;&lt;br /&gt;"When returning references, a reference bound to the return value is not valid after object deletion; when returning values, a reference bound to the return value is valid after object deletion."&lt;br /&gt;&lt;br /&gt;And, of course, if what you are returning a pointer or reference to is a an object in a _local_ variable, that is a seriously broken program right there. So it is kind of a "damned if I do, damned if I don't" situation.&lt;br /&gt;&lt;br /&gt;C++ is actively hostile to functional programming. In fact, the "safety features" of the language can't even be used consistently. And with this compiler, when you try to express what you mean (taken as a given that the compiler won't enforce it), it treats it as a warning!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-115585847487898026?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/115585847487898026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=115585847487898026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115585847487898026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115585847487898026'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/08/const.html' title='A Rant about Const'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-115141845955973836</id><published>2006-06-27T10:13:00.003-04:00</published><updated>2010-03-18T12:46:15.718-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><title type='text'>Paying the Sin Tax on Semantics: the Lowly Struct</title><content type='html'>While this is not strictly about Scheme, I want to make a point about language design and the tax we pay (call it a &lt;span style="font-style:italic;"&gt;sin tax&lt;/span&gt;, as the sins of the language designer are visited on generations of hapless language users) when there is no regularity in the syntax.&lt;br /&gt;&lt;br /&gt;Programmers from the C/C++/Java world often look at languages like Scheme, with its relatively uniform syntax (or, I should say, almost a complete lack of syntax, where the language source is pretty much an textual form of an abstract syntax tree) and bemoan how strange it is.&lt;br /&gt;&lt;br /&gt;But, as I will show, the alternative is actually far more complex: that alternative is to have &lt;span style="font-style:italic;"&gt;semantics&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;syntax&lt;/span&gt; all jumbled together. The result is a jumbled mess that comes back to confuse generations of programmers again, and again, and again.&lt;br /&gt;&lt;br /&gt;Said programmer with brains damaged from years of slogging away in C, C++, or Java might only really &lt;span style="font-style:italic;"&gt;see&lt;/span&gt; this after working a bit with simple languages, such as Scheme, and then returning, as I've done with my embedded work. Going back is painful. To quote &lt;span style="font-style:italic;"&gt;Gollum's Song&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;Where once was light&lt;br /&gt;now darkness falls&lt;br /&gt;where once was love&lt;br /&gt;love is no more&lt;/pre&gt;Let's look at one particular example which seems simple, but which is not, and which C and C++ programmers have come to accept. &lt;span style="font-style:italic;"&gt;The Unix-Hater's Handbook&lt;/span&gt; describes this phenomenon with a quotation attributed to Ken Pier at Xerox PARC, which could also apply to the C family of languages:&lt;br /&gt;&lt;blockquote&gt;"I liken starting one’s computing career with Unix, say as an undergraduate, to being born in East Africa. It is intolerably hot, your body is covered with lice and flies, you are malnourished and you suffer from numerous curable diseases. But, as far as young East Africans can tell, this is simply the natural condition and they live within it. By the time they find out differently, it is too late. They already think that the writing of shell scripts is a natural act."&lt;/blockquote&gt;C has the concept of a struct, which is a sort of low-level record:&lt;br /&gt;&lt;pre&gt;struct s_tag {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;};&lt;/pre&gt;This defines an aggregate type. If you put names after the definition they define variables of that type:&lt;br /&gt;&lt;pre&gt;struct s_tag {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;} s_var_1, s_var_2;&lt;/pre&gt;Just like you define instances of an &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;int i_var_1;&lt;/pre&gt;You don't actually need a name for the type, unless you want to use it elsewhere; the following is legal:&lt;br /&gt;&lt;pre&gt;struct {&lt;br /&gt;    int x;&lt;br /&gt;    char y;&lt;br /&gt;} s_var_1, s_var_2;&lt;/pre&gt;However, even given the relative simplicity of this construct, we're already in a twisty maze of language features, all not quite alike! The &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; is unusual in C in that it operates in a separate namespace reserved for &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;union&lt;/span&gt; tags, kind of like the way Common Lisp uses a distinct namespace for functions. While you normally define an instance of a variable like this (say, at file scope, or as a local variable inside a function):&lt;br /&gt;&lt;pre&gt;int my_int;&lt;/pre&gt;Given the struct definition:&lt;br /&gt;&lt;pre&gt;struct s_tag {&lt;br /&gt;    int x;&lt;br /&gt;    char y;&lt;br /&gt;};&lt;/pre&gt; you cannot write:&lt;br /&gt;&lt;pre&gt;s_tag s_var_1, s_var_2;&lt;/pre&gt; because the struct &lt;span style="font-style:italic;"&gt;tag&lt;/span&gt; (the part that goes between the keyword "struct" and the opening curly bracket) is not a type in the general C namespace.&lt;br /&gt;&lt;br /&gt;To access that namespace, you use the word &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; again as a qualifier::&lt;br /&gt;&lt;pre&gt;struct s_tag my_struct;&lt;/pre&gt;In practice, most C programmers ignore this second namespace, and create a &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt;, which makes an &lt;span style="font-style:italic;"&gt;alias&lt;/span&gt; of the struct tag in the general C namespace. This could be written:&lt;br /&gt;&lt;pre&gt;struct s_tag {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;typedef s_tag s_type;&lt;/pre&gt;but there is a commonly used shortcut, in which wrapping a &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt; around the struct declaration changes its interpretation, and instead of defining variables, you are declaring a type:&lt;br /&gt;&lt;pre&gt;typedef struct s_tag {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;} s_type;&lt;/pre&gt;Since you aren't going to use the tag, you can leave it off altogether:&lt;br /&gt;&lt;pre&gt;typedef struct {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;} s_type;&lt;/pre&gt;and still use s_type as a type:&lt;br /&gt;&lt;pre&gt;s_type my_struct;&lt;/pre&gt;Already, as you can see, the &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; requires a kind of "little language" within C, with a lot of context-senstivity necessary to parse all this. And people thing Lisp's &lt;span style="font-weight:bold;"&gt;format&lt;/span&gt; is complicated! Other "little languages" include the way in which &lt;span style="font-weight:bold;"&gt;for&lt;/span&gt; loops and &lt;span style="font-weight:bold;"&gt;switch&lt;/span&gt; statements are written.&lt;br /&gt;&lt;br /&gt;A "little language" is also known as a DSL, or &lt;span style="font-style:italic;"&gt;domain-specific language&lt;/span&gt; -- you see them used a lot in Lisp-style programming, and implemented using macros. But if we wanted to try to support these various syntactic and semantic variations using Lisp or Scheme-sytle macros, we couldn't do it -- it isn't just a matter of replacing curly brackets with parentheses; there is no &lt;span style="font-style:italic;"&gt;underlying&lt;/span&gt; common syntactic form. In other words, comprehending a language like C requires that we constantly change the behavior of the lowest level of the compiler, the &lt;span style="font-style:italic;"&gt;parser&lt;/span&gt;, in a context-sensitive manner. This makes the full C language quite complex, and don't even get me started on C++. It also imposes a burden on the programmer, which he or she will tend, over time, to forget is there -- read the quotation from Ken Pier again!&lt;br /&gt;&lt;br /&gt;There's another way in which structs are special. C supports a special form of initializer, called an &lt;span style="font-style:italic;"&gt;aggregate initializer&lt;/span&gt;. This lets you specify the contents of a &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; on initialization -- that is, when it comes into scope, whether it is file scope or function scope -- but not later, upon assignment, also known as &lt;span style="font-style:italic;"&gt;mutation&lt;/span&gt;. In other words, the legal syntax changes &lt;span style="font-style:italic;"&gt;again&lt;/span&gt; depending on context!&lt;br /&gt;&lt;br /&gt;This makes it very clear to me that it is highly valuable to teach Scheme first, so that this tortured mess can be understood as it is, rather than as a set of &lt;span style="font-style:italic;"&gt;givens&lt;/span&gt; about programming in general.&lt;br /&gt;&lt;br /&gt;This aggregate initializer syntax can also be used for arrays, unions, and various nested combinations of the above. It also can in particular be used for &lt;span style="font-weight:bold;"&gt;const&lt;/span&gt; variables. For our example:&lt;br /&gt;&lt;pre&gt;const s_type my_struct = { 1, 'a' };&lt;/pre&gt;If you leave off some of the values, the remainder of the &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; will be initialized to zero; aggregate initializers may be nested; dimensions must be specified, or the compiler won't know how much data to supply. All well and good, and commonplace to C programmers. Simple, useful, and aside from some caution you must exercise about alignment and possible holes in the runtime representation, structs generally go about their business quite happily and never hurt anyone. (Of course, this is a lie; this shit causes unanticipated bugs and crashes every day. It would be more accurate to say that at this point we haven't introduced &lt;span style="font-style:italic;"&gt;that&lt;/span&gt; much complexity, and so experienced developers who have been around the block have learned how to use these language elements with reasonable safety by applying some commonplace "best practices." This isn't the same as claiming that the language truly supports or helps to enforce this reasonable safety).&lt;br /&gt;&lt;br /&gt;And then C++ came along.&lt;br /&gt;&lt;br /&gt;One of the ways you can initialize objects in C++ is to provide an &lt;span style="font-style:italic;"&gt;initializer list&lt;/span&gt; in your constructor. This is in fact the required method for initializing members of a class that are &lt;span style="font-weight:bold;"&gt;const&lt;/span&gt; or that are references, which are inherently &lt;span style="font-weight:bold;"&gt;const&lt;/span&gt;. In other cases, it is not required that you initialize members that way, but due to the rules about default member initialization this could mean that if you don't, but assign an initial value in the constructor body, you're wasting effort. Chalk this up to the distinction C and C++ makes between initialization and assignment; somewhat baffling to Scheme programmers, who would understand these both as variants on the underlying concept of &lt;span style="font-style:italic;"&gt;binding&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The class could be declared like this:&lt;br /&gt;&lt;pre&gt;class my_class {&lt;br /&gt;    const int a;&lt;br /&gt;    const int b;&lt;br /&gt;};&lt;/pre&gt;The constructor is declared like this:&lt;br /&gt;&lt;pre&gt;my_class( int a, int b );&lt;/pre&gt;&lt;br /&gt;and defined like this:&lt;br /&gt;&lt;pre&gt;my_class::my_class( int a, int b ) :&lt;br /&gt;   member_a( a ),&lt;br /&gt;   member_b( b )&lt;br /&gt;{&lt;br /&gt;    /* body, which is often empty */&lt;br /&gt;}&lt;/pre&gt;The initializer list is, essentially, made up of constructor calls.&lt;br /&gt;&lt;br /&gt;What do you do if you have a struct in your class?&lt;br /&gt;&lt;pre&gt;class my_class {&lt;br /&gt;    const s_type my_struct;&lt;br /&gt;}&lt;/pre&gt;Can you initialize it like this?&lt;br /&gt;&lt;pre&gt;my_class::my_class( int a, int b ) :&lt;br /&gt;   my_struct( { a, b } )&lt;br /&gt;{&lt;br /&gt;    /* body, which is often empty */&lt;br /&gt;}&lt;/pre&gt;Naturally, after using Scheme for a while, I tend to presume that programming languages are at least somewhat regular. There's an aggregate initializer syntax (really, another tiny DSL) that you can use to initialize a &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt;, right? So can I use it here?&lt;br /&gt;&lt;br /&gt;The answer is "no, that would be too easy!"&lt;br /&gt;&lt;br /&gt;If you are accustomed to Scheme, you have become used to a language that is relatively &lt;span style="font-style:italic;"&gt;regular&lt;/span&gt; -- different language forms, which return values, can be used just about everywhere it might make sense to do so. But C++ was not designed like that. There is no &lt;span style="font-style:italic;"&gt;underlying&lt;/span&gt; syntax that is common despite the changed context.&lt;br /&gt;&lt;br /&gt;In particular, although compatibility with C was a major goal of the language design, C++ broke this compatibility in several ways:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;1. &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; types can be declared directly in the common namespace.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In other words, you can just say&lt;br /&gt;&lt;pre&gt;struct s_type {&lt;br /&gt;  /* ... */&lt;br /&gt;};&lt;/pre&gt;without having to &lt;span style="font-weight:bold;"&gt;typedef&lt;/span&gt; it, and simply use &lt;span style="font-weight:bold;"&gt;s_type&lt;/span&gt; freely as a type. The &lt;span style="font-weight:bold;"&gt;typedef struct&lt;/span&gt; form still works, but you've introduced an &lt;span style="font-style:italic;"&gt;alias&lt;/span&gt; for the type; this is not usually an issue since C programmers tend to use prefixes, or suffixes, or some Hungarian-like name mangling to try to keep them straight. This has the side benefit of allowing you to use header files containing the same &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; declarations in plain old C, assuming you keep those headers free of other C++-specific code.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;2. Structs are classes.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It seems like a strange design decision if a design goal was really to maintain as much compatibility with C++ as possible, but when Bjarne Stroustrup designed C++, he apparently decided that a &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; was just a &lt;span style="font-weight:bold;"&gt;class&lt;/span&gt;, with different default access rules (all members are public by default). The C construct known as the &lt;span style="font-weight:bold;"&gt;union&lt;/span&gt; is also a class now, but that's another story for another day. &lt;br /&gt;&lt;br /&gt;But despite this surface uniformity, C++ is still a &lt;span style="font-style:italic;"&gt;hybrid&lt;/span&gt; language. It isn't "objects all the way down," like Ruby, or Dylan, where even an integer is an object, with a class. Which means that a lot of other language constructs act kind of like classes, in some contexts -- except when they don't.&lt;br /&gt;&lt;br /&gt;When you read Stroustrup's book &lt;span style="font-style:italic;"&gt;The C++ Programming Language, Special Edition&lt;/span&gt;, when you are expecing to look at examples of construction and initialization in classes, he often throws in a struct instead. The C++ Standard document often does the same thing. (Warning: reading the C++ Standard document can cause persistent brain damage).&lt;br /&gt;&lt;br /&gt;This also means it is perfectly legal to adorn the good old struct with &lt;span style="font-weight:bold;"&gt;public&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;protected&lt;/span&gt;, and &lt;span style="font-weight:bold;"&gt;private&lt;/span&gt;, and to provide constructors, assignment operators, and various other methods.&lt;br /&gt;&lt;br /&gt;In fact, if you want to use a struct as a &lt;span style="font-weight:bold;"&gt;const&lt;/span&gt; member of a class, which means that it must be initialized using the &lt;span style="font-style:italic;"&gt;initializer list&lt;/span&gt; syntax described above, you must do so by giving the struct a constructor. You can do this inline as follows:&lt;br /&gt;&lt;pre&gt;struct s_type {&lt;br /&gt;   int x;&lt;br /&gt;   char y;&lt;br /&gt;   s_type ( const int init_x, const char init_y ) { x = init_x; y = init_y; }&lt;br /&gt;};&lt;/pre&gt;Or you can just declare the constructor in the header and place the constructor definition in your implementation file, and you even... wait for it... use the same &lt;span style="font-style:italic;"&gt;initializer-list&lt;/span&gt; syntax:&lt;br /&gt;&lt;pre&gt;struct s_type {&lt;br /&gt;    int x;&lt;br /&gt;    char y;&lt;br /&gt;    s_type ( const int init_x, const char init_y );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;s_type::s_type( const int init_x, const char init_y ) :&lt;br /&gt;    x( init_x ),&lt;br /&gt;    y( init_y )&lt;br /&gt;{&lt;br /&gt;    /* empty constructor body */&lt;br /&gt;}&lt;/pre&gt;And &lt;span style="font-style:italic;"&gt;then&lt;/span&gt;, finally, in your class-containing-a-struct's initializer list, you can do this:&lt;br /&gt;&lt;pre&gt;my_class::my_class( int a, int b ) :&lt;br /&gt;   my_struct( a, b )&lt;br /&gt;{&lt;br /&gt;    /* body, which is often empty */&lt;br /&gt;}&lt;/pre&gt;All that syntax, just to initialize a structure member, because Stroustrup decided that initializer lists would actually be lists of constructor calls, except when they aren't quite.&lt;br /&gt;&lt;br /&gt;But what if you don't want to bother with that, but just want to set up the value of your member struct in the constructor body, like this:&lt;br /&gt;&lt;pre&gt;my_class::my_class( int a, int b )&lt;br /&gt;    /* no initializer list */&lt;br /&gt;{&lt;br /&gt;    my_struct( a, b );&lt;br /&gt;}&lt;/pre&gt;The answer is: &lt;span style="font-style:italic;"&gt;you can't!&lt;/span&gt; Because this isn't initialization; it is assigment. This is true even if the struct member of your class is &lt;span style="font-style:italic;"&gt;not&lt;/span&gt; &lt;span style="font-weight:bold;"&gt;const&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;However, you can &lt;span style="font-style:italic;"&gt;assign&lt;/span&gt; your struct in the constructor body:&lt;br /&gt;&lt;pre&gt;my_class::my_class( int a, int b )&lt;br /&gt;    /* no initializer list */&lt;br /&gt;{&lt;br /&gt;    s_type temp_struct = { 0, 'a' };   &lt;br /&gt;    my_struct = temp_struct;&lt;br /&gt;}&lt;/pre&gt;and this is legal, because it isn't initialization. &lt;br /&gt;&lt;br /&gt;If you want to maintain full compatibility with C and expose your header files to a standard C compiler, you will need to perform just this kind of awkward hack to use structs as members. This is apparently what maintaining full backward compatibility with C meant to Stroustrup: that is, it didn't mean as much as indulging his trivial observation that structs behaved like classes with public data members. Sort of.&lt;br /&gt;&lt;br /&gt;Or, if you don't need your struct instance to be per-member (and if it is const, you probably don't), you can make it &lt;span style="font-weight:bold;"&gt;static&lt;/span&gt;, which means it is initialized at file scope:&lt;br /&gt;&lt;pre&gt;class my_class {&lt;br /&gt;    static const s_type my_struct;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const my_class::my_struct = { 0, 'a' };&lt;/pre&gt;Do you have a headache yet?&lt;br /&gt;&lt;br /&gt;It is surprisingly difficult to get this information out of C++ books, even Stroustrup's books, and the C++ standard document: see the end notes, below. Understanding the usage in C++ basically requires an archaeological excavation of hacks: the original, oddly designed two-namespace &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; in C, the common workarounds, the semantics of classes, Stroustrup's somewhat odd mutation of &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; into &lt;span style="font-weight:bold;"&gt;class&lt;/span&gt;, and the strict distinction between initialization and assignment. (Not that there aren't a few things in Common Lisp that feels similarly weighted with historic baggage!)&lt;br /&gt;&lt;br /&gt;I know this hasn't quite been about Scheme, but I am just trying to point out how C and C++ programmers have come to live with this strange mix of syntax-directed semantics, and semantic-specific syntax, where constructs are legal depening on their context. I've been using C and C++ on and off for about twenty years, but have only very recently fully understood &lt;span style="font-style:italic;"&gt;why&lt;/span&gt; I can't initialize structs in what seems like the logical, backwards-compatible way. Maybe you think you can just look it up in the index. Good luck! And if you think you can just look this up in the language's BNF, think again!&lt;br /&gt;&lt;br /&gt;C and C++ programmers live with these restrictions and special cases every day, but yet think that functional programming in a language like Scheme is somehow hard. It isn't -- it is freedom!&lt;br /&gt;&lt;br /&gt;---------------------------&lt;br /&gt;&lt;br /&gt;End Notes:&lt;br /&gt;&lt;br /&gt;The compiler wasn't cooperating, so I asked myself "does C++ really forbid initialization of a &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; member using aggregate initializer syntax (with the curly brackets) in a constructor initialization list?&lt;br /&gt;&lt;br /&gt;Stroustrup, &lt;span style="font-style:italic;"&gt;The C++ Programming Language, Special Edition&lt;/span&gt; p. 101, 234, 809, 818:&lt;br /&gt;&lt;br /&gt;Stroustrup actually seems to advocate freely intermixing &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;class&lt;/span&gt; depending on your intentions for access control. Regarding initialization of structs, he writes "using a constructor [to initialize a struct] is usually better." But, of course, that breaks compatibility with one of the simplest but most highly useful tools of C, and the struct was never designed to support object-oriented programming.&lt;br /&gt;&lt;br /&gt;Since the struct "tag" is promoted to a type in the general namespace, in order to maintain compatibility with C, which is broken anyway, there is a further workaround: although there is not distinct namespace for structs, you can have a &lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; and non-&lt;span style="font-weight:bold;"&gt;struct&lt;/span&gt; type with the same name declared &lt;span style="font-style:italic;"&gt;in the same scope&lt;/span&gt;, but the non-struct will take precedence unless you disambiguate with the prefix "struct." Stroustrup's examples complicate things even further by disambiguating using namespaces, which are another feature not present in C.&lt;br /&gt;&lt;br /&gt;According to Stroustrup's somewhat limited version of the grammar of C++, there isn't any &lt;span style="font-style:italic;"&gt;aggregate initialization&lt;/span&gt; in mem_initializer_list (p. 810), but the grammar is not complete. Page 247 seems to indicate that items in the &lt;span style="font-style:italic;"&gt;member initializer list&lt;/span&gt; in the constructor definition are all &lt;span style="font-style:italic;"&gt;constructor calls&lt;/span&gt;, given that even POD members (plain old data, like &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;char&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;float&lt;/span&gt; and pointers to these types) can be initialized with this constructor call syntax.&lt;br /&gt;&lt;br /&gt;In C++ Std. section 8.4: the grammar shows &lt;span style="font-weight:bold;"&gt;ctor-initializer&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;mem-initializer-list&lt;/span&gt; (where "mem" means "member.") This is described in 12.6.2 and seems to break down further into the formal grammar into &lt;span style="font-style:italic;"&gt;class names&lt;/span&gt; and parameter lists, which seems to indicate that these are all constructors, but again this does not seem to be a complete syntax for C++. Good luck trying to find a complete grammar for C++!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-115141845955973836?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/115141845955973836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=115141845955973836' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115141845955973836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/115141845955973836'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/06/paying-sin-tax-on-semantics-lowly.html' title='Paying the Sin Tax on Semantics: the Lowly Struct'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-114420190458639920</id><published>2006-04-04T21:49:00.000-04:00</published><updated>2006-04-04T21:51:44.603-04:00</updated><title type='text'>A New Planet Scheme!</title><content type='html'>Planet Scheme is reborn at &lt;a href="http://www.scheme.dk/planet/"&gt;http://www.scheme.dk/planet/&lt;/a&gt; and this blog is now syndicated. Thanks for aggregating me! Time to get back to my Sudoku solver, or take a diversion into another program.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-114420190458639920?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/114420190458639920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=114420190458639920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/114420190458639920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/114420190458639920'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/04/new-planet-scheme.html' title='A New Planet Scheme!'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-114244053462132337</id><published>2006-03-15T11:31:00.000-05:00</published><updated>2006-03-15T13:42:07.200-05:00</updated><title type='text'>Planet Scheme off the Air?</title><content type='html'>Planet Scheme seems to be defunct.&lt;br /&gt;&lt;br /&gt;Presumably this means they won't be aggregating this blog, so I guess I can stop asking!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-114244053462132337?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/114244053462132337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=114244053462132337' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/114244053462132337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/114244053462132337'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/03/planet-scheme-off-air.html' title='Planet Scheme off the Air?'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113950419827084243</id><published>2006-02-09T11:53:00.001-05:00</published><updated>2010-03-18T12:11:06.536-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><title type='text'>Thinking about Sudoku and Scheme, Part 5.1</title><content type='html'>Just a brief post today. I have been too busy to do much on my Sudoku solving program itself, but I did spend some time polishing up my array2D library. With revision this library has finally assumed what I feel is its "natural" shape. The optimal design was not clear at the outset, but with some use I feel I've discerned the implementation that minimizes the amount of redundant code and thus the number of places that possible errors may be hiding. I'm sure it could be even more concise; I have a feeling that a little macro magic could cut the lines of code in half, but the shape of that implementation has not yet become clear to me, and I have an allergy to using techniques that don't provide a clear advantage.&lt;br /&gt;&lt;br /&gt;It is really quite a simple library, but in order to provide some assurance of correctness, I also wrote a series of PLT Scheme test cases. I have not figured out how to use DrScheme to tell me if this test suite covers all of the code, or if this is even possible, but it is at least nearly complete.&lt;br /&gt;&lt;br /&gt;The library does not do meaningful error-checking. Scheme textbook code rarely does anything by way of error-checking. As a result I'm deficient on strategies I could use to address this, especially when trying to write to RSR5.&lt;br /&gt;&lt;br /&gt;It isn't possible to code around every conceivable error. For some applications, it makes sense to perform verification any time data is read from or written to memory. We can't operate at that level. We also shouldn't put in effort to detect flaws in the implementation itself. Given our partially functional approach, in which we don't update any top-level definitions, there aren't a lot of unexpected states our library can get into. We should focus our attention on the response to incorrect inputs. There are only a couple of classes of errors that the library should expect:&lt;br /&gt;&lt;br /&gt;1. The set of array boundary errors. Because coordinate pairs are mapped to a single index on a vector, many of possible boundary errors will result in an incorrect cell being set or get. Only cell references that exceed the internal representation will generate a meaningful run-time error, and this error will not tell us if the x or y index was out of bounds.&lt;br /&gt;&lt;br /&gt;2. The set of errors that can arise from receiving an incorrect value-generator or mapping function. In Scheme, a function signature really consists only of the name and the number of parameters, and does not include type information about the parameters. Supplying an incorrect number of parameters will be caught with a meaningful error at run-time but because the passed functions may be called via several levels of indirection, and the function may not be bound to a named variable, it may be difficult to glean from the error message just what has gone wrong. (Another way to say this is that DrScheme has thrown away too much context information).&lt;br /&gt;&lt;br /&gt;Type errors are potentially more insidious, but in my implementation these functions will tend to receive an array (vector), integer indices, and possibly another function. The result of doing a vector access on an integer or function, or treating a vector or function like an integer, should at least fail fast with a moderately meaningful error.&lt;br /&gt;&lt;br /&gt;There are richer language constructs that could address these problems. For example, either Common Lisp or Dylan would allow me to specify type information for the parameters. The runtime is then capable of flagging type errors as soon as they happen, or better yet, verify type safety across functions and generate code that operates on POD (plain old data). Dylan also supports limited types, although implementation support in Gwydion's d2c is spotty. Limited types would allow range checking further upstream. Of course, if I wrote this program in Common Lisp or Dylan, I would not bother simulating an array. If our language supported exception handling, I could wrap the top-level operations to catch exceptions without too much modification inside all my functions.&lt;br /&gt;&lt;br /&gt;Another approach to bounds-checking in my 2-D array would be to encapsulate the array data together with metadata on its x and y dimensions. I am doing this to a limited extent with the closure generation, but the captured x-dimension is not used to validate that the x-index is within bounds. Other array implementations use a record or a closure to wrap up the representation itself. But then it is more difficult to display the contents of the array, and if we are going to start down that road, we might as well try to generalize our library for an n-dimensional array. That seems like overkill, so for now we will call array2D complete as it is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113950419827084243?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113950419827084243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113950419827084243' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113950419827084243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113950419827084243'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/02/thinking-about-sudoku-and-scheme-part.html' title='Thinking about Sudoku and Scheme, Part 5.1'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113874360182943385</id><published>2006-01-31T16:11:00.000-05:00</published><updated>2006-01-31T16:40:01.880-05:00</updated><title type='text'>Interesting Embeddable Languages</title><content type='html'>There are a few languages I am paying particular attention to these days.&lt;br /&gt;&lt;br /&gt;The first is Scheme; that's the language I'm using for my Sudoku experiments.&lt;br /&gt;&lt;br /&gt;The second is Lua. Lua is a light language that includes a byte code compiler and interpreter. It is designed to have a small implementation footprint and to interface well with C. It has lightweight threads. Lua's home is at &lt;a href="http://lua.org"&gt;http://lua.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The third is Io. Io has a syntax that looks a bit weird, unless you're familiar with Smalltalk. I've never used Smalltalk, but I have used NewtonScript. The prototype-based inheritance scheme used in Io reminds me of NewtonScript's inheritance, although Io does not support dual chains. It may not be quite portable enough to move over to an arbitrary platform, but I won't know for sure until I try. Io's home is at &lt;a href="http://iolanguage.com"&gt;http://iolanguage.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And then there is Ruby. Ruby is not quite so lightweight, but it is designed to be embeddable; it would not be my first choice, though, because it does not have a well-tested compiler or byte code runtime. It has too little regularity in its syntax (otherwise known as "too much syntax"), and uses sigils, which I don't like except as convention, as in Dylan, but as far as I'm concerned for usability it beats Perl hands-down. I prefer it to Python for no particularly good reasons other than Python's use of whitespace, which is a relatively trivial feature, and Guido's apparent hostility towards fully usable lexical closures. Ruby's home is at &lt;a href="http://ruby-lang.org"&gt;http://ruby-lang.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ruby's support for higher-order functions has the side effect of making it serve as  an acceptable dialect of Lisp, even without an exact equivalent of Lisp macros. I was able to bring up my basic Sudoku code in just a couple of hours using Ruby. Ruby is great for rapid prototyping and the standard libraries "feel" just the right size. There's some lessons here to inform future generations of Lisp, if the Lisp community is willing to listen to them.&lt;br /&gt;&lt;br /&gt;There are some Forth-inspired languages that are also interesting; I am a fan of Forth, and consider it to be the "other" programmable programming language. Joy (&lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html"&gt;http://www.latrobe.edu.au/philosophy/phimvt/joy.html&lt;/a&gt;) is a sort of functional variant on Forth.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113874360182943385?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113874360182943385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113874360182943385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113874360182943385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113874360182943385'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/interesting-embeddable-languages.html' title='Interesting Embeddable Languages'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113865254292573039</id><published>2006-01-30T15:22:00.001-05:00</published><updated>2010-03-18T12:10:39.079-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><title type='text'>Thinking about Sudoku and Scheme, Part 4</title><content type='html'>Last time I wrote:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Now we've got our given board and our candidate board, and we can start smashing them together to shake out candidates, and begin finding values to go in our boxes.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;So let's do that. But first, I need to confess something. You may have found yourself wondering "You already have a data structure that contains the givens and their coordinates. Why make the &lt;span style="font-weight: bold;"&gt;given-board&lt;/span&gt; vector at all?" If you wondered that, congratulations. You're paying attention, possibly more than I am, and working towards writing code that is simple.&lt;br /&gt;&lt;br /&gt;So what's the answer? The answer is "I don't have a good reason; the code just grew that way, and has not been optimally cleaned up yet." As I write this code, I'm learning to use Scheme more effectively. It has been an iterative process. Right now I'm in the part of the cycle that is excited to have the code successfully working on the first part of the Sudoku board solution. At some point I'll probably be in the part of the cycle that wants to rip up the code and make it smaller and simpler. Scheme lends itself well to stepwise refinement. This is both a blessing and a curse. A blessing, because it is easy to rewrite your code. In C++, assuming your design is not visibly horrible and doesn't crash, it is generally too painful to redo all those interfaces and class definitions and so working code often doesn't get improved unless there is a burning need. Scheme, especially if it is written in an appropriate functional style, is easy to improve locally. This also means that you can always improve it some more, and fall into the trap of improving it endlessly without solving an actual problem. That's the curse.&lt;br /&gt;&lt;br /&gt;OK, now let's get to the meaty part, keeping in mind that this is code in progress. Here's how we map the givens and use them to cancel the first round of candidates.  From the top:&lt;br /&gt;&lt;pre&gt;(cancel-givens&lt;br /&gt;(make-given-board given-list)&lt;br /&gt;(make-initial-candidate-board))&lt;/pre&gt;&lt;br /&gt;Simple enough so far, right? Now we just have to define cancel-givens, and we're done.&lt;br /&gt;&lt;pre&gt;(define cancel-givens&lt;br /&gt; (lambda (given-board candidate-board)&lt;br /&gt;   (map-board-coordinates-elts&lt;br /&gt;    given-board&lt;br /&gt;    (lambda (x-idx y-idx elt)&lt;br /&gt;      (if elt&lt;br /&gt;          (cancel-given&lt;br /&gt;           candidate-board x-idx y-idx elt))))&lt;br /&gt;   candidate-board))&lt;/pre&gt;&lt;br /&gt;We know roughly what that map function is going to look like; it will call a function with the coordinates and elements of the given board. Now we just need to define cancel-given, and we're done. here's cancel-given. This one is big (most likely it could and should be further simplified):&lt;br /&gt;&lt;pre&gt;(define cancel-given&lt;br /&gt; (lambda (candidate-board x-idx y-idx given)&lt;br /&gt;   (reduce-candidate-list-to-given!&lt;br /&gt;    candidate-board x-idx y-idx given)&lt;br /&gt;   (letrec ((filtered-neighborhood-unique-coordinates-list&lt;br /&gt;             (make-filtered-coordinate-list&lt;br /&gt;              (get-unique-neighborhood-coordinates&lt;br /&gt;               x-idx y-idx) (list x-idx y-idx)))&lt;br /&gt;            (candidate-remover&lt;br /&gt;             (make-candidate-remover given))&lt;br /&gt;            (coordinate-list-handler&lt;br /&gt;             (lambda (coordinate-list)&lt;br /&gt;               (if (not (null? coordinate-list))&lt;br /&gt;                   (begin&lt;br /&gt;                     (candidate-remover&lt;br /&gt;                      candidate-board&lt;br /&gt;                      (caar coordinate-list)&lt;br /&gt;                      (cadar coordinate-list))&lt;br /&gt;                     (coordinate-list-handler&lt;br /&gt;                      (cdr coordinate-list)))))))&lt;br /&gt;     (coordinate-list-handler&lt;br /&gt;      filtered-neighborhood-unique-coordinates-list))&lt;br /&gt;   candidate-board))&lt;/pre&gt;&lt;br /&gt;Let's look at this one in a little more detail. Remember that this is called with each given. The first thing we do is turn the candidate list in the box with the given to a list containing only the given. Maybe that isn't the best representation, but it will do for now:&lt;br /&gt;&lt;pre&gt;(define reduce-candidate-list-to-given!&lt;br /&gt; (lambda (candidate-board x-idx y-idx given)&lt;br /&gt;   (set-board-elt!&lt;br /&gt;    candidate-board&lt;br /&gt;    x-idx y-idx&lt;br /&gt;    (list given))))&lt;/pre&gt;&lt;br /&gt;Note that this is not strictly functional in style. I have tried to move over to a functional style, but my roots are still in imperative programming, so a fully functional, referentially-transparent implementation does not come naturally quite yet. In general, I am at a bit of a loss for good idioms to handle the gamut of solving strategies on the board over time without introducing mutation, but that is probably from lack of experience in purely functional programming techniques and data structures. I could keep regenerating the whole board, but that seems strange to me.  I may explore a stricter functional design in a future version.&lt;br /&gt;&lt;br /&gt;Meanwile, let's continue on and look at the next task, which is to remove the given from the entire neighborhood. Recall that the neighborhood of a box is the combined row, column and grid. We want a list of coordinates. Simply combining the coordinates for the row, column and grid will generate duplicate sets of coordinates; we also don't want to process the box itself, or we'll remove the given we just set. So we first use &lt;span style="font-weight: bold;"&gt;get-unique-neighborhood-coordinates&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;(define get-unique-neighborhood-coordinates&lt;br /&gt; (lambda (x-idx y-idx)&lt;br /&gt;   (let ((grid-bounds&lt;br /&gt;          (map-coordinates-to-grid-bounds x-idx y-idx))&lt;br /&gt;         (acc&lt;br /&gt;          (make-unique-coordinate-accumulator)))&lt;br /&gt;     (map-board-row-coordinates y-idx (car acc))&lt;br /&gt;     (map-board-col-coordinates x-idx (car acc))&lt;br /&gt;     (map-board-subarray-coordinates&lt;br /&gt;      (car grid-bounds)&lt;br /&gt;      (cadr grid-bounds)&lt;br /&gt;      (caddr grid-bounds)&lt;br /&gt;      (cadddr grid-bounds)&lt;br /&gt;      (car acc))&lt;br /&gt;     ((cadr acc)))))&lt;/pre&gt;&lt;br /&gt;The function map-coordinates-to-grid-bounds uses a little bit of Scheme math to determine the bounds of the 3x3 grid our box is in. Here's how I do that:&lt;br /&gt;&lt;pre&gt;(define map-coordinates-to-grid-bounds&lt;br /&gt; (lambda (x-idx y-idx)&lt;br /&gt;   (list (get-grid-lower-bound x-idx grid-x-dim)&lt;br /&gt;         (get-grid-upper-bound x-idx grid-x-dim)&lt;br /&gt;         (get-grid-lower-bound y-idx grid-y-dim)&lt;br /&gt;         (get-grid-upper-bound y-idx grid-y-dim))))&lt;/pre&gt;&lt;br /&gt;And here are the helper functions:&lt;br /&gt;&lt;pre&gt;(define get-grid-lower-bound&lt;br /&gt; (lambda (idx dim)&lt;br /&gt;   (* dim (floor (/ idx dim)))))&lt;br /&gt;&lt;br /&gt;(define get-grid-upper-bound&lt;br /&gt; (lambda (idx dim)&lt;br /&gt;   (- (* dim (ceiling (/ (+ 1 idx) dim))) 1)))&lt;/pre&gt;&lt;br /&gt;The particulars of Scheme math require some care if you want to make sure you get a whole number result rounded in the direction that you want. If you're used to using languages that don't do exact fractions, this may seem like too much work. This way seems to work, though, so we will move on for now.&lt;br /&gt;&lt;br /&gt;Next, we use an accumulator (created by make-unique-coordinate-accumulator) to collect up all the coordinates. This isn't a numeric accumulator, but a list accumulator: when we create it, it holds a reference to an empty list, and as we call it with coordinates, the list is assembled. Our accumulator generator looks like this:&lt;br /&gt;&lt;pre&gt;(define make-unique-coordinate-accumulator&lt;br /&gt; (lambda ()&lt;br /&gt;   (let ((coordinates (list)))&lt;br /&gt;     (list&lt;br /&gt;      (lambda (x-idx y-idx)&lt;br /&gt;        (if (not (member (list x-idx y-idx) coordinates))&lt;br /&gt;            (set! coordinates&lt;br /&gt;                  (cons (list x-idx y-idx) coordinates))))&lt;br /&gt;      (lambda ()&lt;br /&gt;        coordinates)))))&lt;/pre&gt;&lt;br /&gt;This is again not strictly functional; in a more functional style, we'd probably generate a new accumulator with a new list created from the previous one. But then the client that held the accumulator would have to mutate its binding in order to get the new accumulator, so it would have to be strictly functional as well -- a sort of viral strict functionality would require rewriting all the upstream code. Something to think about!&lt;br /&gt;&lt;br /&gt;This is yet another function generator, with a twist. We use a let to create a binding for a list, called &lt;span style="font-weight: bold;"&gt;coordinates&lt;/span&gt;. This is the list that will accumulate the coordinates. The actual return value of the function is... another list! This time, a list of two functions. The first function in the list receives coordinates and if the coordinate pair is not already present in the closed-over list, as determined by &lt;span style="font-weight: bold;"&gt;member&lt;/span&gt;, we destructively set coordinates to be the list with the new coordinate pair prepended. The second function in the list doesn't look like a function at all; in fact, it consists only of:&lt;br /&gt;&lt;pre&gt;(lambda ()&lt;br /&gt; coordinates)&lt;/pre&gt;&lt;br /&gt;All that does is return the value held in the binding named &lt;span style="font-weight: bold;"&gt;coordinates&lt;/span&gt;. It's the rough equivalent of a return statement in C, C++, or Java. The important thing to note here is that both of the functions in the list we return contain a reference to coordinates. The binding in question is the one that is in lexical scope when the lambda form is executed. Note that we could stuff these functions inside some other data structure; we could even put them in a single cons cell using set-car! and set-cdr! But for now I am still using the list as my "Swiss Army Knife" data structure, so we'll use that.&lt;br /&gt;&lt;br /&gt;Returning to the innards of &lt;span style="font-weight: bold;"&gt;get-unique-neighborhood-coordinates&lt;/span&gt; let's look at what happens next:&lt;br /&gt;&lt;pre&gt;(map-board-row-coordinates y-idx (car acc))&lt;br /&gt;    (map-board-col-coordinates x-idx (car acc))&lt;br /&gt;    (map-board-subarray-coordinates&lt;br /&gt;     (car grid-bounds)&lt;br /&gt;     (cadr grid-bounds)&lt;br /&gt;     (caddr grid-bounds)&lt;br /&gt;     (cadddr grid-bounds)&lt;br /&gt;     (car acc))&lt;/pre&gt;&lt;br /&gt;I'm applying my accumulator to the row, the column, and the subarray. The map functions are unexceptional; they are wrappers around my 2D array implementation. To pass the four parameters that constitute the bounding rectangle of the subarray, I'm again using those all-purpose list functions &lt;span style="font-weight: bold;"&gt;car&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;cadr&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;caddr&lt;/span&gt;, and &lt;span style="font-weight: bold;"&gt;cadddr&lt;/span&gt;. These simply correspond to retrieving the first, second, third, and fourth element in a list. Actually, in RSR5 Scheme you can rewrite this to use &lt;span style="font-weight: bold;"&gt;first&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;second&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;third&lt;/span&gt;, and &lt;span style="font-weight: bold;"&gt;fourth&lt;/span&gt; if you want to, but older textbooks generally use the composed list abbreviations, so I will stick with them for now; rather than just use clearer names, if I rewrite this to get rid of the composed list functions, I'd rather use a self-documenting data structure of some kind.&lt;br /&gt;&lt;br /&gt;The last expression in the function is the return value. Don't overlook its importance:&lt;br /&gt;&lt;pre&gt;(cadr acc)&lt;/pre&gt;&lt;br /&gt;This actually calls the function contained in the second element of our accumulator list, which will retrieve the contents of the accumulator. Since it is the last expression in the function, &lt;span style="font-weight: bold;"&gt;get-unique-neighborhood-coordinates&lt;/span&gt; will return its value.&lt;br /&gt;&lt;br /&gt;Now we're back in &lt;span style="font-weight: bold;"&gt;cancel-given&lt;/span&gt;. The next thing we do is call make-filtered-coordinate-list on our unique list. We do this to remove the box containing our given, so that we don't wind up removing that candidate as well:&lt;br /&gt;&lt;pre&gt;(define make-filtered-coordinate-list&lt;br /&gt; (lambda (coordinate-list coordinate-pair)&lt;br /&gt;   (if (null? coordinate-list) (list)&lt;br /&gt;       (if (not (equal?&lt;br /&gt;                 coordinate-pair (car coordinate-list)))&lt;br /&gt;           (cons (car coordinate-list)&lt;br /&gt;                 (make-filtered-coordinate-list&lt;br /&gt;                  (cdr coordinate-list) coordinate-pair))&lt;br /&gt;           (make-filtered-coordinate-list&lt;br /&gt;            (cdr coordinate-list) coordinate-pair)))))&lt;/pre&gt;&lt;br /&gt;This function is a textbook case of filtering out one member from a list, returning a new list. The key implementation detail here is that it recursively walks the list, building up a new list as it goes. As it stops to examine each element in the list, if it is not the equal to the item in question, it goes ahead and conses it on to the generated list; if it is, the element is not consed, and we just continue to recurse. You can see similar examples in &lt;span style="font-weight: bold;"&gt;The Little Schemer&lt;/span&gt;. Note that this function counts on the fact that &lt;span style="font-weight: bold;"&gt;equal?&lt;/span&gt; works properly on data structures that are not atoms and on atoms that are different objects in memory. In Scheme, Lisp, and other dynamic languages -- basically, as soon as you get away from "unboxed" primitive data types -- equality is a complex subject!&lt;br /&gt;&lt;br /&gt;OK, are you still with me? We've got a list of the coordinates for the neighborhood we're examining. Next, we make a candidate remover, which is another function generator; when you pass it a candidate, it removes it from all the candidate list. That should be straightforward enough by now, so I won't belabor it. So, does it work?&lt;br /&gt;&lt;br /&gt;Well, of course, it did not work on the first try. Or the second or third try! In fact, while I have presented this design top-down, I actually wrote it using a much more realistic mixture of top-down and bottom-up design. Sometimes the higher-order algorithm will be clear. This is often best worked out on paper. The &lt;span style="font-weight: bold;"&gt;cancel-givens&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;cancel-given&lt;/span&gt; function started out as a stub that called stubs. To test the implementation function-by-function, the stubs just returned fixed values. These were later fleshed out with real code. As I implemented more functions, I found that certain other function definitions seemed to naturally fall out, so wrote those next. Meanwhile, had already gone "bottom up" in the process of writing my 2D array functions, so my implementation hooked up in the middle. Then there was a bit of "impedance mismatch," where the functions I thought I would need turned out not to be precisely the functions I did need. I wound up iterating in both the "bottom up" and "top down" directions multiple times before getting even to this point. But using the DrScheme listener, turnaround on this kind of iteration is very quick.&lt;br /&gt;&lt;br /&gt;The result of removing all the givens from the board, and crossing off candidates in the neighborhood of each given as I go, is a &lt;span style="font-weight: bold;"&gt;candidate-board&lt;/span&gt; vector that looks like the one below. A list of only one value indicates that the value has been solved. I have formatted the output lightly to make the rows a little more clear, and I have marked the initial set of givens in bold:&lt;br /&gt;&lt;pre&gt;(#81&lt;br /&gt;((2 3 7) (3 8) (2 3 7 8) (2 3 4) &lt;span style="font-weight: bold;"&gt;(6)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt; (2 3 4 8) &lt;span style="font-weight: bold;"&gt;(9)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(1)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(1 2 3 6 7) (1 3 6 8) (2 3 6 7 8) (2 3 4 9) (2 3 7 8)&lt;br /&gt;(2 3 7 8 9) &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt; (4 6 8) (2 3 4 6 8)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(4)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(9)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(1)&lt;/span&gt; (2 3 8) (2 3 8) (2 3 8) &lt;span style="font-weight: bold;"&gt;(7)&lt;/span&gt; (2 3 6 8)&lt;br /&gt;&lt;br /&gt;(2 5 6) (4 6 8) (2 5 6 8) (2 5) &lt;span style="font-weight: bold;"&gt;(9)&lt;/span&gt; (1 2 7) (1 2 4 8)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(3)&lt;/span&gt; (2 4 6 8)&lt;br /&gt;&lt;br /&gt;(2 3 5 9) (3 4) &lt;span style="font-weight: bold;"&gt;(1)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(8)&lt;/span&gt; (2 3) &lt;span style="font-weight: bold;"&gt;(6)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(7)&lt;/span&gt; (4 5) (2 4 9)&lt;br /&gt;&lt;br /&gt;(2 3 5 6 9) &lt;span style="font-weight: bold;"&gt;(7)&lt;/span&gt; (2 3 5 6 8) (2 3 5) &lt;span style="font-weight: bold;"&gt;(4)&lt;/span&gt; (1 2 3) (1 2 8 9)&lt;br /&gt;(1 5 6 8) (2 6 8 9)&lt;br /&gt;&lt;br /&gt;(1 3 7) &lt;span style="font-weight: bold;"&gt;(9)&lt;/span&gt; (3 7) (3) (1 3 8) &lt;span style="font-weight: bold;"&gt;(4)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(6)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(2)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(1 3 5 6 7) (1 3 6) &lt;span style="font-weight: bold;"&gt;(4)&lt;/span&gt; (2 3 6 9) (1 2 3 8) (1 2 3 8 9)&lt;br /&gt;(1 3 8 9) (1 8) (3 7 8 9)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(8)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(2)&lt;/span&gt; (3 6) &lt;span style="font-weight: bold;"&gt;(7)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt; (1 3 9) (1 3 4 9) (1 4) (3 4 9))&lt;/pre&gt;&lt;br /&gt;Note that there were 28 givens. The next important question to ask is "did we find any more solved boxes?" That is, did we reduce the candidate list in any of the non-given boxes to a length of 1, indicating only a single possibility in that box?&lt;br /&gt;&lt;br /&gt;If you look closely, you will notice that, in fact, we have solved some boxes, simply by crossing out the givens and following through on the implications of those givens for the boxes in the neighborhood of each given. In the third-from-last row, which would be row 6 in our zero-based indexing, we see that there is a single 3 candidate in one of the candidate lists. This was not a given:&lt;br /&gt;&lt;pre&gt;(1 3 7) &lt;span style="font-weight: bold;"&gt;(9)&lt;/span&gt; (3 7) (3) (1 3 8) &lt;span style="font-weight: bold;"&gt;(4)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(6)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(2)&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;(5)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;However, our code did not yet discover that we have made more progress. In the next installment, we'll look at how the code can make that discovery, and what the implications are. We'll also look how to apply some slightly less elementary solving rules to the board.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113865254292573039?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113865254292573039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113865254292573039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113865254292573039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113865254292573039'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/thinking-about-sudoku-and-scheme-part_30.html' title='Thinking about Sudoku and Scheme, Part 4'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113864474595294880</id><published>2006-01-30T12:34:00.000-05:00</published><updated>2006-01-30T13:17:28.933-05:00</updated><title type='text'>Practical Subversion and Other Subversive Practices</title><content type='html'>Since I'm a fan of the book &lt;span style="font-weight:bold;"&gt;Programming Ruby&lt;/span&gt;, I purchased the two Pragmatic Programmer books, &lt;span style="font-weight:bold;"&gt;Pragmatic Version Control Using CVS&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;Pragmatic Version Control Using Subversion&lt;/span&gt;. I was planning to use them as a quick refresher to CVS and a quick cross-introduction to Subversion, since I have a couple of years of experience using (and occasionally fixing) CVS repositories, and also have used a couple of other tools including MKS RCS, Voodoo, and (a little bit of) ClearCase, and we are implementing a Subversion repository at work.&lt;br /&gt;&lt;br /&gt;I wound up returning the books to the store, though. I would recommend either of them to someone who is new to both tools, but they are too light for someone who has already used one of these version control systems extensively.&lt;br /&gt;&lt;br /&gt;For CVS, there are plenty of free texts available online, including the venerable Cederquist, which is a bit hard to use as a tutorial, and the Fogel and Bar book (at &lt;a href="http://cvsbook.red-bean.com/"&gt;http://cvsbook.red-bean.com/&lt;/a&gt;). I have the second edition in the dead tree edition; the third edition is available free online. If you like it, buy a paper copy.&lt;br /&gt;&lt;br /&gt;For Subversion, although there are some free texts available, I decided that &lt;span style="font-weight:bold;"&gt;Practical Subversion&lt;/span&gt;, by Garrett Rooney, is the right text, on the right level, at the right time, for me. The chapter on best practices alone helps differentiate it from other books which tend to be organized around a command-line options reference. We'll see how it holds up as I gain a little more experience with Subversion.&lt;br /&gt;&lt;br /&gt;I also picked up a copy of &lt;span style="font-weight:bold;"&gt;The Reasoned Schemer&lt;/span&gt;. I am a big fan of &lt;span style="font-weight:bold;"&gt;The Little Schemer&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;The Seasoned Schemer&lt;/span&gt;, although I must admit I have not completed &lt;span style="font-weight:bold;"&gt;The Seasoned Schemer&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I also started reading &lt;span style="font-weight:bold;"&gt;A Little Java, a Few Patterns&lt;/span&gt;, which is an effort to teach functional and recursive programming using Java. Given that I had a lot of Java experience and had already thought a lot about design patterns, it seemed like a strange and forced hybrid, so I decided not to bother with it and just work on Scheme instead. The book may be interesting to developers who know Java and who would like to begin to understand Scheme.&lt;br /&gt;&lt;br /&gt;I am now re-skimming &lt;span style="font-weight:bold;"&gt;The Little Schemer&lt;/span&gt; as a warmup to the new book on logic programming. I've been interested in learning Prolog for a while now but have not gotten much past reading part of Clocksin and Mellish's book &lt;span style="font-weight:bold;"&gt;Programming in Prolog&lt;/span&gt;, 5th ed. Given that I'm currently learning Scheme, implementing a Prolog-like language in Scheme might be the impetus that I need. If I get enough time to work on it I will report on what I find.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113864474595294880?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113864474595294880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113864474595294880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113864474595294880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113864474595294880'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/practical-subversion-and-other.html' title='Practical Subversion and Other Subversive Practices'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113840538397668958</id><published>2006-01-27T17:50:00.001-05:00</published><updated>2010-03-18T12:10:20.439-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><title type='text'>Thinking about Sudoku and Scheme, Part 3</title><content type='html'>OK, so I've given you a small view of one part of the array2D library and how it is implemented. Now let's look at my Sudoku solver from the top. Note that this is a hobby project, done in the rare scraps of free time I am able to piece together these days, by a relative novice in Scheme. In other words, it is not finished, polished, textbook work, so be kind.&lt;br /&gt;&lt;br /&gt;Let's review what Sudoku is and consider some of the most elementary solving strategies. First, terminology. These are the terms I use; some are borrowed and some are my own. Other Sudoku geeks may use alternate terminology.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Box:&lt;/span&gt; the smallest unit; a single space for a number. I identify boxes using zero-based x, y coordinate pairs. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Open box:&lt;/span&gt; a box that does not have a number in it yet.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Coordinates:&lt;/span&gt; on a 9x9 grid, which does not represent the only possibility in Sudoku, the top row goes from (0, 0) to (8, 0) and the rightmost colum goes from (8, 0) to (8, 8).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Given:&lt;/span&gt; one of the numbers already provided in the puzzle.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Grid:&lt;/span&gt; in a 9x9 Sudoku puzzle, one of the 9 3x3 sub-parts; on a 16x16 puzzle, one of the 16 4x4 sub-parts, etc. Grids are not necessarily square; some published puzzles could contain 4x3 grids, for example.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Virtual row:&lt;/span&gt; a single group that must contain the set of possible numbers (in a 9x9 puzzle, 1 through 9). Note that each box is actually part of three virtual rows: its row, column, and grid.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Number set:&lt;/span&gt; for a 9x9 puzzle, the integers 1 through 9. I have seen Sudoku boards that allow the numbers 1 through 12, 1 through 16, 1 through 25, and 1 through 49. Sometimes letters are used: for example, the numbers 1 through 16 can be encoded using the hexadecimal digits 0..F (or 1..G), and the numbers 1 through 25 can be encoded by the letters A..Y. There are more exotic Sudoku involving the letters that make a specific word, but this is really just an encoding issue and does not fundamentally change the rules.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sudoku rule:&lt;/span&gt; there is probably a good formal expression of this, but informally speaking, the Sudoku rule says that each box in each virtual row must contain one of the numbers in the number set. &lt;br /&gt;&lt;br /&gt;By implication, each box cannot contain a number that is not a member of the number set; it also cannot contain a duplicate of another number in the same virtual row; in a completed puzzle each virtual row must be filled, which means the whole puzzle must be filled.&lt;br /&gt;&lt;br /&gt;If you find that a puzzle you are working on seems to break this rule, either the puzzle was not valid to begin with, or you have made a solving error. The second case is more likely, but I have found errors in published puzzles.&lt;br /&gt;&lt;br /&gt;There are several possible types of errors. The givens may violate the Sudoku rule, which will lead to an insoluble puzzle, or more than one solution may be possible, which could lead you to find a solution that follows the Sudoku rule but which does not match the published solution.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Candidate:&lt;/span&gt; one of the possible values that could legally be written in a box.&lt;br /&gt;&lt;br /&gt;On an empty 9x9 grid, each box has as its candidates all the numbers 1 through 9, so no progress can be made towards a solution.&lt;br /&gt;&lt;br /&gt;When the givens are taken into account, the set of candidates in the remaining open boxes in the neighborhood must be reduced to maintain the Sudoku rule. As the puzzle is filled in, the candidates are reduced further.&lt;br /&gt;&lt;br /&gt;As you perform logical deductions on the board, you will remove candidates; when only one candidate remains for a box, the number should be written down and the candidates for boxes elsewhere in the neighborhood must have that number removed; repeat until no open boxes remain. (This is actually in a nutshell the algorithm for solving any Sudoku puzzle, and translates directly into the main loop of a  computer solution that uses human solving techniques rather than testing every possibile chain of possibilities).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Noncandidate:&lt;/span&gt; instead of writing down candidates as you work on the puzzle, you could also write down noncandidates: that is, numbers that have been ruled out for each box. When the set of noncandidates for a given box leaves only one remaining candidate in the number set, you can write down that possibility, and you must then add this number this to the sets of noncandidates elsewhere in the neighborhood. You could represent noncandidates by writing them down directly, although this can be confusing, or writing down the number set in each open box and crossing out numbers as they become noncandidates.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Single Candidate:&lt;/span&gt; the case when one candidate remains in a box; once you recognize this case, you should write in the number; the box is solved, you should then make sure to reduce the candidates in the neighborhood. Which brings us to another term.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Neighborhood:&lt;/span&gt; the combined row, column, and grid that contains a given open box. Neighborhood is a distinct concept from virtual row because if a number appears anywhere in the neighborhood containing a given box, it cannot be a valid candidate for the box; this is because the Sudoku rule applies to each box three ways.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Basic Solving Strategies&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For demonstration purposes, we will use the following 9x9 puzzle (taken from _Sudoku: Easy to Hard Presented by Will Shortz_ Volume 3):&lt;br /&gt;&lt;pre&gt;-------------------------&lt;br /&gt;| 9 . 8 | 3 . . | 7 4 2 |&lt;br /&gt;| . 4 . | 5 8 . | . 9 . |&lt;br /&gt;| 2 . . | . 7 . | 1 . 8 |&lt;br /&gt;-------------------------&lt;br /&gt;| . . 6 | 2 9 4 | 8 3 . |&lt;br /&gt;| 4 8 . | . . . | . . 1 |&lt;br /&gt;| 3 7 . | 6 . 8 | . 2 . |&lt;br /&gt;-------------------------&lt;br /&gt;| . 3 . | . 5 6 | . . . |&lt;br /&gt;| 6 . . | 1 . . | . 8 3 |&lt;br /&gt;| . 2 . | . . 3 | . 1 5 |&lt;br /&gt;-------------------------&lt;/pre&gt;&lt;br /&gt;Let's look at how we might represent this board in Scheme, and then start coming up with functions to operate on it.&lt;br /&gt;&lt;br /&gt;To allow my solver to be configured for different board sizes and grid dimensions, we'll provide bindings for the independent dimension values:&lt;br /&gt;&lt;pre&gt;(define max-box-value 9)&lt;br /&gt;(define board-x-dim 9)&lt;br /&gt;(define board-y-dim 9)&lt;br /&gt;(define grid-x-dim 3)&lt;br /&gt;(define grid-y-dim 3)&lt;/pre&gt;&lt;br /&gt;To start solving our sample puzzle, let's use the following algorithm:&lt;br /&gt;&lt;br /&gt;1. Make a given board. A given board is a board array that contains only the givens. Here are the givens, as a list of list, where each list contains a coordinate pair as a list and a value:&lt;br /&gt;&lt;pre&gt;(define given-list &lt;br /&gt;  '(((4 0) 6) ((5 0) 5) ((7 0) 9) ((8 0) 1)&lt;br /&gt;    ((6 1) 5)&lt;br /&gt;    ((0 2) 4) ((1 2) 5) ((2 2) 9) ((3 2) 1) ((7 2) 7)&lt;br /&gt;    ((4 3) 9) ((7 3) 3)&lt;br /&gt;    ((2 4) 1) ((3 4) 8) ((5 4) 6) ((6 4) 7)&lt;br /&gt;    ((1 5) 7) ((4 5) 4)&lt;br /&gt;    ((1 6) 9) ((5 6) 4) ((6 6) 6) ((7 6) 2) ((8 6) 5)&lt;br /&gt;    ((2 7) 4)&lt;br /&gt;    ((0 8) 8) ((1 8) 2) ((3 8) 7) ((4 8) 5)))&lt;/pre&gt;&lt;br /&gt;Here's a function which will make a given board:&lt;br /&gt;&lt;pre&gt;(define make-given-board&lt;br /&gt;  (lambda (given-list)&lt;br /&gt;    (let ((given-board &lt;br /&gt;           (make-vector (* board-x-dim board-y-dim) #f))&lt;br /&gt;          (setter! (array2D-make-setter board-x-dim)))&lt;br /&gt;      (letrec ((do-write-givens&lt;br /&gt;                (lambda (puzzle-array givens)&lt;br /&gt;                  (if (not (null? givens))&lt;br /&gt;                      (begin&lt;br /&gt;                        (do-write-givens &lt;br /&gt;                         puzzle-array (cdr givens))&lt;br /&gt;                        (setter! puzzle-array &lt;br /&gt;                                 (caaar givens) &lt;br /&gt;                                 (cadaar givens)&lt;br /&gt;                                 (cadar givens)))))))&lt;br /&gt;        (do-write-givens given-board given-list))&lt;br /&gt;      given-board)))&lt;/pre&gt;&lt;br /&gt;This is a pretty simple function, but let's look at a couple of points. First, the default value of our vector is #f, the canonical "false" value. This has no real purpose other than allowing us to use the elements of this array act as an argument to Scheme's &lt;span style="font-weight:bold;"&gt;if&lt;/span&gt; or &lt;span style="font-weight:bold;"&gt;cond&lt;/span&gt; and give the expected results. We've already seen how to use &lt;span style="font-weight:bold;"&gt;letrec&lt;/span&gt; to create a self-recursive helper function; we already know how the curried setter! function works. The body of this function is a pretty straightforward example of recursion over a list. The arguments we pass to setter! are a little more interesting:&lt;br /&gt;&lt;pre&gt;(setter! puzzle-array &lt;br /&gt;              (caaar givens) &lt;br /&gt;              (cadaar givens)&lt;br /&gt;              (cadar givens))&lt;/pre&gt;&lt;br /&gt;These primitives provide shortcuts for expressing combinations of &lt;span style="font-weight:bold;"&gt;car&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;cdr&lt;/span&gt;, and are read inside out from right to left; &lt;span style="font-weight:bold;"&gt;caaar&lt;/span&gt; becomes &lt;span style="font-weight:bold;"&gt;(car (car (car ...)))&lt;/span&gt;, cadaar becomes &lt;span style="font-weight:bold;"&gt;(car (cdr (car (car ...))))&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;An aside: I have a love-hate relationship with these constructions. On the one hand, they allow you to do quick deconstruction of arbitrary list structures, and that's a good thing because lists are very quick and dirty and you can easily put together data structures using lists. On the other hand, they allow you to do quick deconstruction of arbitrary list structures, and that's bad because they are not self-documenting in any way and nothing in them is named. Using something like a plist or record type is probably a better idea, so I will consider that later; Common Lisp provides destructuring, which would also be a valid option because it is self-documenting.&lt;br /&gt;&lt;br /&gt;Anyway, that will build a given board. Now let's build a candidate board. The initial candidate list can be easily generated using another function:&lt;br /&gt;&lt;pre&gt;(define make-initial-candidate-list&lt;br /&gt;  (lambda ()&lt;br /&gt;    ((lambda (max)&lt;br /&gt;       (letrec ((make-candidate-list&lt;br /&gt;                 (lambda (count)&lt;br /&gt;                   (if (&gt; count max) (list)&lt;br /&gt;                       (cons count &lt;br /&gt;                             (make-candidate-list &lt;br /&gt;                              (+ count 1)))))))&lt;br /&gt;         (make-candidate-list 1)))&lt;br /&gt;     max-box-value)))&lt;/pre&gt;&lt;br /&gt;I'm going to wrap this up in the form of a value generator. A value generator is a function that receives x and y indices and returns a new value for the board. In this case our value generator will ignore the parameters:&lt;br /&gt;&lt;pre&gt;(define initial-candidate-value-generator&lt;br /&gt;  (lambda (x-idx y-idx)&lt;br /&gt;    (make-initial-candidate-list)))&lt;/pre&gt;&lt;br /&gt;Now we can use our set-board-elts primitive, which is a curried array mapping function, to fill in the candidates. Each box gets a list containing the full set of candidates:&lt;br /&gt;&lt;pre&gt;(define make-initial-candidate-board&lt;br /&gt;  (lambda ()&lt;br /&gt;    (let ((candidate-board &lt;br /&gt;           (make-vector &lt;br /&gt;            (* board-x-dim board-y-dim) '())))&lt;br /&gt;      (set-board-elts &lt;br /&gt;       candidate-board initial-candidate-value-generator)&lt;br /&gt;      candidate-board)))&lt;/pre&gt;&lt;br /&gt;Now we've got our given board and our candidate board, and we can start smashing them together to shake out candidates, and begin finding values to go in our boxes. More on that next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113840538397668958?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113840538397668958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113840538397668958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113840538397668958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113840538397668958'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/thinking-about-sudoku-and-scheme-part_27.html' title='Thinking about Sudoku and Scheme, Part 3'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113840103242981239</id><published>2006-01-27T15:52:00.000-05:00</published><updated>2006-09-29T17:21:21.846-04:00</updated><title type='text'>Version Control Systems</title><content type='html'>I've had a fair amount of experience using CVS, but not for a couple of years ago. Recently I have been investigating version control systems again. One scenario I wanted to investigate was the following. Assuming a tree of files like this:&lt;br /&gt;&lt;pre&gt;A/&lt;br /&gt;  B/&lt;br /&gt;    foo.cpp&lt;br /&gt;    foobar.cpp&lt;br /&gt;C/&lt;br /&gt;  D/&lt;br /&gt;    bar.cpp&lt;br /&gt;    barbaz.cpp&lt;/pre&gt;&lt;br /&gt;From this, we want to be able to checkout the following to a sandbox directory with a single checkout command:&lt;br /&gt;&lt;pre&gt;F/&lt;br /&gt;  foo.cpp&lt;br /&gt;  bar.cpp&lt;/pre&gt;&lt;br /&gt;If you're a CVS or svn user, go along with me for a moment and assume that this is a valid thing to want to do.&lt;br /&gt;&lt;br /&gt;Unfortunately, it seems to be impossible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;What about CVS modules?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well, I would summarize what modules can do by saying that upon checkout, the use of modules can collapse existing directory hierarchy, or add directory hierarchy that does not exist in the repository, or place directories in places where they don't exist to start with, but they fall short of allowing you to arbitrarily rearrange the tree, and they won't rearrange files. This is probably in part because of the ways in which metadata is stored on disk for CVS sandboxes: it goes into your directories, even though CVS does not treat directories in general as first-class citizens.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Here is what you can do with modules:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Alias&lt;/span&gt; modules will simply allow you to use a different name for an existing module or path. When you check out, all intermediate directories will be created. For example:&lt;br /&gt;&lt;pre&gt;r5rv_alias_dirs -a r5rv/a/b r5rv/c/d&lt;/pre&gt;&lt;br /&gt;Will give you:&lt;br /&gt;&lt;pre&gt;r5rv/&lt;br /&gt;     a/&lt;br /&gt;       b/&lt;br /&gt;         foo.cpp&lt;br /&gt;         foobar.cpp&lt;br /&gt;     c/&lt;br /&gt;       d/&lt;br /&gt;         bar.cpp&lt;br /&gt;         barbaz.cpp&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Regular&lt;/span&gt; modules let you label all or some of the files in a directory with a module name. For example, this will get only the files indicated and write them in a directory with the name of the module, generating no intermediate directories in the output:&lt;br /&gt;&lt;pre&gt;r5rv_foo r5rv/a/b foo.cpp&lt;/pre&gt;&lt;br /&gt;# This will give you:&lt;br /&gt;&lt;pre&gt;r5rv_foo/&lt;br /&gt;         foo.cpp&lt;/pre&gt;&lt;br /&gt;Leaving off the filename will get you all the files in the specified subdirectory:&lt;br /&gt;&lt;pre&gt;r5rv_b r5rv/a/b&lt;/pre&gt;&lt;br /&gt;giving you:&lt;br /&gt;&lt;pre&gt;r5rv_b/&lt;br /&gt;       foo.cpp&lt;br /&gt;       foobar.cpp&lt;/pre&gt;&lt;br /&gt;Note that for regular modules you can't put multiple directories on the same line, or CVS gets confused.&lt;br /&gt;&lt;br /&gt;If you want to put specific files or the contents of specific directories together, you have to use &lt;span style="font-weight:bold;"&gt;ampersand&lt;/span&gt; modules. But: when CVS writes out ampersand modules, it addes the module names to the directory structure! So, given:&lt;br /&gt;&lt;pre&gt;r5rv_bar r5rv/c/d/ bar.cpp&lt;br /&gt;r5rv_foo_bar &amp;r5rv_foo &amp;r5rv_bar&lt;/pre&gt;&lt;br /&gt;Checking out r5rv_foo_bar will give you:&lt;br /&gt;&lt;pre&gt;r5rv_foo_bar/&lt;br /&gt;             r5rv_foo/&lt;br /&gt;                      foo.cpp&lt;br /&gt;             r5rv_bar/&lt;br /&gt;                      bar.cpp&lt;/pre&gt;&lt;br /&gt;Not quite what we want.&lt;br /&gt;&lt;br /&gt;You can exclude directories when defining an alias module. For example:&lt;br /&gt;&lt;pre&gt;r5rv_no_c -a !r5rv/c r5rv&lt;/pre&gt;&lt;br /&gt;will give you only:&lt;br /&gt;&lt;pre&gt;r5rv/&lt;br /&gt;     a/&lt;br /&gt;       d/&lt;/pre&gt;&lt;br /&gt;Note that if you already have r5rv checked out from the module r5rv_alias_dirs above, CVS will not remove the contents of c/, so it would be best to remove your local sandbox version of r5rv before checking out this new module.&lt;br /&gt;&lt;br /&gt;So can we achieve an output dir like:&lt;br /&gt;&lt;pre&gt;r5rv_proj/&lt;br /&gt;          f/&lt;br /&gt;            foo.cpp&lt;br /&gt;            bar.cpp&lt;/pre&gt;&lt;br /&gt;I don't think CVS can do this directly, but we come close, if we're willing to accept intermediate directories around our individual files. Using as a model the r5rv_foo_bar module above, we can change it to rename the working directory to something other than the module name:&lt;br /&gt;&lt;pre&gt;r5rv_foo_bar_renamed -d r5rv_proj &amp;r5rv_foo &amp;r5rv_bar&lt;/pre&gt;&lt;br /&gt;We get:&lt;br /&gt;&lt;pre&gt;r5rv_proj/&lt;br /&gt;          r5rv_bar/&lt;br /&gt;                   bar.cpp&lt;br /&gt;          r5rv_foo/&lt;br /&gt;                   foo.cpp&lt;/pre&gt;&lt;br /&gt;What if we wanted to fix up this hierarchy with a post-checkout script? Well, assuming we can guarantee the script will run on the client, if we have a script that will move our files, we can specify that we want a script to run by defining a module like this:&lt;br /&gt;&lt;pre&gt;r5rv_post -o combine.sh -d r5rv_proj &amp;r5rv_foo &amp;r5rv_bar&lt;/pre&gt;&lt;br /&gt;This gives us what we want, but there is one problem: we have not properly preserved the contents of the CVS metadata directories. This means that CVS no longer knows what directory foo.cpp and bar.cpp belong to, and will be generating all kinds of errors when, for example, doing a status check or update. There are some workarounds that can be put into place using .cvsignore files, and I suppose that if I was feeling ambitious I could write some scripts that would actually run sed on the metadata files in the CVS subdirectories, but it should be obvious that this solution would be ugly and brittle.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;So what about Subversion?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In Subversion, when you commit your initial structure, you can do something like this:&lt;br /&gt;&lt;br /&gt;original:&lt;br /&gt;&lt;pre&gt;a/&lt;br /&gt;  b/&lt;br /&gt;     foo.cpp&lt;br /&gt;     foobar.cpp&lt;br /&gt;c/&lt;br /&gt;  d/bar.cpp&lt;br /&gt;     barbaz.cpp&lt;/pre&gt;&lt;br /&gt;Let's say you want to be able to mix-and-match these into your output. You can check them in to svn as separate projects. Easily done:&lt;br /&gt;&lt;pre&gt;svn import ./a file:///cygdrive/e/repo-svn/r5rv-a -m "initial"&lt;br /&gt;svn import ./b file:///cygdrive/e/repo-svn/r5rv-b -m "initial"&lt;/pre&gt;&lt;br /&gt;Now you want to create a directory that will contain both of them upon checkout:&lt;br /&gt;&lt;pre&gt;mkdir r5rv-proj&lt;br /&gt;svn import ./r5rv-proj file:///cygdrive/e/repo-svn/r5rv-proj -m "initial"&lt;/pre&gt;&lt;br /&gt;Then over in your workspace, you check out that empty directory: the last parameter is the name to give it in your workspace:&lt;br /&gt;&lt;pre&gt;svn checkout file:///cygdrive/e/repo-svn/r5rv-proj r5rv-proj&lt;/pre&gt;&lt;br /&gt;Now you have a working copy of an empty directory (something that is impossible in CVS!) You want to add a &lt;span style="font-weight:bold;"&gt;svn:externals&lt;/span&gt; property to it. This consists of a set of svn URLs for things that should be retrieved here when the directory is checked out. You can do this with svn propset, but since you want one local directory name and one svn URL per line, you can't really do it directly on the command line. Instead you can do something like &lt;br /&gt;&lt;pre&gt;echo "r5rv-a file:///cygdrive/e/repo-svn/r5rv-a" &gt;&gt; props&lt;br /&gt;echo "r5rv-c file:///cygdrive/e/repo-svn/r5rv-c" &gt;&gt; props&lt;/pre&gt;&lt;br /&gt;Check that it looks right:&lt;br /&gt;&lt;pre&gt;$ cat props&lt;br /&gt;r5rv-a file:///cygdrive/e/repo-svn/r5rv-a&lt;br /&gt;r5rv-b file:///cygdrive/e/repo-svn/r5rv-b&lt;/pre&gt;&lt;br /&gt;then set the externals property using -F, which means read from a file, like so:&lt;br /&gt;&lt;pre&gt;$ svn propset svn:externals -F props r5rv-proj/&lt;br /&gt;property 'svn:externals' set on 'r5rv-proj'&lt;/pre&gt;&lt;br /&gt;You can confirm the property has been set:&lt;br /&gt;&lt;pre&gt;$ svn propget svn:externals r5rv-proj&lt;br /&gt;r5rv-a file:///cygdrive/e/repo-svn/r5rv-a&lt;br /&gt;r5rv-b file:///cygdrive/e/repo-svn/r5rv-b&lt;/pre&gt;&lt;br /&gt;Clean up:&lt;br /&gt;&lt;pre&gt;$ rm props&lt;/pre&gt;&lt;br /&gt;OK, now commit:&lt;br /&gt;&lt;pre&gt;svn commit r5rv-proj/ -m "added external property"&lt;/pre&gt;&lt;br /&gt;And update:&lt;br /&gt;&lt;pre&gt;svn update r5rv-proj/&lt;/pre&gt;&lt;br /&gt;You see something like this:&lt;br /&gt;&lt;pre&gt;Fetching external item into 'r5rv-proj/r5rv-a'&lt;br /&gt;A    r5rv-proj/r5rv-a/b&lt;br /&gt;A    r5rv-proj/r5rv-a/b/foo.cpp&lt;br /&gt;Updated external to revision 4.&lt;br /&gt;&lt;br /&gt;Fetching external item into 'r5rv-proj/r5rv-c'&lt;br /&gt;A    r5rv-proj/r5rv-c/d&lt;br /&gt;A    r5rv-proj/r5rv-c/d/bar.cpp&lt;br /&gt;Updated external to revision 4.&lt;/pre&gt;&lt;br /&gt;That's a lot of work! But the model is actually simpler than elaborate use of entries in the modules file. In addition, under svn, a non-privileged user can make this change (that is, a user with ordinary write access, rather than administrator access). And more importantly, these changes are all versioned; under CVS, if you want to use those module definitions, you have to make sure that the paths specified in the modules don't change, or the modules file will be out of sync with the repository structure. This is a general problem with CVS, which is not really designed to cope well with restructuring the repository.&lt;br /&gt;&lt;br /&gt;Now your local project looks like this:&lt;br /&gt;&lt;pre&gt;r5rv-proj/&lt;br /&gt;          r5rv-a/&lt;br /&gt;                 b/&lt;br /&gt;                   foo.cpp&lt;br /&gt;          r5rv-c/&lt;br /&gt;                 d/&lt;br /&gt;                   bar.cpp&lt;/pre&gt;&lt;br /&gt;Which is pretty close to what we want, taking into account the fact that neither CVS nor svn seems to be able to write individual files from different repository locations to the same output directory in the working copy.&lt;br /&gt;&lt;br /&gt;However, there are a couple of things to keep in mind about the svn solution. First, your external links have to be complete svn URLs. That is, they can't be relative URLS to directories in the same repository [see note 1].&lt;br /&gt;&lt;br /&gt;Worse, it seems that since I'm using svn URLs that start with svn+ssh, the URL I put into the svn::externals property has to include my username! [see note 2]. This means that the external URL will only work when I do the update, not when my co-workers do it. What a mess. &lt;br /&gt;&lt;br /&gt;It appears that svn ignores externals when you perform a commit. That is, it assumes you are using an external piece of code that you don't own, and don't want to (or don't have permission to) change. However, you _can_ specify that the external reference should either remain stuck on a particular version, or should refer to the head; if you choose the latter, when you do an update, if the external tree have changed your working copy will be updated.&lt;br /&gt;&lt;br /&gt;Anyway, there it is: externals are slightly more flexible than CVS, but not arbitrarily flexible, and with some critical usability issues. Neither of the tools really will let you assemble a checkout out of arbitrary directories and files.&lt;br /&gt;&lt;br /&gt;I am going with svn and hoping not to look back, but the ability to define completely arbitrary modules would have been a nice fit to our build process.&lt;br /&gt;&lt;br /&gt;From the point of view of programming languages, or even a DSL for version control, this would seem like a perfect example of failed Greenspunning. Why _shouldn't_ the modules system in CVS let you specify arbitrary paths, or even use regular expression pattern matching, to specify the members of a retrievable module? Why shouldn't a tool like svn let you use a DSL to specify what actually happens in the checkout process, with primitives that correspond to the domain entities and proper handling of metadata?&lt;br /&gt;&lt;br /&gt;Without this, it seems to me, there is still room in the version control space for a better tool. But I guess there is always room for a better tool; the question is "how flexible is flexible enough?"&lt;br /&gt;&lt;br /&gt;NOTE 1: Apparently this subversion feature (relative external links) has been under discussion for a long time. See &lt;a href="http://subversion.tigris.org/issues/show_bug.cgi?id=1336"&gt;the bug report.&lt;/a&gt; It looks like it might appear in svn 1.5, but I'm not holding my breath.&lt;br /&gt;&lt;br /&gt;NOTE 2: There seems to be a way to configure resource files so that command-line svn clients will let you use external svn+ssh URLs that don't specify a username. However, at my workplace we are all using the TortoiseSVN client, and I'm not aware of any way to make that client work with these URLs without specifying the username. Also, just as a matter of design, it seems like a bad idea to force your repository to contain hard-coded references to its own URL, since these will break if the entire repository is moved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113840103242981239?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113840103242981239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113840103242981239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113840103242981239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113840103242981239'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/version-control-systems.html' title='Version Control Systems'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113821580951613385</id><published>2006-01-25T12:50:00.001-05:00</published><updated>2010-03-18T12:10:04.065-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><title type='text'>Thinking about Sudoku and Scheme, Part 2</title><content type='html'>Here is how I implemented some of my array primitives. I'll start in the middle:&lt;br /&gt;&lt;pre&gt;(define map-board-row-elts&lt;br /&gt; (array2D-make-row-elt-mapper board-x-dim))&lt;/pre&gt;&lt;br /&gt;When treating a vector like a two-dimensional array, assuming that you store them row-first, the key piece of information you need is the size of the row. (More generally, for an &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;-dimensional array, to access an element you need to know the size of dimensions 1 to &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; - 1). On the top side of my program, the dimensions of my Sudoku board are known. The array primitives don't know. Rather than pass this information to every array access call, I create a function. The function &lt;span style="font-weight: bold;"&gt;array2D-make-row-elt-mapper&lt;/span&gt; captures this information using closure and returns another function:&lt;br /&gt;&lt;pre&gt;(define array2D-make-row-elt-mapper&lt;br /&gt;  (lambda (x-dim)&lt;br /&gt;    (lambda (array2D y-idx elt-handler)&lt;br /&gt;      (array2D-map-row-elts &lt;br /&gt;       array2D y-idx x-dim elt-handler))))&lt;/pre&gt;&lt;br /&gt;Note the nested lambda expressions. The top one receives the &lt;span style="font-weight:bold;"&gt;x-dim&lt;/span&gt; parameter, and the body of this function is another lambda expression. This second lambda expression is the return value of this function: it returns a function. This returned function invokes another function which requires an &lt;span style="font-weight:bold;"&gt;x-dim&lt;/span&gt; parameter.&lt;br /&gt;&lt;br /&gt;In this case, the purpose of returning this function is to provide the functionality of another function, &lt;span style="font-weight:bold;"&gt;array2D-map-row-elts&lt;/span&gt;, but without the need to provide an &lt;span style="font-weight:bold;"&gt;x-dim&lt;/span&gt; parameter. The new function is a &lt;span style="font-style:italic;"&gt;curried function&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;What is a curried function? Currying means taking a function with &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; parameters and creating a new function with &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; - 1 parameters. The new function provides a default value for the missing parameter, giving you a simplified API to the original function.&lt;br /&gt;&lt;br /&gt;Common Lisp and other languages provide &lt;span style="font-weight: bold;"&gt;curry&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;rcurry&lt;/span&gt; functions which peel off parameters from the left or right of the paramter list, respectively. So our currying may not meet a strict definition, although we are doing the same thing: providing an interface function that will supply a value for one of the original parameters. Currying often uses a constant for these default parameters; in our case, we're using a variable, but the idea is similar. Scheme does not have a standard &lt;span style="font-weight: bold;"&gt;curry&lt;/span&gt; function, but it is easy enough to express currying by using nested lambda expressions.&lt;br /&gt;&lt;br /&gt;In my case, &lt;span style="font-weight: bold;"&gt;x-dim&lt;/span&gt; is the curried parameter. Inside this lambda expression is a reference to x-dim. Scheme supports lexical closure; at the time this lambda expression is evaluated, the result is a function object that "closes over" or "captures" -- that is, retains a reference to -- the variable binding in effect when the lambda expression is evaluated.&lt;br /&gt;&lt;br /&gt;This is the variable binding owned by the caller, the variable bound to the name &lt;span style="font-weight: bold;"&gt;board-x-dim&lt;/span&gt;. It is not a copy: if some other piece of code updates the value in that variable, this function would see a different value for x-dim when it executes. This creates complex state with multiple possible "listeners" for the state change: this is one of the reasons that Scheme programmers tend to prefer a functional style where variables are not altered after initial binding.&lt;br /&gt;&lt;br /&gt;If you are a C programmer, you may find this very confusing. You can think of it as if the returned function retains a pointer to the board-x-dim sent by the caller. The C runtime model is quite different, though: it has distinct lifetimes for variables; local non-static ("automatic") variables that exist on the stack may be recycled when a given function returns, so it is unsafe to retain pointers to them (in fact, retaining a pointer to an automatic variable is a common beginner's bug in C).&lt;br /&gt;&lt;br /&gt;In Scheme, bindings exist as long as there are references to them; when there are no more references to them, they may be garbage-collected (or not).&lt;br /&gt;&lt;br /&gt;Let's look at the definition of the next function we call, &lt;span style="font-weight:bold;"&gt;array2D-map-row-elts&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;((define array2D-map-row-elts&lt;br /&gt;  (lambda (array2D y-idx x-dim elt-handler)&lt;br /&gt;    (array2D-map-subrow-elts&lt;br /&gt;     array2D &lt;br /&gt;     0 (- x-dim 1) &lt;br /&gt;     y-idx &lt;br /&gt;     x-dim &lt;br /&gt;     elt-handler)))&lt;/pre&gt;&lt;br /&gt;OK, we call yet another function: &lt;span style="font-weight:bold;"&gt;array2D-map-subrow-elts&lt;/span&gt;, which is more general (it will map any contiguous subset of the array elements). It is the general case, and &lt;span style="font-weight:bold;"&gt;array2D-map-row-elts&lt;/span&gt; is the more specific case (it maps the whole row), which means we can quite naturally define this specific case by parameterizing the general case. It isn't quite the same as currying, but it is a similar idea; we provide some fixed parameters representing the start of the row (index 0) and end (index x-dim - 1). Here is the general function:&lt;br /&gt;&lt;pre&gt;(define array2D-map-subrow-elts&lt;br /&gt;  (lambda (array2D &lt;br /&gt;           x-first-idx x-last-idx &lt;br /&gt;           y-idx &lt;br /&gt;           x-dim &lt;br /&gt;           elt-handler)&lt;br /&gt;    (letrec ((iter-x&lt;br /&gt;              (lambda (x-idx y-idx)&lt;br /&gt;                (elt-handler &lt;br /&gt;                 (array2D-get array2D x-idx y-idx x-dim))&lt;br /&gt;                (if (&lt; x-idx x-last-idx)&lt;br /&gt;                    (iter-x (+ x-idx 1) y-idx)))))&lt;br /&gt;      (iter-x x-first-idx y-idx))))&lt;/pre&gt;&lt;br /&gt;Are we there yet?&lt;br /&gt;&lt;br /&gt;This function receives all the parameters and walks through the array, starting with an arbitrary x-idx (in this case, zero), and proceeding until we have processed the last legal x index (in this case, x-idx - 1). &lt;br /&gt;&lt;br /&gt;Note that instead of iteration to walk the array, I use recursion. I won't go into a full explanation of recursion here; suffice it to say that although many people feel that recursion is unnatural and does not reflect how they think about iteration in the "real world," after expressing algorithms recursively for a while, it starts to seem much more natural, and the proposition that recursion and iteration can be transformed into each other does not seem so strange.&lt;br /&gt;&lt;br /&gt;This function is formulated using tail recursion, where the bindings are not referenced after the recursive function call. In C or Pascal, the compilers are generally not smart about this sort of thing, and recursing on a large array could result in a very deep set of stack frames. A language like Scheme is able to recognize that since the values that exist in previous function calls are not used, it is free to lose track of the previous values, so no deep stack is actually required. Since this is the case, the decision to use recursion was largely arbitrary. I chose it because I wanted to practice writing recursive functions.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight: bold;"&gt;letrec&lt;/span&gt; may be unfamiliar. If the innermost function was not recursive, we could just call it like this, without ever binding the function to a name at all:&lt;br /&gt;&lt;pre&gt;((lambda (x-idx y-idx)&lt;br /&gt;   ... )&lt;br /&gt;0 y-idx)&lt;/pre&gt;&lt;br /&gt;In this case the innermost function is never bound to a name, because nothing has to refer to it by name. The expression around it would simply call it. This is also known as &lt;span style="font-style:italic;"&gt;applying&lt;/span&gt; parameters to the &lt;span style="font-weight: bold;"&gt;anonymous&lt;/span&gt; function object.&lt;br /&gt;&lt;br /&gt;You might think that we could just do this with &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt;. The semantics of &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt; allow the call from outside the function, but the binding to the name &lt;span style="font-weight: bold;"&gt;iter-x&lt;/span&gt; would exist only within the body of the &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt; expression. This body consists of the expression or expressions that occur after the binding list in the &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt; expression. Since the definition of the function occurs as part of the binding list, not part of the body of the &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt; expression, &lt;span style="font-weight: bold;"&gt;let&lt;/span&gt; will not work; &lt;span style="font-weight: bold;"&gt;letrec&lt;/span&gt; is designed specifically to allow definition of recursive or mutually recursive functions within the binding list.&lt;br /&gt;&lt;br /&gt;So &lt;span style="font-style:italic;"&gt;now&lt;/span&gt; are we there yet?&lt;br /&gt;&lt;br /&gt;Almost. My final comment on this function concerns the use of the &lt;span style="font-weight: bold;"&gt;elt-handler&lt;/span&gt; parameter. The generated function allows the caller to pass in a handler function. Applying functions to functions is known as &lt;span style="font-weight: bold;"&gt;higher-order programming&lt;/span&gt;; support for higher-order programming is one of the essential features of Lisp and Scheme.&lt;br /&gt;&lt;br /&gt;It might seem like this is much too complicated. Functions generating functions calling functions calling functions? Well, yes, this is a bit of overkill to access an array; normally we would use some standard functions for handling data structures. But the general style: creating a lot of small functions -- appears very commonly in Scheme programs, and now you have had a taste of how a typical data structure library might be implemented.&lt;br /&gt;&lt;br /&gt;I don't claim to be very experienced with Scheme yet, but I am happy to have gotten to the point where writing functions like &lt;span style="font-weight: bold;"&gt;array2D-make-row-elt-mapper&lt;/span&gt; and its supporting functions comes rapidly and naturally. Reading examples helps, but the lessons don't really click until you tackle a programming problem, and feel your mind begin to undergo rewiring. The level of abstraction, and thus the leverage you can gain from Scheme, become much higher than this, so stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113821580951613385?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113821580951613385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113821580951613385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821580951613385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821580951613385'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/thinking-about-sudoku-and-scheme-part_25.html' title='Thinking about Sudoku and Scheme, Part 2'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113821070245587948</id><published>2006-01-25T12:34:00.000-05:00</published><updated>2006-01-31T14:03:54.710-05:00</updated><title type='text'>Some Computer Science Classics</title><content type='html'>I've been building up a computer science library via ABE Books (http://abebooks.com, highly recommended), purchasing a couple of used books and a couple of new books each month.&lt;br /&gt;&lt;br /&gt;Recently arrived used:&lt;br /&gt;&lt;br /&gt;Hoare, Communicating Sequential Processes.&lt;br /&gt;Dijkstra, A Discipline of Programming&lt;br /&gt;Agha, Actors&lt;br /&gt;&lt;br /&gt;Recently arrived new:&lt;br /&gt;Brodie, Thinking Forth&lt;br /&gt;&lt;br /&gt;Some comments on these texts later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113821070245587948?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113821070245587948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113821070245587948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821070245587948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821070245587948'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/some-computer-science-classics.html' title='Some Computer Science Classics'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113821017524934032</id><published>2006-01-25T12:29:00.001-05:00</published><updated>2010-03-18T12:09:34.002-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><title type='text'>Thinking about Sudoku and Scheme, Part 1</title><content type='html'>I've been working on some tools to help me solve Sudoku puzzles in Scheme. That goal is actually secondary to the goal of learning to write better, more idiomatic Scheme programs, and so progress towards the Sudoku solver is frequently interrupted while I backtrack in an attempt to reorganize and optimize the supporting code.&lt;br /&gt;&lt;br /&gt;I'm working on this both in a bottom-up and top-down direction. Bottom up, to develop something of a domain-specific Sudoku-solving language. Top down, because my higher-level strategy is also not that clear at the outset and is undergoing stepwise refinement.&lt;br /&gt;&lt;br /&gt;My approach to solving Sudoku by computer is not to recursively explore every the tree of moves until a solution is found. That approach is easily doable but less interesting to me than trying to emulate some of the solving strategies that can be performed by a human solver. Ultimately I would like the tool to assist a human solver, not replace her.&lt;br /&gt;&lt;br /&gt;My tool of choice is PLT Scheme version 3.00. For reasons to painful to go into just now, I have currently given up on using either SRFIs or SLIB for libraries and am writing everything in plain RSR5 Scheme. More on hat later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113821017524934032?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113821017524934032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113821017524934032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821017524934032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821017524934032'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/thinking-about-sudoku-and-scheme-part.html' title='Thinking about Sudoku and Scheme, Part 1'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-21500237.post-113821013817667475</id><published>2006-01-25T12:25:00.000-05:00</published><updated>2006-01-25T12:30:26.653-05:00</updated><title type='text'>Welcome</title><content type='html'>This blog, "Curse and Recurse" is a spinoff of my weblogs "Geek Like Me" and "Geek Like Me, Too."&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thepottshouse.org/blosxom.cgi"&gt;http://thepottshouse.org/blosxom.cgi&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://geeklikemetoo.blogspot.com/"&gt;http://geeklikemetoo.blogspot.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The topic of this blog is pragmatic programming and programming languages. I am interested in clearer and more effective ways to express programs and tools that will get to bug-free code faster, Sapir-Worf be damned. I don't have a Ph.D. and this is not an exposition about theoretical type systems.&lt;br /&gt;&lt;br /&gt;The languages I am currently most interested in are Scheme, and Ruby. I have long-term goals to learn idiomatic programming in Common Lisp and to find better approaches to embedded systems programming by using embedded languages such as Lua and Io. This is not currently another Ruby on Rails weblog and I am not doing web development these days, although I have done so in the distant past.&lt;br /&gt;&lt;br /&gt;If you are still reading, welcome! Maybe we can both learn something.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/21500237-113821013817667475?l=praisecurseandrecurse.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://praisecurseandrecurse.blogspot.com/feeds/113821013817667475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=21500237&amp;postID=113821013817667475' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821013817667475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/21500237/posts/default/113821013817667475'/><link rel='alternate' type='text/html' href='http://praisecurseandrecurse.blogspot.com/2006/01/welcome.html' title='Welcome'/><author><name>Paul Potts</name><uri>https://profiles.google.com/111931884962855299890</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-1ww6aIZqQwc/AAAAAAAAAAI/AAAAAAAACQ4/0Z88XqV325Q/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
