<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>halostatue</title>
	<atom:link href="http://www.halostatue.ca/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.halostatue.ca</link>
	<description>software development with ruby in Toronto</description>
	<lastBuildDate>Mon, 29 Mar 2010 18:28:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>net-ldap version 0.1.1 has been released!</title>
		<link>http://www.halostatue.ca/2010/03/18/net-ldap-version-0-1-1-has-been-released/</link>
		<comments>http://www.halostatue.ca/2010/03/18/net-ldap-version-0-1-1-has-been-released/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 13:59:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2010/03/18/net-ldap-version-0-1-1-has-been-released/</guid>
		<description><![CDATA[Pure Ruby LDAP library.
Changes:
### Net::LDAP 0.1.1 / 2010-03-18
* Fixing a critical problem with sockets.
### Net::LDAP 0.1.0 / 2010-03-17
* Small fixes throughout, more to come.
* Ruby 1.9 support added.
* Ruby 1.8.6 and below support removed. If we can figure out a compatible way
  to reintroduce this, we will.
* New maintainers, new project repository location. Please [...]]]></description>
			<content:encoded><![CDATA[<p>Pure Ruby LDAP library.</p>
<p>Changes:</p>
<p>### Net::LDAP 0.1.1 / 2010-03-18<br />
* Fixing a critical problem with sockets.</p>
<p>### Net::LDAP 0.1.0 / 2010-03-17<br />
* Small fixes throughout, more to come.<br />
* Ruby 1.9 support added.<br />
* Ruby 1.8.6 and below support removed. If we can figure out a compatible way<br />
  to reintroduce this, we will.<br />
* New maintainers, new project repository location. Please see the README.txt.</p>
<p>* <http ://net-ldap.rubyforge.org/><br />
* <http ://github.com/RoryO/ruby-net-ldap></http></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2010/03/18/net-ldap-version-0-1-1-has-been-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>net-ldap version 0.1.0 has been released!</title>
		<link>http://www.halostatue.ca/2010/03/17/net-ldap-version-0-1-0-has-been-released/</link>
		<comments>http://www.halostatue.ca/2010/03/17/net-ldap-version-0-1-0-has-been-released/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 01:08:29 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2010/03/17/net-ldap-version-0-1-0-has-been-released/</guid>
		<description><![CDATA[Pure Ruby LDAP library.
Changes:
### Net::LDAP 0.1.0 / 2010-03-08
* Small fixes throughout, more to come.
* Ruby 1.9 support added.
* Ruby 1.8.6 and below support removed. If we can figure out a compatible way
  to reintroduce this, we will.
* New maintainers, new project repository location. Please see the README.txt.
### Net::LDAP 0.0.5 / 2009-03-xx
* 13 minor enhancements:
 [...]]]></description>
			<content:encoded><![CDATA[<p>Pure Ruby LDAP library.</p>
<p>Changes:</p>
<p>### Net::LDAP 0.1.0 / 2010-03-08<br />
* Small fixes throughout, more to come.<br />
* Ruby 1.9 support added.<br />
* Ruby 1.8.6 and below support removed. If we can figure out a compatible way<br />
  to reintroduce this, we will.<br />
* New maintainers, new project repository location. Please see the README.txt.</p>
<p>### Net::LDAP 0.0.5 / 2009-03-xx<br />
* 13 minor enhancements:<br />
  * Added Net::LDAP::Entry#to_ldif<br />
  * Supported rootDSE searches with a new API.<br />
  * Added [preliminary (still undocumented) support for SASL authentication.<br />
  * Supported several constructs from the server side of the LDAP protocol.<br />
  * Added a &#8220;consuming&#8221; String#read_ber! method.<br />
  * Added some support for SNMP data-handling.<br />
  * Belatedly added a patch contributed by Kouhei Sutou last October.<br />
    The patch adds start_tls support.<br />
  * Added Net::LDAP#search_subschema_entry<br />
  * Added Net::LDAP::Filter#parse_ber, which constructs Net::LDAP::Filter<br />
    objects directly from BER objects that represent search filters in<br />
    LDAP SearchRequest packets.<br />
  * Added Net::LDAP::Filter#execute, which allows arbitrary processing<br />
    based on LDAP filters.<br />
  * Changed Net::LDAP::Entry so it can be marshalled and unmarshalled.<br />
    Thanks to an anonymous feature requester who only left the name<br />
    &#8220;Jammy.&#8221;<br />
  * Added support for binary values in Net::LDAP::Entry LDIF conversions<br />
    and marshalling.<br />
  * Migrated to &#8216;hoe&#8217; as the new project droid.<br />
* 14 bugs fixed:<br />
  * Silenced some annoying warnings in filter.rb. Thanks to &#8220;barjunk&#8221;<br />
    for pointing this out.<br />
  * Some fairly extensive performance optimizations in the BER parser.<br />
  * Fixed a bug in Net::LDAP::Entry::from_single_ldif_string noticed by<br />
    Matthias Tarasiewicz.<br />
  * Removed an erroneous LdapError value, noticed by Kouhei Sutou.<br />
  * Supported attributes containing blanks (cn=Babs Jensen) to<br />
    Filter#construct. Suggested by an anonymous Rubyforge user.<br />
  * Added missing syntactic support for Filter ANDs, NOTs and a few other<br />
    things.<br />
  * Extended support for server-reported error messages. This was provisionally<br />
    added to Net::LDAP#add, and eventually will be added to other methods.<br />
  * Fixed bug in Net::LDAP#bind. We were ignoring the passed-in auth parm.<br />
    Thanks to Kouhei Sutou for spotting it.<br />
  * Patched filter syntax to support octal \XX codes. Thanks to Kouhei Sutou<br />
    for the patch.<br />
  * Applied an additional patch from Kouhei.<br />
  * Allowed comma in filter strings, suggested by Kouhei.<br />
  * 04Sep07, Changed four error classes to inherit from StandardError rather<br />
    Exception, in order to be friendlier to irb. Suggested by Kouhei.<br />
  * Ensure connections are closed. Thanks to Kristian Meier.<br />
  * Minor bug fixes here and there.</p>
<p>* <http ://net-ldap.rubyforge.org/><br />
* <http ://github.com/RoryO/ruby-net-ldap></http></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2010/03/17/net-ldap-version-0-1-0-has-been-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FOSSLC Panels and Me</title>
		<link>http://www.halostatue.ca/2009/04/16/fosslc-panels-and-me/</link>
		<comments>http://www.halostatue.ca/2009/04/16/fosslc-panels-and-me/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 03:10:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=569</guid>
		<description><![CDATA[I&#8217;ve been extraordinarily fortunate recently to be invited to participate in two panels presented by FOSSLC and hosted by the University of Toronto.
The first panel, held on the 31st of March, was about participating in the Google Summer of Code and my experiences as a mentor. With me on the panel were Diego Novillo who [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been extraordinarily fortunate recently to be invited to participate in two panels presented by FOSSLC and hosted by the University of Toronto.</p>
<p>The <a href="http://www.fosslc.org/drupal/node/374">first panel</a>, held on the 31<sup>st</sup> of March, was about participating in the <a href="http://code.google.com/soc/">Google Summer of Code</a> and my experiences as a mentor. With me on the panel were <a href="http://www.airs.com/dnovillo/">Diego Novillo</a> who works at Google on <a href="http://gcc.gnu.org/">GCC</a>; <a href="http://weblog.latte.ca/">Blake Winton</a> (<a href="http://twitter.com/bwinton">@bwinton</a>) who mentored for <a href="https://www.drproject.org/">DrProject</a>; <a href="http://nelsonko.com/">Nelson Ko</a> who mentored for <a href="http://info.tikiwiki.org/tiki-index.php">Tiki Wiki</a>; and <a href="http://behdad.org/">Behdad Esfahbod</a> (<a href="http://twitter.com/behdadesfahbod ">@behdadesfahbod</a>)who was in different years a student for, a mentor for, and an organizer for the <a href="http://foundation.gnome.org">GNOME Foundation</a>. It was a lively and informative panel, and I think a lot of interesting things were said.</p>
<p>The <a href="http://www.fosslc.org/drupal/yyz3">second panel</a> is what FOSSLC calls a &#8220;Leaders panel discussion&#8221;, taking place next Wednesday, the 23<sup>rd</sup> of April. I&#8217;m going to be participating with some fascinating people (not everyone is yet listed on the page) and I&#8217;m looking forward to it. The questions haven&#8217;t been decided yet, but I think that there will be interesting things said.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2009/04/16/fosslc-panels-and-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac Recipe Management Programs, Planning a Revisit</title>
		<link>http://www.halostatue.ca/2009/04/12/mac-recipe-management-programs-planning-a-revisit/</link>
		<comments>http://www.halostatue.ca/2009/04/12/mac-recipe-management-programs-planning-a-revisit/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 23:51:45 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Recipes]]></category>
		<category><![CDATA[cooking]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=567</guid>
		<description><![CDATA[Mostly through a couple of bundles that I&#8217;ve purchased recently, I have acquired full licences to Acacia Tree Software&#8217;s SousChef and MacGourmet Deluxe (which is, remember, MacGourmet with all of the plug-ins included).
One thing which I mentioned in the last review for MacGourmet is that it failed to import my data from Yum 2.7.4 due [...]]]></description>
			<content:encoded><![CDATA[<p>Mostly through a couple of bundles that I&#8217;ve purchased recently, I have acquired full licences to Acacia Tree Software&#8217;s <a href="http://acaciatreesoftware.com/">SousChef</a> and <a href="http://www.marinersoftware.com/sitepage.php?page=130">MacGourmet Deluxe</a> (which is, remember, <a href="http://www.macgourmet.com/">MacGourmet</a> with all of the plug-ins included).</p>
<p>One thing which I mentioned in the last review for MacGourmet is that it failed to import my data from Yum 2.7.4 due to a change in the XML format by the new owners of <a href="http://yum-mac.com/">Yum</a>. This has, as promised, been fixed. I imported my database without problems.</p>
<p>SousChef, I&#8217;m happy to report, can now import from MacGourmet databases. It&#8217;s not quite the direct import that I&#8217;d like, but I have now imported my Yum database into SousChef via MacGourmet.</p>
<p>This leaves Yum 3.0, which I have purchased. These, to me, are the best three recipe management programs in the Mac world. I know some people love YummySoup!, but as I said in my <a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/">last review</a>, I&#8217;ve never been able to warm to YummySoup!, which is too bad because it looks nice otherwise.</p>
<p>I&#8217;m going to be living with these recipe programs for a while and do some serious evaluation of all three. This will take a while to do, because we&#8217;re preparing to move house at the end of May and we&#8217;ve already started packing. <em>Bon Appetit!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2009/04/12/mac-recipe-management-programs-planning-a-revisit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixing a problem with hald on Ubuntu 8.10</title>
		<link>http://www.halostatue.ca/2009/03/16/fixing-a-problem-with-hald-on-ubuntu-810/</link>
		<comments>http://www.halostatue.ca/2009/03/16/fixing-a-problem-with-hald-on-ubuntu-810/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 17:50:21 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[linux ubuntu hal]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=562</guid>
		<description><![CDATA[Saved for my own reference as much as anything. I was having a problem this morning on my Ubuntu x86-64 where I was getting nothing but a spinning cursor (the busy cursor) where I should have seen gdm. The problem was the HAL daemon (hald) wasn&#8217;t starting and I couldn&#8217;t figure out why. After digging [...]]]></description>
			<content:encoded><![CDATA[<p>Saved for my own reference as much as anything. I was having a problem this morning on my Ubuntu x86-64 where I was getting nothing but a spinning cursor (the busy cursor) where I should have seen gdm. The problem was the HAL daemon (hald) wasn&#8217;t starting and I couldn&#8217;t figure out why. After digging through several bugs, <a href="https://bugs.launchpad.net/ubuntu/intrepid/+source/gdm/+bug/271138/comments/25">this gem</a> presented itself, and I tried the <a href="https://bugs.launchpad.net/ubuntu/+source/xorg/+bug/276857/comments/8">changed gdm script</a>. It didn&#8217;t fix the problem, but when I ran &#8220;lshal&#8221; by itself, I got:</p>
<pre>lshal: symbol lookup error: /usr/lib/libgobject-2.0.so.0: undefined symbol: g_regex_unref</pre>
<p>This helped me find a <a href="http://translate.google.ca/translate?hl=en&#038;sl=it&#038;u=http://www.slackware-italia.com/forum/viewtopic.php%3Ff%3D19%26t%3D3636&#038;ei=J42-SfeUJ46ytweGl7X3Cw&#038;sa=X&#038;oi=translate&#038;resnum=1&#038;ct=result&#038;prev=/search%3Fq%3Dundefined%2Bsymbol%2Bg_regex_unref%2Bhald%26hl%3Den%26client%3Dfirefox-a%26rls%3Dcom.ubuntu:en-US:unofficial%26hs%3Dndb%26sa%3DG">reference</a> on slackware-italia.com that helped me solve my problem: my ld.so.conf.d had no reference to /usr/lib, only /usr/local/lib. I added it and all is well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2009/03/16/fixing-a-problem-with-hald-on-ubuntu-810/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mime-types version 1.16 has been released!</title>
		<link>http://www.halostatue.ca/2009/03/02/mime-types-version-116-has-been-released/</link>
		<comments>http://www.halostatue.ca/2009/03/02/mime-types-version-116-has-been-released/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 05:36:19 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[mime-types]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2009/03/02/mime-types-version-116-has-been-released/</guid>
		<description><![CDATA[After an excessive amount of time, I&#8217;ve released MIME::Types 1.16. The primary purpose of this release is compatibility with Ruby 1.9.1, but I haven&#8217;t ignored the latest IANA registered types. I have also picked up a few other types that others submitted as patches and scanned through the latest version (1.27) of the Perl MIME::Types [...]]]></description>
			<content:encoded><![CDATA[<p>After an excessive amount of time, I&#8217;ve released MIME::Types 1.16. The primary purpose of this release is compatibility with Ruby 1.9.1, but I haven&#8217;t ignored the latest IANA registered types. I have also picked up a few other types that others submitted as patches and scanned through the latest version (1.27) of the Perl MIME::Types library.</p>
<p>MIME::Types for Ruby allows for the identification of a file&#8217;s likely MIME content type based on the file&#8217;s filename extension, or provides a list of extensions associated with a MIME content type, if known.</p>
<ul>
<li><a href="http://mime-types.rubyforge.org/">http://mime-types.rubyforge.org/</a></li>
<li><a href="http://rubyforge.org/projects/mime-types">http://rubyforge.org/projects/mime-types</a></li>
<li><a href="http://github.com/halostatue/mime-types/tree/master">http://github.com/halostatue/mime-types/tree/master</a></li>
</ul>
<p>MIME::Types for Ruby originally based on and synchronized with the Perl version by Mark Overmeer, copyright 2001 &#8211; 2009. As of version 1.15, the data format for the MIME::Type list has changed and synchronization, if it happens, will be sporadic at best. The preferred source of input for a MIME::Type is the IANA registered list.</p>
<p>Copyright: 2002 &#8211; 2009, Austin Ziegler; based on prior work copyright Mark Overmeer.</p>
<h3 id="toc-licence-notes">Licence Notes</h3>
<p>MIME::Types is available under Ruby&#8217;s disjunctive licence with the GNU GPL or the Perl Artistic licence. See the file Licence.txt in the package for full details.</p>
<h3 id="toc-requirements-and-installation">Requirements and Installation</h3>
<p>MIME::Types has been tested with Ruby 1.8.6, Ruby 1.8.7, Ruby 1.9.1, JRuby 1.1.6 (in Ruby 1.8 mode), and MacRuby 0.3.</p>
<p>MIME::Types can be installed with:</p>
<pre>% ruby setup.rb</pre>
<p>Alternatively, you can use the RubyGems version of MIME::Types available as mime-types-1.16.gem from the usual sources.</p>
<h3 id="toc-mimetypes-1-16">MIME::Types 1.16</h3>
<ul>
<li>Made compatible with Ruby 1.8.6, 1.8.7, and 1.9.1.</li>
<li>Switched to the &#8216;hoe&#8217; gem system and added a lot of build-time tools.</li>
<li>Updated the MIME types to the list based on the values in the Perl library version 1.27. Also updated based on external source information and bug reports.</li>
<li>This is the last planned version of MIME::Types 1.x. Work will be starting soon on MIME::Types 2.x with richer data querying mechanisms and support for external data sources.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2009/03/02/mime-types-version-116-has-been-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What the Obama Inauguration Means to Me</title>
		<link>http://www.halostatue.ca/2009/01/09/obama-inauguration/</link>
		<comments>http://www.halostatue.ca/2009/01/09/obama-inauguration/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 05:12:06 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[inauguration]]></category>
		<category><![CDATA[Obama]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=546</guid>
		<description><![CDATA[The Presidential Inauguration Committee has been asking for essays about what President-elect Obama&#8217;s inauguration means to individuals. Ten people out of however many people submit essays—whether they donate to the inauguration committee or not—will be selected to attend the inauguration. I have submitted the following essay about what this means to me.
In a word, hope.
I [...]]]></description>
			<content:encoded><![CDATA[<p><em>The Presidential Inauguration Committee has been asking for essays about what President-elect Obama&#8217;s inauguration means to individuals. Ten people out of however many people submit essays—whether they donate to the inauguration committee or not—will be selected to attend the inauguration. I have submitted the following essay about what this means to me.</em></p>
<p>In a word, hope.</p>
<p>I do not mean this flippantly, since it was one of the major themes of President-elect Obama&#8217;s campaign. Rather, I see this inauguration as an opportunity for America to heal divisions both recent and decades deep. When I was growing up as a child of an Air Force chaplain, I learned what most American schoolchildren learn: that America is the land of equality and opportunity, and that we are a shining beacon of hope and a model for the rest of the world to follow.</p>
<p>By time I finished college in the middle of the Clinton Presidency, I knew that this was as often false as it was true, and I felt it becoming less true as the years wore on with the bitter partisan fighting instead of paying attention to the needs of Americans and the world.</p>
<p>Ten and a half years ago I met my now-wife, who is Canadian. I found it very easy to emigrate: I was disillusioned with America and saw little hope that things would get any better. I could not completely leave America behind—as the place of my birth and where my parents and brother still live, it has a deep grip on my heart. I have watched over the last ten years with deep sadness and anger as my fears of the deep divisions in America were realized. When America quickly fell to partisan bickering and bullying after 9/11, I knew that I needed to be involved in my local political process and soon after took Canadian citizenship.</p>
<p>Yet every two years, I make sure that my voter registration is still valid and request an absentee ballot. I avoid voting on local issues because I am not affected by them, but I try to make sure that I am aware of who is running for national office and figure out the best choice that I can make. I have voted for a hope at healing in America three times in that last three Presidential elections; this election, it seems the rest of America voted with me.</p>
<p>The wounds in the American psyche are deep; there are entrenched interests who would not see them healed, but I have great hope that this Presidency will be the start of the healing process. I grew up with a vision of America as a better place; under President Obama, I have hope that it will begin to be so once again.</p>
<p><em>According to the rules that they put together, I am eligible for this contest since I am an American citizen, even though I reside in Canada. I hope to win, of course, but it also felt good to write this down. I&#8217;m going to leave comments open on this, but will be moderating comments much more heavily than normal. If you don&#8217;t have anything nice to say about this in a comment, either don&#8217;t say it at all or say it on your own blog.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2009/01/09/obama-inauguration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mac Recipe Management Programs</title>
		<link>http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/</link>
		<comments>http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#comments</comments>
		<pubDate>Sun, 23 Nov 2008 23:51:27 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=539</guid>
		<description><![CDATA[Updated 30 November 2008: I sent links of this review to the publishers involved (except for SousChef, because Ben Lachman the developer found this post on his own and reminded me that I hadn&#8217;t done this even though I meant to). I received a note from the developer of MacGourmet and have added some additional [...]]]></description>
			<content:encoded><![CDATA[<p><em>Updated 30 November 2008: I sent links of this review to the publishers involved (except for SousChef, because Ben Lachman the developer found this post on his own and reminded me that I hadn&#8217;t done this even though I meant to). I received a note from the developer of MacGourmet and have added some additional notes.</em></p>
<p>It&#8217;s time to declutter the house. One of the things I want to get rid of are all the recipe magazines and loose recipes that I have. To do this, I need to keep the recipes that I like or want to try. I need a recipe management program. I currently use Yum 2.7.4, which is good, but not <em>great</em>. I decided to seriously evaluate the various recipe management programs available for the Mac. There&#8217;s a number of them out there, each with different strengths. I&#8217;m going to be evaluating these programs on the following criteria:</p>
<ul>
<li><strong>Browsing</strong>: How easy is it to find a recipe without searching?</li>
<li><strong>Reading</strong>: How easy is it to read the recipes, once entered? A &#8220;kitchen mode&#8221; is nice, but absolutely unnecessary in my kitchen—my iMac is in the office. So, I&#8217;ll either be reading the recipe to get a sense of the way to make it (and often just a reminder), or I&#8217;ll be printing the recipe.</li>
<li><strong>Printing</strong>: How good does the output look? How much fiddling do I have to do to get multiple recipes on a single page, if they&#8217;re small enough? How much fiddling do I have to do to get a longer recipe on a single page? Sure, I can use the n-up feature on my printer, but that shrinks the whole page down really small.</li>
<li><strong>Searching</strong>: How good is the recipe search?</li>
<li><strong>Adding/Editing</strong>: While I will be reading, searching and printing recipes most often, I&#8217;m going to be most annoyed at a program while adding a recipe by hand.</li>
<li><strong>Import</strong>: I&#8217;ve been using Yum (see below) for a while, and while I&#8217;m not unhappy with it, it has some major annoyances on recipe entry that keep me looking. Whatever I switch to is going to have to handle importing my Yum database one way or another, without screwing it up. Additionally, since I&#8217;ll be looking at the latest version of Yum, I want to see the external import techniques (from text or the Web).</li>
<li><strong>Extras</strong>: What extras exist for the program? Can I easily transfer a recipe to my iPhone or iPod Touch? Does it have an extensive ingredient list with nutrition data to give a rough approximation of the caloric content? These things aren&#8217;t going to be deal breakers, but if everything else works, they could be deal makers.</li>
</ul>
<p>There are more programs available than I am reviewing here. A number of these programs presented problems early enough in the review process that I didn&#8217;t think it was worth spending any more time on them.</p>
<p>One that I wish had been better was <a href="http://www.shallotpatch.com/MeasuringCup/index.html">Measuring Cup</a>. It has some really interesting ideas including sub-recipes and not distinguishing view and edit modes. Unfortunately, it doesn&#8217;t have any import facility to speak of, and the controls on the lists are non-standard and finicky. It&#8217;s worth looking at if you&#8217;re just starting your recipe collection. I&#8217;m not.</p>
<div class="toc">
<ol>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-connoisseur-1-2"><a href="http://www.connoisseurx.com/">Connoisseur 1.2</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-cookware-deluxe-3-2"><a href="http://www.digitalfriedchicken.com/CookWare.html">Cookware Deluxe 3.2</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-macgourmet-2-3"><a href="http://www.macgourmet.com/">MacGourmet 2.3</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-souschef-1-0-1"><a href="http://acaciatreesoftware.com/">SousChef 1.0.1</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-yum-3-0"><a href="http://yum-mac.com/">Yum 3.0</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-yummysoup-1-6-9-5"><a href="http://hungryseacow.com/">YummySoup! 1.6.9.5</a></a></li>
<li><a href="http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/#toc-the-verdict">The Verdict</a></li>
</ol>
</div>
<h2 id="toc-connoisseur-1-2"><a href="http://www.connoisseurx.com/">Connoisseur 1.2</a></h2>
<p>Only Connoisseur 1.2 is available for direct download; there is a beta version referred to, but you must contact the developer for this information.</p>
<ul>
<li><strong>Browsing</strong>: <em>A</em> Connoisseur has fairly good browsing. It&#8217;s laid out much like iTunes with a &#8220;sources&#8221; list on the left and three filtering criteria on the main panel under the toolbar: Cuisine, Course, and Ingredient. This will make it easy to find recipes based on the ingredients you have at hand and the meal you&#8217;re serving.<br />
You can great new &#8220;groups&#8221; (recipe collections/folders) and smart groups (groups with search criteria) pretty easily.</li>
<li><strong>Reading</strong>: <em>C+</em> After browsing to the recipe, or searching for it, you double click on the recipe in the main list to display it<sup><a class='footnote' id='note-539-1' href='#footnote-539-1'>1</a></sup> in a smaller (but resizable) display window. The window isn&#8217;t bad, but it&#8217;s too loose: the recipe metadata (such as cook time, yield, etc.) takes up far too much space; blank fields are shown; ingredient lines are 1¼ linespacing, which is too much.<br />
On the up-side, there&#8217;s a nice &#8220;Cooking View&#8221; that fills the screen with the recipe. The directions are too widely spaced, but this is a much better &#8220;view&#8221; than the default windowed view. As a nice touch, Connoisseur will also read the recipe steps to you.</li>
<li><strong>Printing</strong>: <em>F</em> Everything that&#8217;s wrong with the display window is wrong with the print function, and it has additional sins of commission. The linespacing per field appears to be about 1½ and the ingredients are still 1¼. The empty fields don&#8217;t show here, but the amount of space taken up by the metadata eats up half of the first page. Worse, the metadata is incomplete: it&#8217;s cropped if it goes over a certain (small) width. The directions for a &#8220;2-Minute Fudge&#8221; included with Connoisseur don&#8217;t begin until page two—and the heading &#8220;Directions&#8221; is on page one. The directions are cropped if they&#8217;re over a certain (small) width.</li>
<li><strong>Searching</strong>: <em>F</em> ⌘F and ⌘⌥F don&#8217;t work for search. As far as I can tell, aside from the filtering mechanisms mentioned in browse, there&#8217;s no way to search for a recipe.</li>
<li><strong>Adding/Editing</strong>: <em>F</em> I&#8217;m not sure where to begin with the problems presented by Connoisseur&#8217;s add/edit recipe sheet. When adding or editing a recipe, you are presented with a modal sheet on the main program window. If you&#8217;re copying information from another recipe, you have to first have displayed that recipe in a separate window before you start editing the current one. The recipe sheet is tabbed and has far too many controls on it (at the bottom of the sheet is a help question mark, previous, next, a &#8220;cooked&#8221; checkbox, cancel, and save. The recipe scaling feature looks impressive, but I&#8217;m not sure why it&#8217;s part of the recipe editing—this is something that Connoisseur should be able to figure out automatically, on the fly.<br />
The ingredients and directions are on separate tabs, requiring flipping tabs to make sure you&#8217;re correctly using all of the ingredients as you&#8217;re writing the recipe down (as someone who creates recipes from time to time, this matters). Ingredient and direction entry is more complex than it should be, relying on +/- buttons on each and every ingredient and step.</li>
<li><strong>Import</strong>: <em>B</em> Will not import directly from the Yum database format, but recognized the Yum XML format reasonably well. The import itself was fairly pedestrian, although my imported recipes had stupid errors, such as: &#8220;2.  1. In a small bowl…&#8221; There&#8217;s some level of intelligence that should be applied here. There&#8217;s no import from a webpage, and the import from text is a little hit-and-miss (in my test of a copied recipe from the New York Times, the instructions were inserted as ingredients, possibly because they were numbered).</li>
<li><strong>Extras</strong>: There&#8217;s a nice set of default recipes included. You can add a recipe to a shopping list and export it to an iPod as a list, or to the Palm program &#8220;HandyShopper&#8221; and &#8220;SplashShopper&#8221; (which would be useful if I used a Palm device anymore). There&#8217;s an online component for shared recipes and you can download others&#8217; shared recipes, too. It looks like there&#8217;s a moderation process to the recipes, though.</li>
</ul>
<p>This is not a program that I would recommend to anyone at this point. It looks pretty, and the filtering mechanism is superb, but I don&#8217;t think that this is a usable program.</p>
<h2 id="toc-cookware-deluxe-3-2"><a href="http://www.digitalfriedchicken.com/CookWare.html">Cookware Deluxe 3.2</a></h2>
<ul>
<li><strong>Browsing</strong>: <em>B-</em> Cookware Deluxe starts in a recipe view, requiring explicit switching to a browser. The browse interface is a filtering interface that&#8217;s rather busy and confusing. The display has three panels. The recipes are in the main panel on the right, and there is a switch (&#8221;First/Any&#8221;, defaulting to &#8220;First&#8221;), followed by the alphabet, &#8220;All&#8221;, and a heart symbol. Clicking on a letter will filter the display of recipes based on the presence of that letter at the beginning of a word in the recipe name; if the switch is set to &#8220;first&#8221;, only the first word is considered. Clicking on &#8220;All&#8221; clears the filters and clicking on the heart selects &#8220;collected&#8221; recipes (those that carry from version to version).<br />
The upper panel on the left has five tabs that act as filters: Cookbook, Ingredient, Region, Course, Bev (the alcoholic beverage one would have with the recipe, generally limited to wines and some beers). These filters are not co-operative filters; they work independently (one cannot select an ingredient of &#8220;Asparagus&#8221; and a beverage of &#8220;Pinot Grigio&#8221; to filter for recipes that call for both). The lower panel are for saved search templates (loading a saved search goes to the Find window) and menu sets (collecting several recipes that are intended to go together as a meal). Clicking on &#8220;All&#8221; above the menu list removes any of the filters applied from the left panel, too.<br />
Cookware Deluxe also has a planner view where meals and menus can be planned in advance. There&#8217;s both a monthly calendar and a weekly calendar view (called &#8220;Planner&#8221; and &#8220;Details&#8221;, confusingly). There is no option to make Monday the beginning of the week.</li>
<li><strong>Reading</strong>: The recipe display panel is fairly decent, divided into two panels (a large upper panel shaped like a recipe card and a lower tabbed panel). The recipe card is divided into three columns. The first column is a quarter of the entire card and contains the name of the recipe, a tabbed box for photographs of the recipe, and other important metadata (cooking time, oven pre-heat temperature, difficulty).<br />The second column is the ingredient column and also takes up a quarter of the recipe card. The third column has a small toolbar (about ¹/₁₀ of the vertical space), a description area (about ²/₁₀ of the vertical space), and the directions. The toolbar over the directions provide a checkbox (&#8221;Multi-Print&#8221;), four buttons (Tools, Custom Print Layout, User Prefs, and Large Print Display), another checkbox (&#8221;Collected Recipe&#8221;, see above), and a bronze badge with a check mark inside for checking spelling.<br />The font in all of these sections is small, but there are two icons of interest for this: in the lower left hand of the card is an icon that looks like a two item bar graph. Clicking on the taller bar zooms the interface larger; the shorter bar zooms it smaller (and it will go smaller than the default). In the toolbar over the directions column the last button will display the current recipe in a window with a much larger font for viewing from a distance. It&#8217;s not as good as Connoisseur&#8217;s full screen display, but it works (it also only shows the ingredients and directions.<br />
The bottom tabbed panel allows for category information (cookbooks, course, main ingredient, region, beverage, source, recipes it requires, and recipes that work well with it); additional source information, Weight Watchers™ points, and nutritional data (unformatted and <a href="http://www.digitalfriedchicken.com/NoNutrition.html">not calculated on purpose</a>); and notes and substitutions.</li>
<li><strong>Printing</strong>: <em>A-</em> Very strong. Includes the ability to customize where each section of a recipe, although the sections themselves include very weak formatting. The &#8220;Multi-print&#8221; selection (in recipes and the browse list) allows you to print multiple recipes on a single page (if they fit).</li>
<li><strong>Searching</strong>: Has relatively strong search capabilities, but the layout is pretty confusing.</li>
<li><strong>Adding/Editing</strong>: <em>B-</em> Recipes can only be created from the &#8220;Recipe&#8221; view; not from the &#8220;Browser&#8221; view. The strengths of the recipe view are present, but each of the fields is unformatted, leaving it to the user to know the appropriate abbreviations and names of each ingredient. This makes for easy cut and paste, but explains why the &#8220;main ingredient&#8221; must be entered separately; the ingredients are not stored individually, but in aggregate. Note that I did not attempt drag and drop adding, but I would expect it to work well given the lack of formatting in the fields.</li>
<li><strong>Import</strong>: <em>C-</em> Only supports importing past CookWare recipes, recipe sets, and MasterCook recipes. This is found under the application menu, not a &#8220;File&#8221; menu.</li>
<li><strong>Extras</strong>: Supports an iPod cookbook or recipe (presumably just a text note). Supports QuickTime movies for each recipe. Has a Windows version.</li>
</ul>
<p>This is another program that I can&#8217;t recommend. There are some nice features, but this program is written on top of FileMaker and it feels like it. The layout is crowded and hard to read; if there&#8217;s been thought given to making this program easier to use, it seems to have been hampered by FileMaker forms options.</p>
<h2 id="toc-macgourmet-2-3"><a href="http://www.macgourmet.com/">MacGourmet 2.3</a></h2>
<p>MacGourmet and <a href="http://www.marinersoftware.com/sitepage.php?page=130">MacGourmet Deluxe</a> are essentially the same program. MacGourmet Deluxe includes all of the available MacGourmet plug-ins (&#8221;Cookbook&#8221;, &#8220;Mealplan&#8221;, and &#8220;Nutrition&#8221;) and is a better value than buying the plug-ins individually. Because the plug-ins are extra for MacGourmet, I will only cover them in the <em>Extras</em> section of the review.</p>
<ul>
<li><strong>Browsing</strong>: <em>B+</em> The interface for MacGourmet looks like the Apple Mail or NetNewsWire interface with sources and folders on the left, a recipe index on the top right and recipe details on the bottom right. There are two views for the recipe index: a standard tabular view and a simplified image, name, source, and rating view.  By default, the simplified view only shows two recipes at a time; the standard view shows seven.</li>
<li><strong>Reading</strong>: <em>A</em> The recipe layout is beautiful. The ingredients are in a formatted box with the source, yield, pictures, and other metadata on the right side of the recipe<sup><a class='footnote' id='note-539-2' href='#footnote-539-2'>2</a></sup>. The directions are below the ingredients. There&#8217;s a very readable chef view; as a nice touch, if multiple recipes are selected, the chef view is a tabbed interface, one tab per recipe. In the standard view, only one recipe can be displayed at a time; multiple  recipes can be displayed in separate chef view windows as well.</li>
<li><strong>Printing</strong>: <em>A</em> Standard printing facilities are superb and support printing on Avery 3&#215;5 and 4&#215;6 cards as well as several other templates.</li>
<li><strong>Searching</strong>: <em>A</em> Simple but effective rule-based &#8220;cupboard&#8221; searching (like Spotlight) with ⌘F. ⌘⌥F provides access to the quick search box, which is very effective. Explicit note, recipe, and wine note searches are also available.</li>
<li><strong>Adding/Editing</strong>: <em>B-</em> Some of the problems seen in Connoisseur&#8217;s add/edit screen are here to a lesser degree. By default the recipe add/edit screen isn&#8217;t a modal sheet (but it can be configured as such), but it is a modal dialog that blocks the main view. Otherwise, it takes an iTunes approach to editing: multiple tabs for Info, Ingredients, Directions, Preparation, Notes, Picture, and Nutrition data (which can be calculated from the ingredient list). The ingredients list is pretty easy to use, but there are two columns of checkboxes (&#8221;D&#8221; and &#8220;M&#8221;) which aren&#8217;t explained in the help documents. &#8220;D&#8221; marks the ingredient line as a descriptive title separating distinct portions of the ingredient list; I haven&#8217;t figured out what &#8220;M&#8221; does. The other sections are unformatted text entry.</li>
<li><strong>Import</strong>: <em>A</em> Importing is strengthened by the clippings section to turn clipboard results into recipes relatively quickly. Featured recipes from MacGourmet.com and Amazon.com are also automatically importable through the &#8220;Featured&#8221; section. It supports importing from Yum, but only imported 70 of the 116 recipes that I have in Yum; I&#8217;m not sure if this is a demo limitation or not.</li>
<li><strong>Extras</strong>: There&#8217;s a shopping list, a generic note list, and wine notes. Easily supports publishing to standalone sites or weblogs (the ability to use a weblog publisher like MarsEdit would be nice).<br />
The Cookbook Builder plug-in is a fairly nice idea and works reasonably well (drag and drop recipes into the appropriate places), although I don&#8217;t think it&#8217;s something that I would use often, if at all. The meal planner works similarly but is a little finicky as to where things should be dragged (if I drag the &#8220;breakfast&#8221; meal into the day area, even if it&#8217;s not on the day row, the &#8220;breakfast&#8221; meal should land in the right spot; don&#8217;t make me care about your hierarchies when adding—you just need to do the right thing). It&#8217;s nice that the meal planner can easily become a shopping list. The nutritional plug-in is a little confusing as to <em>how</em> it works at first (you need to edit the recipe to calculate the nutritional value for it based on ingredients), but it does a very nice job of calculating once it&#8217;s clear.</li>
<li><strong>Update</strong>: Michael Dupuis, the developer of MacGourmet, indicated that the Yum import failure with MacGourmet is related to an XML format change in the Yum format, not a limitation in the demo. This will be fixed in the next update of MacGourmet. I discovered that I had forgotten to put a grade on the Import feature. He also mentioned that the &#8220;D&#8221; and &#8220;M&#8221; checkboxes in recipes are explained on pages 23–24 of the user guide as &#8220;Divider&#8221; (descriptive title, as I surmised) and &#8220;Main Ingredient&#8221;. Finally, the post editor allows you to choose an extern blog posting tool such as MarsEdit by choosing it under the &#8220;Post using&#8221; menu.
</li>
</ul>
<p>This is a <em>great</em> program. There&#8217;s enough here that I can possibly see replacing Yum with MacGourmet. I suspect that although I don&#8217;t see myself using the cookbook builder, I would consider using the meal planner and the nutrition calculator, so I might go with MacGourmet Deluxe.</p>
<h2 id="toc-souschef-1-0-1"><a href="http://acaciatreesoftware.com/">SousChef 1.0.1</a></h2>
<ul>
<li><strong>Browsing</strong>: <em>A-</em> The app is divided into three panels: a source list, a recipe list, and a recipe display. It looks very much like the Address Book application provided with Mac OS X. The source list contains a master recipe library, a search results entry, recent imports, and then user-added folders and collections. Folders can only contain collections; collections contain recipes. Collections are associative; recipes can belong to more than one collection at a time. Deleting a recipe from a collection only deletes it from the collection; it does not appear that there is a way to delete a recipe from the recipe library permanently except using the recipe library view.</li>
<li><strong>Reading</strong>: <em>A</em> The reading pane is clear, well laid out, and easy to read. This is not as flexible as the display in MacGourmet, but I am pleased to say that it&#8217;s easily readable. The full-screen &#8220;Cook&#8221; view is the best I&#8217;ve seen in any of these programs: it will not only speak your recipe (which Connoisseur also does), but you can also turn on voice recognition so that you can tell it you want the next instruction to be read. Drop down menus in the ingredients list let you search for other recipes with this ingredient with ease.</li>
<li><strong>Printing</strong>: <em>B-</em> The print layout is functional and well laid out, but you can&#8217;t print more than one recipe at a time.</li>
<li><strong>Searching</strong>: <em>A+</em> Excellent search on ingredients, name, category, or cuisine. Simultaneously searches local and &#8220;cloud&#8221; recipes.</li>
<li><strong>Adding/Editing</strong>: <em>A-</em> Heavy reminders of Address Book here; ingredients and directions are added and removed with the red &#8220;-&#8221; and green &#8220;+&#8221; circles. Can&#8217;t drag and drop ingredients, and the green &#8220;+&#8221; isn&#8217;t always visible on entry. Sub-recipes (the crust for a cheesecake) are handled manually (possibly poorly). Directions are automatically numbered. Notes are automatically bulleted.</li>
<li><strong>Import</strong>: <em>B</em> Can only import one recipe at a time essentially from the clipboard or a single text file. Does not handle heavily formatted recipes well. No support for Yum importing.</li>
<li><strong>Extras</strong>: Blogging, although how it works is not clear without a licence. &#8220;Cloud&#8221; recipe sharing of recipes in yours and others cookbooks.</li>
</ul>
<p>This is another program that I really like. I&#8217;m not happy about the state of import for multiple recipes—I have an extensive collection that I want to import already. Conversion utilities would be very useful here. I&#8217;d also like to see print improved some, or at least some sort of iPhone integration.</p>
<h2 id="toc-yum-3-0"><a href="http://yum-mac.com/">Yum 3.0</a></h2>
<p>Yum was recently acquired by &#8220;Dare to be Creative&#8221; and has been turned into a shareware program as of Yum 3.0. I&#8217;m currently using Yum 2.7.4 which is no longer supported. I&#8217;m reasonably happy with Yum 2.7.4. This review is based on the trial version of Yum 3.0.</p>
<ul>
<li><strong>Browsing</strong>: <em>A-</em> Like several other recipe programs, Yum uses a 3 column layout. In this case, it&#8217;s category, recipe list, and then the recipe itself.  Categories are associative (and in Yum 2.7.4, able to be managed in the &#8220;categories drawer&#8221;; this appears to be read-only in Yum 3). A nice touch carried over from Yum 2.7 is that when you select a recipe, all of the categories to which it belongs are highlighted (similar to Address Book).</li>
<li><strong>Reading</strong>: <em>A-</em> Simple, well-laid out. Ingredients are always on the left; the method (directions) are always on the right. There&#8217;s a full-screen mode, but the default configuration misses the point (it doesn&#8217;t increase the font size at all)—you need to go into the Format|Manage Layouts and change the &#8220;step-by-step&#8221; layout to &#8220;Step-by-Step&#8221; to be meaningful.</li>
<li><strong>Printing</strong>: <em>A-</em> Layouts can be edited (it&#8217;s not completely clear how they work) and multiple recipes can be printed on a single page if they fit. Layout is <em>completely</em> customizable (but I have never done so).</li>
<li><strong>Searching</strong>: <em>B+</em> It works well enough, but there&#8217;s no keyboard shortcut.</li>
<li><strong>Adding/Editing</strong>: <em>B+</em> Fairly good adding and editing. It&#8217;s been improved from 2.7 (which allowed the method to be formatted rich text). Automatically converts fractions to their proper display form. Has a &#8220;paste ingredients&#8221; for quick addition from a copied list. Scaling is done in here and not elsewhere.</li>
<li><strong>Import</strong>: Imports from Yum, MasterCook, and XML only. Doesn&#8217;t have a single recipe import mode (although &#8220;paste ingredients&#8221; helps with that).</li>
<li><strong>Extras</strong>: Now comes with a shopping list mode.</li>
</ul>
<p>This is a fair update to a good recipe manager. I&#8217;m not sure that it&#8217;s worth the shareware cost, when others that offer more features are just a few dollars more. However, I am excited to see that Yum has been acquired and is under active development again; I would not be surprised to see Yum become a viable competitor to YummySoup!, MacGourmet, and SousChef moving forward.</p>
<h2 id="toc-yummysoup-1-6-9-5"><a href="http://hungryseacow.com/">YummySoup! 1.6.9.5</a></h2>
<p>I&#8217;ve tried YummySoup! a few times and never been quite convinced by it.</p>
<ul>
<li><strong>Browsing</strong>: <em>A</em> Like MacGourmet, this is somewhat reminiscent of Mail or NetNewsWire; there&#8217;s a source list on the left and recipes on the right. There&#8217;s both the &#8220;My Library&#8221; and the &#8220;Online Library&#8221; view for viewing and sharing recipes online. The default recipe index (top right panel) is the image browser. This isn&#8217;t quite Recipe CoverFlow, but it&#8217;s pretty damned close. This view alone argues in favour of taking pictures of your masterpieces. There&#8217;s also a standard tabular view which is clear and readable. There are both groups (folders) and smart groups (live search folders); groups are associative (recipes can exist in more than one group at a time). Recipes can be removed from a group or from the library.</li>
<li><strong>Reading</strong>: <em>B+</em> Functional and pleasant, but it still puts metadata at the top and too prominent. The first thing I care about when looking at a recipe is the ingredients. I don&#8217;t care about the source, difficulty, ethnicity or anything else. The full screen view is well done, but not as nice as SousChef (and, to be honest, I don&#8217;t care about the recipe picture in full screen mode).</li>
<li><strong>Printing</strong>: <em>C+</em> Only one recipe can be printed at a time. Standard print format.</li>
<li><strong>Searching</strong>: <em>B</em> No keyboard shortcut. It works well from the search box, and the smart groups really are smart.</li>
<li><strong>Adding/Editing</strong>: <em>A-</em> A modal sheet for editing, but everything is on one pane (no tabs!). Easily make new ingredient groups; good auto-fill values. Bullet (●), ℃ and ℉ buttons. It gets nearly everything right (modal?).</li>
<li><strong>Import</strong>: <em>B+</em> Doesn&#8217;t support importing from Yum; I could import Connoisseur or MacGourmet recipes if I wanted to. Importing from a web site could not be easier (and works very similarly to SousChef; YummySoup! had it first, though).</li>
<li><strong>Extras</strong>: An easy to use grocery list; a liquor cabinet tracker. Online publishing (via email to HungrySeacow) and downloading.</li>
</ul>
<p>I&#8217;m still undecided about what to think about YummySoup!. I like what it has, but it has some weaknesses that I&#8217;m not fond of. I don&#8217;t think that it&#8217;s as good as MacGourmet or SousChef.</p>
<h2 id="toc-the-verdict">The Verdict</h2>
<p>Tonight, the verdict is to change nothing—I&#8217;m not convinced that the alternatives are worth the price today (including the new Yum 3.0), and the stronger contenders (MacGourmet, SousChef, YummySoup!, Yum 3.0) have serious flaws with how I need to use a recipe management program. If I were forced to make a choice, I think that MacGourmet Deluxe would be the winner, but I&#8217;m not sure that the expense is worth the time and effort it would take me to switch. I really want to like SousChef, but it&#8217;s not quite there yet for me.
<div class='footnotes'>
<h4>Notes</h4>
<ol class='footnotes'>
<li id='footnote-539-1'><a href='#note-539-1'>&uarr;1</a> A preference allows this to be changed to &#8220;edit.&#8221; </li>
<li id='footnote-539-2'><a href='#note-539-2'>&uarr;2</a> This is controlled by the display template and style, which suggests that user styles are possible. </li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/11/23/mac-recipe-management-programs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Aw, Damn (Au Revoir, M Decoux)</title>
		<link>http://www.halostatue.ca/2008/09/25/aw-damn-au-revoir-m-decoux/</link>
		<comments>http://www.halostatue.ca/2008/09/25/aw-damn-au-revoir-m-decoux/#comments</comments>
		<pubDate>Fri, 26 Sep 2008 03:43:28 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=528</guid>
		<description><![CDATA[Guy Decoux, an extraordinary Rubyist, died earlier this month in tragic circumstances.
He will be missed by the community.
_why has some of the best commentary on this.
There&#8217;s already talk of a permanent addition to Ruby in his honour, $ABOUT.ts (&#8221;ts&#8221; was his email address), and Ruby Central is considering naming something (possibly a grant) in his [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/70b8cce2be8efbd3?pli=1">Guy Decoux</a>, an extraordinary Rubyist, died earlier this month in tragic circumstances.</p>
<p>He will be missed by the community.</p>
<p><a href="http://hackety.org/2008/09/25/legendNeverToBeSolved.html">_why</a> has some of the best commentary on this.</p>
<p>There&#8217;s already talk of a permanent addition to Ruby in his honour, $ABOUT.ts (&#8221;ts&#8221; was his email address), and Ruby Central is considering naming something (possibly a grant) in his honour.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/09/25/aw-damn-au-revoir-m-decoux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vacationing with the iPhone</title>
		<link>http://www.halostatue.ca/2008/09/02/vacationing-with-the-iphone/</link>
		<comments>http://www.halostatue.ca/2008/09/02/vacationing-with-the-iphone/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 03:54:54 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=522</guid>
		<description><![CDATA[This past August, my wife and I went out to Nova Scotia with my parents in their RV1. I&#8217;ll be uploading some of the better pictures I took to my Flickr stream in the near future2.
My parents tell me that they have wireless access in a campground more often than they don&#8217;t. Of the campgrounds [...]]]></description>
			<content:encoded><![CDATA[<p>This past August, my wife and I went out to Nova Scotia with my parents in their RV<sup><a class='footnote' id='note-522-1' href='#footnote-522-1'>1</a></sup>. I&#8217;ll be uploading some of the better pictures I took to my Flickr stream in the near future<sup><a class='footnote' id='note-522-2' href='#footnote-522-2'>2</a></sup>.</p>
<p>My parents tell me that they have wireless access in a campground more often than they don&#8217;t. Of the campgrounds we went to this summer, exactly <em>three</em> had any Internet access at all, and only <em>one</em> was reachable from where we were parked.</p>
<p>Intrepid road warriors, we kept up with our email and other web browsing most days through the iPhone. Even in Cape Breton on the Cabot Trail, we had decent EDGE data signal through the Rogers network<sup><a class='footnote' id='note-522-3' href='#footnote-522-3'>3</a></sup>. For eighteen of our twenty-two days away from Toronto, the iPhone was our only meaningful Internet access. It performed like a champ. We even got tickets to see Neil Young at the Air Canada Centre in December while rolling down the road.</p>
<p>My parents also use Microsoft Streets &#038; Trips with an attached GPS for navigation. More than once, the iPhone with its GPS and Internet connection (and Google Maps) gave us better directions than Streets &#038; Trips. There was one notable incident where Streets &#038; Trips put us in the Atlantic, but Google Maps on the iPhone gave us the right directions<sup><a class='footnote' id='note-522-4' href='#footnote-522-4'>4</a></sup></p>
<p>The iPhone is too small to be practical for extended use as your sole access to the Internet. It is an excellent adjunct to a standard laptop or other computer and I don&#8217;t regret the purchase or contract at all. I have some ideas on how a good web tablet might work, based on my use of the iPhone and a Tablet PC, but I&#8217;m going to let them percolate a bit before I publish them.
<div class='footnotes'>
<h4>Notes</h4>
<ol class='footnotes'>
<li id='footnote-522-1'><a href='#note-522-1'>&uarr;1</a> We call it &#8220;The Bus&#8221;, since it&#8217;s a 40-foot Mandalay with four slides, resulting in about 400 square feet of living space when parked. </li>
<li id='footnote-522-2'><a href='#note-522-2'>&uarr;2</a> …which will flood my Tumblr and FriendFeed, but such is life. </li>
<li id='footnote-522-3'><a href='#note-522-3'>&uarr;3</a> Our level of access was predicted to be minimal by some Haligonians on Segways, advertising for Aliant—a competitor. </li>
<li id='footnote-522-4'><a href='#note-522-4'>&uarr;4</a> This was in part because I used the <em>address</em> and not the name. Google Maps shows the wrong location for <a href="http://maps.google.ca/maps?q=Lunenburg+County+Winery&#038;ie=UTF8&#038;ll=44.311543,-64.30845&#038;spn=0.005228,0.009205&#038;t=h&#038;z=17">Lunenburg County Winery</a>, but the right location for <a href="http://maps.google.ca/maps?f=q&#038;hl=en&#038;geocode=&#038;q=Lunenburg,+Nova+Scotia,+B0J+2E0&#038;ie=UTF8&#038;ll=44.539223,-64.373703&#038;spn=0.041662,0.073643&#038;t=h&#038;z=14&#038;iwloc=addr">Lunenburg, Nova Scotia, B0J 2E0</a>. Go figure. </li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/09/02/vacationing-with-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GNU GPLed Software and the iPhone</title>
		<link>http://www.halostatue.ca/2008/08/26/gnu-gpled-software-and-the-iphone/</link>
		<comments>http://www.halostatue.ca/2008/08/26/gnu-gpled-software-and-the-iphone/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 04:27:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=504</guid>
		<description><![CDATA[Last month, Aristotle Pagaltzis claimed that &#8220;John Gruber doesn&#8217;t understand freedom&#8220;. This is in response to Gruber&#8217;s post about the release of the WordPress iPhone application source code.
Unsurprisingly, Aristotle is probably wrong, as is the FSF. Their own history with respect to running applications on non-GNU GPLed operating systems suggests this. I&#8217;m going to briefly [...]]]></description>
			<content:encoded><![CDATA[<p>Last month, Aristotle Pagaltzis claimed that &#8220;<a href="http://plasmasturm.org/log/512/">John Gruber doesn&#8217;t understand freedom</a>&#8220;. This is in response to Gruber&#8217;s post about the release of the WordPress iPhone application <a href="http://daringfireball.net/linked/2008/07/24/wordpress-iphone">source code</a>.</p>
<p>Unsurprisingly, Aristotle is probably wrong, as is the FSF. Their own history with respect to running applications on non-GNU GPLed operating systems suggests this. I&#8217;m going to briefly address Aristotle&#8217;s comments in regards to the FSF&#8217;s definition of &#8220;free software&#8221;<sup><a class='footnote' id='note-504-1' href='#footnote-504-1'>1</a></sup>.</p>
<blockquote><blockquote>The freedom to study how the program works, and adapt it to your needs (freedom 1). Access to the source code is a precondition for this.</p></blockquote>
<p>Study? Yes. Adapt? Technically, with the source code, yes, except, without a developer key from Apple the most useful thing I can do with the changed source code is print it out and use that as… toilet paper.</p></blockquote>
<p>On many Unixes, compilers were an added cost. This still remains true on some platforms (and <code>gcc</code> isn&#8217;t an acceptable replacement on some platforms). Without access to a compiler, the most useful thing you can do with the changed source code is, as Aristotle says, toilet paper. Note as well that there&#8217;s <em>still</em> the &#8220;Operating System exception&#8221; in the use of the GNU GPL. Specifically, I can use any services or libraries provided by the operating system without infecting the operating system or the GNU GPLed software that I&#8217;m compiling.</p>
<p>You may as well complain that the development toolchain requires that you purchase a Macintosh computer to write an iPhone application, since there&#8217;s no version for Windows or Linux. (Nor is there likely to ever be.) I see the requirement for a developer key as analogous to the requirement of a compiler and easily falling under the &#8220;Operating System exception&#8221; for execution purposes.</p>
<blockquote><blockquote>The freedom to redistribute copies so you can help your neighbor (freedom 2).</p></blockquote>
<p>As long as my neighbour is the App Store, I suppose.</p></blockquote>
<p>You can still do this, either through ad hoc distribution or through Apple&#8217;s own system. You can <em>also</em> redistribute the changed source without limitation. The GNU GPL says <em>nothing</em> about requiring that distributions be binary distributions.</p>
<blockquote><blockquote>Being free to do these things means (among other things) that you <strong>do not have to ask or pay for permission</strong> [emphasis mine].<br />
You should also have the freedom to make modifications and use them privately in your own work or play, <strong>without even mentioning that they exist</strong>. If you do publish your changes, <strong>you should not be required to notify anyone in particular, or in any particular way</strong> [ditto].</p></blockquote>
<p>Uhm, except Apple, right? Right?</p></blockquote>
<p>This is where Aristotle has gone completely off the rails with respect to iPhone software development.</p>
<p>As a license agreement, the GNU GPL does not impose—nay, <em>cannot</em> impose—requirements on third parties. This is partially the source of the &#8220;Operating System exception&#8221;; you cannot force IBM to release the source of AIX just because you build, run, and/or distribute a GNU GPLed piece of software on it. (If you want to write well-accepted software for AIX, you&#8217;re not going to use <code>gcc</code>; you&#8217;re going to use IBM&#8217;s <code>xlC</code>, which is really expensive.)</p>
<p>I can, without limitation, make modifications to the WordPress iPhone application and use it privately with my developer key. I don&#8217;t have to tell anyone that I&#8217;m doing this, at all. (My iPod Touch still has some demo programs on it.) I can also, without limitation, post my modified source (which, again, is <em>all</em> the GNU GPL gives a damn about) anywhere I want without telling anyone else anything about it.</p>
<p>What I <em>can&#8217;t</em> do, without going through the App Store, is publish a compiled binary for other people to use without having to effectively buy the compiler.</p>
<p>But none<sup><a class='footnote' id='note-504-2' href='#footnote-504-2'>2</a></sup> of my rights under the GNU GPL have been violated. Period. Because the GNU GPL <em>just</em> cares about the software in the abstract, not in a specific compiled form.</p>
<blockquote><p>I guess those silly hippies at the Free Software Foundation were right.</p></blockquote>
<p>I guess those silly hippies forgot to read their own licence and recognise their own history when it comes to their licence. You and I might prefer a more open App Store with fewer restrictions on what software can run and how it could be distributed, but nothing about iPhone software development violates the GNU GPL, as much as people would love to pretend that it does.
<div class='footnotes'>
<h4>Notes</h4>
<ol class='footnotes'>
<li id='footnote-504-1'><a href='#note-504-1'>&uarr;1</a> This is <em>1984</em>-style propaganda, pure and simple. GNU GPLed software isn&#8217;t &#8220;free&#8221;; it&#8217;s encumbered. Those encumbrances may be for a greater good, but <strong>stop lying</strong> and calling it &#8220;free&#8221;. There&#8217;s absolutely no need for that crap. </li>
<li id='footnote-504-2'><a href='#note-504-2'>&uarr;2</a> Yes, none. I can give you the .ipa file for an iPhone application if you want it; you just have no way to install it on your device to make it run. But the GNU GPL doesn&#8217;t require that I give binaries out at will, but it does require that the source be made freely available to recipients of binaries. </li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/08/26/gnu-gpled-software-and-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Revisiting the iPhone on Rogers/Fido</title>
		<link>http://www.halostatue.ca/2008/07/13/revisiting-the-iphone-on-rogersfido/</link>
		<comments>http://www.halostatue.ca/2008/07/13/revisiting-the-iphone-on-rogersfido/#comments</comments>
		<pubDate>Sun, 13 Jul 2008 14:16:52 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Toronto]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=496</guid>
		<description><![CDATA[A few days ago, I wrote that I wasn&#8217;t planning on getting the iPhone under the data plans that Rogers/Fido offered offered.
I didn&#8217;t.
When they offered the $30/6 GB data plan, I started looking at my options and on Friday, I ordered an iPhone (16 GB, Black) with the $30/6 GB data plan, combined with my [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://www.halostatue.ca/2008/06/28/rogersfido-the-iphone-and-me/">few days ago</a>, I wrote that I wasn&#8217;t planning on getting the iPhone under the data plans that Rogers/Fido offered offered.</p>
<p>I didn&#8217;t.</p>
<p>When they offered the $30/6 GB data plan, I started looking at my options and on Friday, I ordered an iPhone (16 GB, Black) with the $30/6 GB data plan, combined with my existing 300 minute plan totalling out at $75. I don&#8217;t have Visual Voicemail or text messages with this, but I can add Visual Voicemail and a few other features for $15 per month, so for $90 a month I&#8217;m getting a pretty good plan—and I don&#8217;t have to give up my long distance option.</p>
<p>I may shift my voice plan around a bit since the plan that I&#8217;m on has been grandfathered in and includes voicemail already (which I won&#8217;t need with Visual Voicemail) and I&#8217;m pretty sure that I can save some money doing that.</p>
<p>Even better, since I ordered my iPhone on-line, it&#8217;ll arrive sometime next week (without having to stand in line) and it&#8217;s going to be $48 dollars cheaper than it would have been because I had 48 &#8220;Fido Dollars&#8221; in rewards.</p>
<p>Go me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/07/13/revisiting-the-iphone-on-rogersfido/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rogers/Fido, the iPhone, and Me</title>
		<link>http://www.halostatue.ca/2008/06/28/rogersfido-the-iphone-and-me/</link>
		<comments>http://www.halostatue.ca/2008/06/28/rogersfido-the-iphone-and-me/#comments</comments>
		<pubDate>Sat, 28 Jun 2008 04:24:39 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/?p=495</guid>
		<description><![CDATA[I&#8217;m a happy customer of Fido. Even after Rogers bought them, they didn&#8217;t ruin them.
Now, Rogers has the iPhone. And the best data rates that they&#8217;ve come up with are absolutely insane &#8212; with no unlimited data and that we should feel that their plans are &#8220;High Value&#8221;.
Colour me not interested. Here&#8217;s the text of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a happy customer of <a href="http://www.fido.ca/">Fido</a>. Even after <a href="http://www.rogers.com">Rogers</a> bought them, they didn&#8217;t ruin them.</p>
<p>Now, Rogers has the iPhone. And the best data rates that they&#8217;ve come up with are absolutely insane &#8212; with no unlimited data and that we should feel that their plans are &#8220;High Value&#8221;.</p>
<p>Colour me not interested. Here&#8217;s the text of my feedback to Fido:</p>
<blockquote><p>Thank you for showing that Rogers is both stupid and greedy. I had planned on getting an iPhone in two weeks. Now I will NOT get an iPhone because of your absolutely insane data pricing. You call it &#8220;High Value&#8221; pricing; I call it &#8220;highway robbery&#8221; pricing. When AT&#038;T has a better price plan than you, it strongly suggests that you&#8217;re out of touch. Let me know when your prices return to Earth with an unlimited 3G plan and I&#8217;ll happily upgrade to the iPhone.</p></blockquote>
<p>I should have pointed out, but did not, that I have no problem with the idea that I have to spend $75 or more per month—I&#8217;m already spending a lot of money. But I want <em>value</em> for that money, and Rogers plans are anything but value to the consumer. They&#8217;re a pure rip-off.</p>
<p>That said, there&#8217;s a petition on-line that I refuse to sign, mostly because I refuse to have my name associated with some of the disgusting things (including wishing Ted Rogers bodily harm). I may think that Ted Rogers is a greedy pinhead, but we should act civilized, people. Grow up.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/06/28/rogersfido-the-iphone-and-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why Most People Don&#8217;t Trust Economists, Exhibit 732:</title>
		<link>http://www.halostatue.ca/2008/03/26/why-most-people-dont-trust-economists-exhibit-732/</link>
		<comments>http://www.halostatue.ca/2008/03/26/why-most-people-dont-trust-economists-exhibit-732/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 01:51:35 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Politics]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2008/03/26/why-most-people-dont-trust-economists-exhibit-732/</guid>
		<description><![CDATA[John McCain&#8217;s economics advisor, Kevin Hasset, is quoted by the New York Times as saying:
What really happens is that the economy grows more vigorously when you lower tax rates. It is beyond the reach of economic science to explain precisely why that happens, but it does.
Dani Rodrik calls this shift faith-based economics. I agree.
(Via Dani [...]]]></description>
			<content:encoded><![CDATA[<p>John McCain&#8217;s economics advisor, Kevin Hasset, is <a href="http://www.nytimes.com/2008/03/26/business/26supply.html?_r=1&#038;adxnnl=1&#038;oref=slogin&#038;adxnnlx=1206536490-aYjmqdWzKdc5TqKd3QjNsg">quoted</a> by the New York Times as saying:</p>
<blockquote><p>What really happens is that the economy grows more vigorously when you lower tax rates. It is beyond the reach of economic science to explain precisely why that happens, but it does.</p></blockquote>
<p>Dani Rodrik calls this shift <a href="http://rodrik.typepad.com/dani_rodriks_weblog/2008/03/faith-based-eco.html">faith-based economics</a>. I agree.</p>
<p>(Via <a href="http://rodrik.typepad.com/dani_rodriks_weblog/">Dani Rodrik&#8217;s weblog</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/03/26/why-most-people-dont-trust-economists-exhibit-732/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Common Craft Explains Twitter</title>
		<link>http://www.halostatue.ca/2008/03/05/common-craft-explains-twitter/</link>
		<comments>http://www.halostatue.ca/2008/03/05/common-craft-explains-twitter/#comments</comments>
		<pubDate>Thu, 06 Mar 2008 04:24:52 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2008/03/05/common-craft-explains-twitter/</guid>
		<description><![CDATA[I love this explanation of Twitter from Comon Craft.

(Via Laura Fitton of Pistachio Consulting.)
]]></description>
			<content:encoded><![CDATA[<p>I love this explanation of <a href="http://www.commoncraft.com/Twitter">Twitter</a> from <a href="http://www.commoncraft.com/">Comon Craft</a>.</p>
<p><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/ddO9idmax0o"></param><embed src="http://www.youtube.com/v/ddO9idmax0o" type="application/x-shockwave-flash" width="425" height="350"></embed></object></p>
<p>(Via <a href="http://twitter.com/Pistachio/statuses/767370946">Laura Fitton of Pistachio Consulting</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/03/05/common-craft-explains-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Legend Passes</title>
		<link>http://www.halostatue.ca/2008/03/04/a-legend-passes/</link>
		<comments>http://www.halostatue.ca/2008/03/04/a-legend-passes/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 02:50:00 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2008/03/04/a-legend-passes/</guid>
		<description><![CDATA[So, as most of the gaming world knows, E. Gary Gygax died today.
This begins John C. Welch&#8217;s paean to the more famous of the creators of Dungeons and Dragons. I haven&#8217;t read a lot of them, but I really liked John&#8217;s and really think it&#8217;s worth reading. Wil Wheaton also has some really cool things [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><a href="http://www.bynkii.com/archives/2008/03/goodbye_gary.html">So, as most of the gaming world knows, E. Gary Gygax died today.</a></p></blockquote>
<p>This begins John C. Welch&#8217;s paean to the more famous of the creators of <em>Dungeons and Dragons</em>. I haven&#8217;t read a lot of them, but I really liked John&#8217;s and really think it&#8217;s worth reading. <a href="http://wilwheaton.typepad.com/wwdnbackup/2008/03/across-the-sea.html">Wil Wheaton</a> also has some really cool things to say.</p>
<p>Like many other geeks, I grew up playing D&#038;D. I don&#8217;t remember exactly when I first played, but I know that like Wil, it helped me survive with a few of the other geeks at First Baptist Church School in Charleston, South Carolina. It gave me a ready-made group of friends when we moved to San Antonio, Texas and I was starting at Judson High School. I remember long hours of play with Travis, Randy, and Von. We explored not only D&#038;D, but various other games including <em>Star Frontiers</em>.</p>
<p>D&#038;D was one of the things that helped me survive at Boston University where I knew no one (the other was an early exposure to the Internet of 1989, where IRC channels were <em>numbered</em>, and I played my first MUD—largely based on a mix of D&#038;D and <em>Adventure</em>). Without D&#038;D, there would be no <em>World of Warcraft</em>.</p>
<p>My favourite module to run as a DM has always been <em>Ravenloft</em>. At Boston University, I played with a group of Monty Haulers (one of them had three <em>Wands of Wonder</em>, fully charged, ok?) and they were quite cocky. They hadn&#8217;t met someone who could match them in using the rules. I boosted Strahd—a vampire as nasty as they come, and the main villain of the module—to their power. He was powerful enough to cast <em>Anti-Magic Shell</em>. This spell, for those of you not familiar with D&#038;D, nullifies <em>all</em> magic in a radius of 14 feet for 60 minutes and vampires can <em>only</em> be damaged by silver or magic weapons of a certain strength (+2, I think). What was left unsaid in the rules, and I made a call on, was that vampires weren&#8217;t powered by magic.</p>
<p>Strahd attacked them early on and devastated them by casting <em>Anti-Magic Shell</em>, leaving them with no way to damage him. How did they drive him off? Through an innovative use of their combined magical items. The wizard cast <em>Tensor&#8217;s Floating Disk</em> and then used a <em>Ring of Telekinesis</em> to invert it. They poured five or six bottles of holy water into the inverted disk and then used telekinesis to float the disk over Strahd&#8217;s head. They dispelled the disk and dumped the holy water on his head.</p>
<p>I ran <em>Ravenloft</em> twice more with different groups, and always had a lot of fun. I played more than D&#038;D, getting into Cyberpunk and various super hero games (I always thought <em>Villains and Vigilantes</em> was the best), and kept playing until just over ten years ago. But it was an important part of my life, and something that I won&#8217;t forget. And, as John said:</p>
<blockquote><p>Goodbye Gary, and thanks. My life wouldn&#8217;t have been the same without you.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2008/03/04/a-legend-passes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Save a Lemur: Club Thievey</title>
		<link>http://www.halostatue.ca/2007/12/31/save-a-lemur-club-thievy/</link>
		<comments>http://www.halostatue.ca/2007/12/31/save-a-lemur-club-thievy/#comments</comments>
		<pubDate>Mon, 31 Dec 2007 05:55:52 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/12/31/save-a-lemur-club-thievy/</guid>
		<description><![CDATA[
 
Crowned Lemur by belgianchocolate on Flickr

Lemurs are beautiful and deeply threatened creatures that are found only in Madagascar. Mike Lee of Delicious Monster is organizing something called Club Thievey in an attempt to encourage people to donate to the Madagascar Fauna Group.
This is a worthy cause. While I still haven&#8217;t decided whether I&#8217;m participating [...]]]></description>
			<content:encoded><![CDATA[<div style="float: right; margin-left: 10px; margin-bottom: 10px;">
 <a href="http://www.flickr.com/photos/frank-wouters/63842168/" title="photo sharing"><img src="http://farm1.static.flickr.com/27/63842168_4f96ae40a4_m.jpg" alt="" style="border: solid 2px #000000;" /></a><br />
<caption><a href="http://www.flickr.com/photos/frank-wouters/63842168/">Crowned Lemur</a> by <a href="http://www.flickr.com/people/frank-wouters/">belgianchocolate</a> on <a href="http://flickr.com/">Flickr</a></caption>
</div>
<p>Lemurs are beautiful and deeply threatened creatures that are found only in Madagascar. <a href="http://atomicwang.org/motherfucker">Mike Lee</a> of <a href="http://www.delicious-monster.com/">Delicious Monster</a> is organizing something called <a href="http://atomicwang.org/thievey/Club_Thievey/Welcome.html">Club Thievey</a> in an attempt to encourage people to donate to the <a href="http://savethelemur.org/">Madagascar Fauna Group</a>.</p>
<p>This is a worthy cause. While I still haven&#8217;t decided whether I&#8217;m participating in <a href="http://www.laptopgiving.org/en/index.php">Laptop Giving</a> or I&#8217;m making a last-minute donation for 2007 to <a href="http://www.msf.org/">Médecins Sans Frontières</a> (Doctors without Borders), I <em>have</em> donated to MFG; my wife did so earlier this year after reading Mike&#8217;s excellent <a href="http://atomicwang.org/thievey/Club_Thievey/Dinosaur_Ranch.html">Dinosaur Ranch</a>. It&#8217;s the right thing to do, and I want to see Mike&#8217;s goal of 100 members in the troop reached.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/12/31/save-a-lemur-club-thievy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>I Paid for Twitterrific</title>
		<link>http://www.halostatue.ca/2007/12/27/i-paid-for-twitterrific/</link>
		<comments>http://www.halostatue.ca/2007/12/27/i-paid-for-twitterrific/#comments</comments>
		<pubDate>Thu, 27 Dec 2007 20:36:18 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/12/27/i-paid-for-twitterrific/</guid>
		<description><![CDATA[
When Craig Hockenberry released Twitterrific 3 as either ad-supported or a $15 licence, I paid it immediately. According to one &#8220;Captain Marc&#8221; over at Odelbee, there&#8217;s a &#8220;hack&#8221; to disable the ads from Twitterrific, who apparently thinks that I&#8217;m a bit of an idiot for paying for Twitterrific. (Interestingly, between comment #9 and #21, Marc [...]]]></description>
			<content:encoded><![CDATA[<p class="i_right"><a href="http://iconfactory.com/software/twitterrific"><img src="http://www.halostatue.ca/wordpress/wp-content/uploads/2007/12/10dd6661-7f0c-4792-83c0-bd7f9b21fb67.jpg" alt="10DD6661-7F0C-4792-83C0-BD7F9B21FB67.jpg" border="0" width="108" height="108" /></a></p>
<p>When Craig Hockenberry released <a href="http://iconfactory.com/software/twitterrific">Twitterrific 3</a> as either ad-supported or a $15 licence, I paid it immediately. According to one &#8220;Captain Marc&#8221; over at Odelbee, there&#8217;s a &#8220;hack&#8221; to disable the ads from Twitterrific, who apparently thinks that I&#8217;m a bit of an idiot for paying for Twitterrific. (Interestingly, between comment #9 and #21, Marc went from thinking that Twitterrific was a &#8220;POS&#8221; and a pretty good app.) &#8220;Captain Marc&#8221; is wrong: the switch from free to free+ads or paid wasn&#8217;t without warning; this was stated up front on the download page of Twitterrific.
<p>He&#8217;s further wrong: Eudora was <quote>simply a tool for receiving and delivering … content</quote>, yet it sold for quite a long time. Very few of the applications that I&#8217;ve bought for the Mac since I switched eighteen months ago have I had any qualms about buying after buying them, and Twitterrific is one of the apps that I use every day, multiple times a day. There are features I&#8217;d like to see, certainly, but it&#8217;s a damned good product and I&#8217;m <em>proud</em> to have paid for it.There&#8217;s plenty of software that I wouldn&#8217;t buy at full price; sometimes I&#8217;ve waited for bundles (and my unwillingness to pay full price has generally been justified by the lack of use the product ends up seeing). More often, though, I just stop using the product. If I use it, though, I pay for it. No ifs, ands, or buts about it. And so should you, &#8220;Captain Marc.&#8221; You certainly shouldn&#8217;t be posting hacks or alleged hacks.</p>
<p>More on this from <a href="http://www.truerwords.net/6118">Seth Dillingham</a> and <a href="http://codesorcery.net/2007/12/27/bait-and-switch-no-its-called-software-development/">Justin Miller</a>.</p>
<blockquote><p>The Twitterrific icon in this post is copied from the IconFactory web site. It belongs to IconFactory and has been used with permission. </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/12/27/i-paid-for-twitterrific/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Optimize What?</title>
		<link>http://www.halostatue.ca/2007/11/25/optimize-what/</link>
		<comments>http://www.halostatue.ca/2007/11/25/optimize-what/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 14:52:03 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/25/optimize-what/</guid>
		<description><![CDATA[There&#8217;s been a furore recently over an article by Ankur Kothari where he optimized CTGradient. As an exercise in optimizing code, it was fairly aggressive but otherwise pedestrian. As an article, it was inflammatory and insulting from the beginning:
CTGradient contains an incredible diversity of built-in gradients, gradient styles… For demonstration purposes, all these features are excellent. [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a <a href="http://definr.com/furore">furore</a> recently over an <a href="http://lipidity.com/apple/ctgradient-code-bloat/">article</a> by <a href="http://lipidity.com/">Ankur Kothari</a> where he <em>optimized</em> <a href="http://blog.oofn.net/2006/01/15/gradients-in-cocoa/">CTGradient</a>. As an exercise in optimizing code, it was fairly aggressive but otherwise pedestrian. As an article, it was inflammatory and insulting from the beginning:<br />
<blockquote>CTGradient contains an incredible diversity of built-in gradients, gradient styles… For demonstration purposes, all these features are excellent. For production, this is a nightmare.</p></blockquote>
<p>It gets no better at the end:<br />
<blockquote>…The documentation already shows you how to draw gradients, yet the number of applications using CTGradient &#8211; the whole 1300 lines of it &#8211; is astonishing.Please: When you use other people’s code, don’t put it in without a thought. Go through it, understand it, and optimize it for your specific need. For the better performance and reduced RAM usage, computers will thank you.</p></blockquote>
<p>Quite legitimately, some Mac developers spoke out about this. Hoare&#8217;s famous dictum <q><a href="http://c2.com/cgi/wiki?PrematureOptimization">Premature optimization is the root of all evil</a></q> was pulled out early. It&#8217;s completely applicable here by any measure. This story would have ended here, and I wouldn&#8217;t be writing now, had it not been for a series of bile-filled nonsensical articles posted at <a href="http://rixstep.com">Rixstep</a>, starting with one calling Mac developers (such as <a href="http://red-sweater.com/">Daniel Jalkut</a>) objecting to this inflammatory article as the <a href="http://rixstep.com/2/1/20071121,00.shtml">Landed Gentry of Mac Development™</a>.<br />
<h2 id="toc-which-optimization">Which Optimization?</h2>
<p>I&#8217;ve been developing software for a long time. While I haven&#8217;t done <em>any</em> Objective C programming yet, there&#8217;s nothing in Ankur&#8217;s article which is unique to Objective C. When developing software, you make it work, make it right, make it fast. <strong>In that order.</strong> The goal is to <em>ship</em> your software, not have it languishing in interminable development. Mac developers aren&#8217;t the only ones who will use third-party source without looking for optimizations (or further optimizations, as the case may be); Unix and Windows developers do this, too. <strong>Any</strong> developer worth their salt does this, because the first goal is to <em>make it work</em>. At work, when we see performance and memory issues, we don&#8217;t start digging through third-party code. We don&#8217;t even start looking at our own code. We start looking at profiled performance data. Then, and only then, do we start to make something fast.So, if the first goal of software development is <em>make it work</em>, what&#8217;s the first optimization you should do? You should optimize your developers&#8217; time toward <em>shipping</em> the softare. Window background gradients aren&#8217;t the type of thing that will sell <strong>more</strong> copies of an application, but their absence may prevent some sales because the application doesn&#8217;t look &#8220;tasty&#8221; enough. So, you start looking at how to provide gradients. You see that Core Graphics supports it, and you start digging in the documentation and you see that it&#8217;s going to cost you lots of extra time to learn the CG gradient support. And then you have to debug what you&#8217;ve written. No sensible unit testing here; this is visual inspection. If you can add a single file that reduces your time to implement a background gradient—which you don&#8217;t really care about yourself but you know it&#8217;ll cost you sales not to have it—then you&#8217;re going to be better off entirely. Scott Stevenson of <a href="http://theocacao.com">Theocacao</a> stated it <a href="http://theocacao.com/document.page/242">much better</a> in 2006:<br />
<blockquote>Ah. Now doesn&#8217;t that feel better? It&#8217;s not that the class does anything that is otherwise impossible, it&#8217;s just a lot cleaner because all of the goofy callbacks and whatnot are moved into their own code space. In other words, you have more free time to work on the actual application.</p></blockquote>
<p>CTGradient is (almost) all about <em>developer</em> optimization. It also helps you deal with the second optimization: optimizing for correctness. It&#8217;s code that someone else has written and debugged. You know that other people who develop Mac apps are using it, and no one is screaming loudly about bugs in the code, so you feel pretty comfortable with it. So, you know that by using this drop-in library, you are not only getting this negative feature <em>done</em>, you&#8217;re getting it done <em>right</em>. At this point, you can forget about the getting it done fast, because no one has complained about gradient performance at this point, because you&#8217;re not yet done shipping.Make it work; make it right; make it fast. Optimize for developer time first (and this includes good design), and then worry about the rest when you need to.<br />
<h2 id="toc-more-code-optimization-better-developer">More Code Optimization = Better Developer?</h2>
<p>Things really went off the rails with this discussion when Rixstep posted the &#8220;Landed Gentry&#8221; article. He&#8217;s posted further bilious articles attacking some of the developers involved in the discussion over CTGradient optimization, but I&#8217;m not considering those articles for this discussion, since they&#8217;re pure bile and add nothing meaningful to the discussion (that is, they&#8217;re still based on false optimizations that I&#8217;ll address in a moment). In the &#8220;Landed Genry&#8221; article, Rixstep asks:<br />
<blockquote>Who would you rather have engineer your software? Someone who&#8217;s as conscientious as Ankur Kothari? Or someone who squirms and attacks and insinuates and does the absolute utmost to avoid the actual question? You the user/paying customer can decide. Wander over to Ankur Kothari&#8217;s article on CTGradient and see who&#8217;s objecting. At least you&#8217;ll now know what the Landed Gentry of Mac Development™ think of you.</p></blockquote>
<p>Rixstep presents a false dichotomy here. Ankur isn&#8217;t particularly conscientious in his article; there are specializations presented as optimizations, and some optimizations aren&#8217;t geared toward the most important parts of development anyway. Daniel Jalkut, on the other hand, is very conscientious toward his most important target: his customers&#8217; time in using the program. I&#8217;d be very surprised if anyone was saying that MarsEdit is too slow because of gradient display.Optimizing on parts of code that don&#8217;t matter doesn&#8217;t make you a better developer. Optimizing the right parts of code at the right time do. If I were hiring Ankur and Daniel, I&#8217;d have to watch over Ankur more to ensure that he wasn&#8217;t working on stuff that doesn&#8217;t matter to the customer. Like optimizing gradient code without actually knowing that it was a performance bottleneck. Ankur does a decent job of making sure that the resulting code meets the minimum required needs of the job (which, if you&#8217;re developing from scratch is a good thing, after all, YAGNI). He outright says that one should spend time going through third-party code that (probably) isn&#8217;t relevant to the primary mission of your softwasre, and therefore doesn&#8217;t help toward &#8220;make it work.&#8221;In reality? They&#8217;d probably both work out as great developers. But Ankur cares no more about a user&#8217;s software experience than Daniel does, despite the insinuations of Rixstep. I do question Ankur&#8217;s judgement on the optimizations made and how they were reached, or at least how they were explained.<br />
<h2 id="toc-the-axis-of-optimization">The Axis of Optimization</h2>
<p>Let&#8217;s play along for a moment, though. Assume we have already determined that there&#8217;s a measurable performance problem and we don&#8217;t have any currently outstanding feature requests or other problems that are higher priority than this performance problem. Assume further that we&#8217;ve profiled our program and we&#8217;ve determined that yes, our source of program slowdowns is CTGradient.There&#8217;s a legitimate question about whether Ankur&#8217;s effort was really optimization or specialization. When he says <q>Firstly, let&#8217;s remove the methods we know for sure we won&#8217;t need…</q>, the discerning reader <em>should</em> be asking why we don&#8217;t need those methods. Ankur doesn&#8217;t explain how he reached this conclusion. This means that the developer who is doing their job <em>right</em> won&#8217;t immediately think of eviscerating the entire CTGradient library, but rather measuring the performance characteristics of the library.Ankur made a mistake in his approach. Yes, simpler code is usually easier to maintain, debug, and will usually perform better. But simpler code does not necessarily mean better or more performant code. A bubble sort is simpler than quicksort; there&#8217;s no way that it&#8217;s faster. One may as well look at binary size for comparison. This isn&#8217;t to say that one shouldn&#8217;t strive for smaller binaries; the larger your binary, the more likely it is that you&#8217;ll cause something else the user uses to swap out to disk, which would be bad. Can CTGradient actively contribute to this? It&#8217;s not distributed as a Framework, so most projects compile it directly into their code.CTGradient&#8217;s 1,172 lines of code in six source files (as determined by <a href="http://www.dwheeler.com/sloccount/">Sloccount</a>) doesn&#8217;t even come close to adding meaningful binary code bloat. I compiled CTGradient from the latest available SVN checkout and Ankur&#8217;s &#8220;Lean Gradient&#8221; project. I compiled both as Universal using the default settings and compared the final binary size (from <code>Contents/MacOS/</code>) and the intermediate object file sizes. Since the projects are structured differently, it&#8217;s not a completely fair comparison. Ankur&#8217;s binary does one gradient and results in a binary size of 42,992 bytes; CTGradient does a lot of different types of gradients and results in a binary size of 78,776 bytes, a difference of a mere 35,784 more bytes of Universal code. A lot of the binary size differences is overhead, though. CTGradient creates three object files per architecture: CTGradient.o (55,964 bytes), CTGradientView.o (14,160 bytes), and main.o (976 bytes), leaving an overhead slack of 7,676 bytes. optGrad just has main.o (10,912 bytes), leaving an overhead slack of 32,080 bytes. So, CTGradient.o isn&#8217;t going to add to your binary size overhead in any meaningful way.What about memory use? Ankur posted two follow-up comments that suggested that CTGradient adds between three and ten megabyes of memory use to a program over and above his approach. That suggests that there might be room for a CTGradientLite, but making that would require extensive profiling to determine the parts that could be excised prior to doing so. And, of course, if all you need is a single gradient like Ankur did, and have the time and mathematical knowledge to do what Ankur did, by means do so. Ankur&#8217;s five minutes, though, might be five hours for you—so make sure that you don&#8217;t have something more important you should be working on.<br />
<h2 id="toc-the-unwashed-messes">The Unwashed Messes</h2>
<p>Ankur can perhaps be forgiven for the mistakes he made, as other posts by Rixstep suggest that he&#8217;s quite young. He hasn&#8217;t yet had to learn the personal interaction lessons that most of us have to learn, and that most of us do learn. There&#8217;s a few who don&#8217;t, and Rixstep appears to be one of these developers who resisted learning about how to behave toward other people throughout his career. He stepped into this discussion &#8220;defending&#8221; Ankur from the &#8220;Landed Gentry&#8221;, who were simply asking the same questions that any good software developer would. He&#8217;s gone further recently into personal attacks against two of the more vocal questioners. Reading further on Rixstep&#8217;s site, anything that is selling better than his software seems to result in that anything being called the &#8220;Landed Gentry&#8221; of something. He thinks that he&#8217;s defeating dragons, but in reality he&#8217;s tilting at windmills just as usefully as Don Quixote did.Rixstep is supposedly in the business of selling software. The content and tone of his posts have managed to do the opposite. I had recently considered purchasing some of his software; I know now that to do so would have been a mistake, because he doesn&#8217;t treat his peers well. It&#8217;s impossible for him to treat his customers well with that sort of attitude. It doesn&#8217;t take much to be generous in spirit to people, at least in starting. It doesn&#8217;t take much to realize that there are better ways to deal with conflict than has been done.There is a difference between taking a hard-line, hard-nosed approach to something and defending it on technical grounds and actively attacking someone without basis. Rixstep&#8217;s attacks, starting with the &#8220;Landed Gentry&#8221; article, are entirely without merit. Ankur didn&#8217;t optimize CTGradient; he made a specialization. This is valid sometimes, but <em>in reality</em> something like window gradients isn&#8217;t central to your application&#8217;s purpose, and to spend more than an hour or two dealing with them would be wholly inappropriate. The good developer knows that it&#8217;s better to ship than to spend all your time optimizing someone else&#8217;s code or rewriting it yourself.<br />
<h2 id="toc-where-does-ruby-fit-into-this">Where does Ruby Fit into This?</h2>
<p>The astute reader would have noticed that I filed this as a Ruby article as well. While I haven&#8217;t mentioned Ruby until this point in the article, the parallels here are obvious. Rixstep and Ankur both say that the dozens of applications that use CTGradient are abusing their users because it uses too much code, too much space, too much memory, and it&#8217;s too slow. Aside from the memory use, the claims have either been exposed as false already or haven&#8217;t been supported with data. As Scott Stevenson&#8217;s quote suggests, CTGradient optimizes for developer time.So does Ruby. I can get more written with Ruby than any other language that I use. It won&#8217;t be the fastest software, it might be a little more memory intensive, but I will get it written—and written correctly—faster. And that, given that shipping is the goal, is important. When Rixstep rejects CTGradient without providing a more optimized yet equivalent functionality alternative, he rejects any developer-side optimizations in favour of hand coding everything, including using more expressive languages.I reject that notion. And so should you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/25/optimize-what/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WWF Canada Advertisement</title>
		<link>http://www.halostatue.ca/2007/11/16/wwf-canada-advertisement/</link>
		<comments>http://www.halostatue.ca/2007/11/16/wwf-canada-advertisement/#comments</comments>
		<pubDate>Sat, 17 Nov 2007 02:55:21 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Politics]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/16/wwf-canada-advertisement/</guid>
		<description><![CDATA[Sorry about the videos lately, but this is just too cool not to share.

I really wish more politicians believed this and started investing in more and better options for getting around. One of America&#8217;s greatest presidents was a conservative—in the absolute most accurate sense: he was a conservationist. That man was Theodore Roosevelt. Too bad [...]]]></description>
			<content:encoded><![CDATA[<p>Sorry about the videos lately, but this is just too cool not to share.</p>
<p><object width="425" height="373"><param name="movie" value="http://www.youtube.com/v/GrlEQ15mVPM&#038;rel=0&#038;color1=0xd6d6d6&#038;color2=0xf0f0f0&#038;border=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/GrlEQ15mVPM&#038;rel=0&#038;color1=0xd6d6d6&#038;color2=0xf0f0f0&#038;border=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="373"></embed></object></p>
<p>I really wish more politicians believed this and started investing in more and better options for getting around. One of America&#8217;s greatest presidents was a conservative—in the absolute most accurate sense: he was a conservationist. That man was Theodore Roosevelt. Too bad that most modern conservatives aren&#8217;t after conserving anything.</p>
<p>(I&#8217;m not fond of most liberal-environmentalists, either, like Greenpeace. Frankly, I&#8217;m a futurist—I believe that technology will make a difference, and that nuclear is vital to the future.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/16/wwf-canada-advertisement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zooming in on the iPhone</title>
		<link>http://www.halostatue.ca/2007/11/14/zooming-in-on-the-iphone/</link>
		<comments>http://www.halostatue.ca/2007/11/14/zooming-in-on-the-iphone/#comments</comments>
		<pubDate>Wed, 14 Nov 2007 21:55:47 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Humor]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/14/zooming-in-on-the-iphone/</guid>
		<description><![CDATA[
(Via kottke.org.)
]]></description>
			<content:encoded><![CDATA[<p><object type="application/x-shockwave-flash" data="http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=1766423&#038;fullscreen=1" width="480" height="360" ><param name="allowfullscreen" value="true" /><param name="movie" quality="best" value="http://www.collegehumor.com/moogaloop/moogaloop.swf?clip_id=1766423&#038;fullscreen=1" /></object></p>
<p>(Via <a href="http://www.kottke.org/07/11/eames-powers-of-ten-iphone-god">kottke.org</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/14/zooming-in-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Old Magazines</title>
		<link>http://www.halostatue.ca/2007/11/13/more-old-magazines/</link>
		<comments>http://www.halostatue.ca/2007/11/13/more-old-magazines/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 22:57:32 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/13/more-old-magazines/</guid>
		<description><![CDATA[So, I went back to the medical devices place to return the trial mask and buy the permanent mask. I had to wait a while, so I dug through all of their magazines. At first, it seemed that the September 1989 magazine I found was the oldest:


A couple of minutes more digging yielded an older [...]]]></description>
			<content:encoded><![CDATA[<p>So, I went back to the medical devices place to return the trial mask and buy the permanent mask. I had to wait a while, so I dug through all of their magazines. At first, it seemed that the September 1989 magazine I found was the oldest:</p>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/2006854995" title="View 'Another old magazine' on Flickr.com"><img src="http://farm3.static.flickr.com/2007/2006854995_500f8a67a6_m.jpg" alt="Another old magazine" border="0" width="240" height="180" /></a></div>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/2006855153" title="View 'Toronto Life October 1990' on Flickr.com"><img src="http://farm3.static.flickr.com/2357/2006855153_eafebbfc84_m.jpg" alt="Toronto Life October 1990" border="0" width="240" height="180" /></a></div>
<p>A couple of minutes more digging yielded an older magazine, though, by five months.</p>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/2007651168" title="View 'Canadian Home April 1989' on Flickr.com"><img src="http://farm3.static.flickr.com/2128/2007651168_8d7b7770b7_m.jpg" alt="Canadian Home April 1989" border="0" width="240" height="180" /></a></div>
<p>But I kept looking. Long before my appointment was ready, I found something twenty-four years old:</p>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/2007651326" title="View 'December 1983' on Flickr.com"><img src="http://farm3.static.flickr.com/2196/2007651326_f27de29652_m.jpg" alt="December 1983" border="0" width="240" height="180" /></a></div>
<p>But right under that one was one that was even older: Woman&#8217;s Day from February 1982. Twenty-five years old, almost twenty-six.</p>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/2007651640" title="View 'Womans Day February 9, 1982' on Flickr.com"><img src="http://farm3.static.flickr.com/2399/2007651640_29a80c77f7_m.jpg" alt="Womans Day February 9, 1982" border="0" width="240" height="180" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/13/more-old-magazines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Own Your Words</title>
		<link>http://www.halostatue.ca/2007/11/08/own-your-words/</link>
		<comments>http://www.halostatue.ca/2007/11/08/own-your-words/#comments</comments>
		<pubDate>Fri, 09 Nov 2007 04:44:03 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/08/own-your-words/</guid>
		<description><![CDATA[I have approved my last anonymous comment on halostatue.ca. I don&#8217;t care if people disagree with me; I do care that people won&#8217;t own their words. I happily own my words here—whether you agree with me or not.  I expect people who comment on my posts to do the same.
I don&#8217;t have a problem [...]]]></description>
			<content:encoded><![CDATA[<p>I have approved my last anonymous comment on <a href="http://halostatue.ca">halostatue.ca</a>. I don&#8217;t care if people disagree with me; I do care that people won&#8217;t own their words. I happily own my words here—whether you agree with me or not.  I expect people who comment on my posts to do the same.</p>
<p>I don&#8217;t have a problem with identifiable pseudonyms, like <a href="http://fakesteve.blogspot.com/">Fake Steve Jobs</a> or <a href="http://minimsft.blogspot.com/">Mini-Microsoft</a> or even <a href="http://whytheluckystiff.net/">why the lucky stiff</a>. Those are all people who can be identified. I do have a problem with anonymous cowards, as Slashdot calls them.</p>
<p>If you want to comment on my blog in the future, you must provide either a valid email address that I can verify personally (and I <em>will</em>) or a valid URL to your own blog or public profile page that identifies you in a way that people can see what you&#8217;re about—whether you&#8217;re a real person or a pseudonymous person. If you don&#8217;t do one of the above, your comment will be deleted with no notice.</p>
<p>I also won&#8217;t allow abusive comments, toward me or toward others. If you feel that  <em>I</em> have been abusive in a post, please post a comment. I will act on it. (See the discussion in last year&#8217;s posts with Ola Bini; we worked out our differences.)</p>
<p>My readers, whomever they may be, will be able to know that even if I accept a pseudonym, I have at least been able to find someone who will own up to the words posted here.</p>
<p>Comments on <em>this</em> post are closed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/08/own-your-words/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amnesty Condemns Canada on Death Penalty</title>
		<link>http://www.halostatue.ca/2007/11/07/amnesty-condemns-canada-on-death-penalty/</link>
		<comments>http://www.halostatue.ca/2007/11/07/amnesty-condemns-canada-on-death-penalty/#comments</comments>
		<pubDate>Wed, 07 Nov 2007 17:28:22 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Politics]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/07/amnesty-condemns-canada-on-death-penalty/</guid>
		<description><![CDATA[So, Amnesty International is condemning Canada for being soft on the death penalty. I mostly agree with them. The problem isn&#8217;t Canada the nation, it&#8217;s the conservative government. Canadians are still largely against the death penalty, and support the idea that we should not extradite criminals if they are to face the death penalty, and [...]]]></description>
			<content:encoded><![CDATA[<p>So, <a href="http://www.amnesty.org/">Amnesty International</a> is condemning Canada for being <a href="http://www.cbc.ca/canada/story/2007/11/07/death-penalty.html?ref=rss">soft on the death penalty</a>. I mostly agree with them. The problem isn&#8217;t Canada the nation, it&#8217;s the conservative government. Canadians are still largely against the death penalty, and support the idea that we should not extradite criminals if they are to face the death penalty, and support the idea that we should request clemency for Canadian citizens facing the death penalty in other nations.</p>
<p>The <del>Conservatives</del><ins>Reform Party</ins>, on the other hand, are a bunch of rednecks who would love to see it brought back. So, they come up with excuses as to why they&#8217;re backpedaling on forty years of precedent. They sound as lame as the Republicans do south of us.</p>
<p>It&#8217;s really too bad that Dion&#8217;s Liberals are too lily-livered to come up with real positions that the <del>Conservatives</del><ins>Reform Party</ins> can&#8217;t respond to without sounding like the rednecks they are. Or that <strong>real</strong> <em>Progressive Conservatives</em> can&#8217;t stand up and take their party back from Stephen Harper&#8217;s rednecks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/07/amnesty-condemns-canada-on-death-penalty/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Medical Office Magazine Collections</title>
		<link>http://www.halostatue.ca/2007/11/06/medical-office-magazine-collections/</link>
		<comments>http://www.halostatue.ca/2007/11/06/medical-office-magazine-collections/#comments</comments>
		<pubDate>Tue, 06 Nov 2007 13:00:39 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/11/06/medical-office-magazine-collections/</guid>
		<description><![CDATA[So, I went to get a CPAP device yesterday. While waiting in the lobby of the medical devices office in Mississauga, I flipped through their magazine stack. This is what I found:

This is obviously old. The cut of the model&#8217;s blouse is not recent—I&#8217;m one of the least fashion-observant people in existence, but even I [...]]]></description>
			<content:encoded><![CDATA[<p>So, I went to get a <abbr title="continuous positive airway pressure">CPAP</abbr> device yesterday. While waiting in the lobby of the medical devices office in Mississauga, I flipped through their magazine stack. This is what I found:
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/1887554293" title="View 'First for Women' on Flickr.com"><img src="http://farm3.static.flickr.com/2048/1887554293_6d14860355_m.jpg" alt="First for Women" border="0" width="240" height="180" /></a></div>
<p>This is obviously old. The cut of the model&#8217;s blouse is not recent—I&#8217;m one of the least fashion-observant people in existence, but even I can recognise this. More obvious is the model&#8217;s hair style. Yeah, there&#8217;s a few people who have similar hair styles in 2007, but it&#8217;s very uncommon, and never on magazine covers at this point. So, when <em>was</em> this thing published?</p>
<div style="text-align:center;"><a href="http://www.flickr.com/photos/37996598059@N01/1888385254" title="View 'First for Women—September 1989' on Flickr.com"><img src="http://farm3.static.flickr.com/2165/1888385254_8814e0f4f9_m.jpg" alt="First for Women—September 1989" border="0" width="240" height="180" /></a></div>
<p>Eighteen years ago.</p>
<p>I expect to find old magazines in a medical office. It&#8217;s a common thing these days, right? But eighteen years? Isn&#8217;t there a statute of limitations for keeping around old magazines?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/11/06/medical-office-magazine-collections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>There&#8217;s a Ruby Debugger?</title>
		<link>http://www.halostatue.ca/2007/10/31/theres-a-ruby-debugger/</link>
		<comments>http://www.halostatue.ca/2007/10/31/theres-a-ruby-debugger/#comments</comments>
		<pubDate>Wed, 31 Oct 2007 22:45:22 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/31/theres-a-ruby-debugger/</guid>
		<description><![CDATA[Yeah. My post title is a little over the top, but since I started using Ruby in early 2002, I can&#8217;t count the number of times that I&#8217;ve used the Ruby debugger. After all, how does one count the empty set?
This is not to say that I haven&#8217;t had to debug; it&#8217;s to say that [...]]]></description>
			<content:encoded><![CDATA[<p>Yeah. My post title is a little over the top, but since I started using Ruby in early 2002, I can&#8217;t count the number of times that I&#8217;ve used the Ruby debugger. After all, how does one count the empty set?</p>
<p>This is not to say that I haven&#8217;t had to debug; it&#8217;s to say that where tests haven&#8217;t sufficed in helping me specify behaviour correctly, <code>Kernel#p</code> has helped me find what did go wrong so that I could fix the problem and add a test (where appropriate; PDF::Writer, for example, has no tests).</p>
<p>So I think that Giles Bowkett is <a href="http://gilesbowkett.blogspot.com/2007/10/debugger-support-considered-harmful.html">right</a>, even though I&#8217;d say that debuggers aren&#8217;t harmful; they&#8217;re pointless in a pointerless language.</p>
<p>I find that I mostly use the debugger in C/C++/C# for stack traces in any case. It&#8217;s a bit less painful with a good IDE, but depending on the nature of the problem that I&#8217;m debugging (especially one in a tight loop), I will usually add print outputs to a log file and debug based on those logs. Yes, even when there&#8217;s pointers involved (because it&#8217;s usually a binary search approach where I figure out where a pointer went bad over a large run).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/31/theres-a-ruby-debugger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Not Going Back</title>
		<link>http://www.halostatue.ca/2007/10/24/not-going-back/</link>
		<comments>http://www.halostatue.ca/2007/10/24/not-going-back/#comments</comments>
		<pubDate>Thu, 25 Oct 2007 02:19:49 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/24/not-going-back/</guid>
		<description><![CDATA[John Gruber has it exactly right: 
Windows lost a huge chunk of the nerd market. Nerd switchers, in and of themselves, don’t constitute a significant enough number of people to account for anything other than a tiny blip in Apple’s Mac sales. But nerds are the people who recommend computers to friends and families; it [...]]]></description>
			<content:encoded><![CDATA[<p>John Gruber has it <a href="http://daringfireball.net/2007/10/milhouse">exactly right</a>: </p>
<blockquote><p>Windows lost a huge chunk of the nerd market. Nerd switchers, in and of themselves, don’t constitute a significant enough number of people to account for anything other than a tiny blip in Apple’s Mac sales. But nerds are the people who recommend computers to friends and families; it seems inarguable that there are an awful lot of nerds recommending Macs today who weren’t five years ago.</p></blockquote>
<p>I bought my first Mac (15&#8243; MBP) in August 2006. In some ways, I bought it two months too early; in others, I bought just at the right time (I needed a new home laptop). In that time, I have convinced my parents to ditch their two Windows computers for a Mac—my MBP, when I upgrade early next year; I have told my wife that her next computer when this one dies will be a Mac and I have recommended Macs to three other people. There&#8217;s very little that one can do on Windows that one can&#8217;t do on the Mac; the only compelling reason for most people is games.</p>
<p>If you&#8217;re a big player of FPS games, you want a Windows PC. If you must always have the latest and greatest video card, you want a Windows PC.</p>
<p>Anyone else? You want a Mac. No, Apple doesn&#8217;t offer a $400 Mac. If that&#8217;s your budgetary limit, you *still* want a Mac, but you can&#8217;t afford one. Look at one of the Linux vendors. Because you&#8217;re not going to run a decent version of Vista on that $400 PC. And you&#8217;ll need to replace it sooner than you would an equivalent Mac. My rule of thumb for non-Mac hardware has been that you&#8217;ll get about 12 &#8211; 14 months of meaningful use per $500 you spend. I suspect that it&#8217;s 18 &#8211; 24 months of meaningful use per $500 you spend on a Mac. By meaningful use I mean before you start noticing memory and graphics limitations requiring significant hardware upgrades to keep up to date.</p>
<p>I&#8217;m not going back. I don&#8217;t know that I&#8217;ll stay with the Mac &#8220;forever&#8221;, but at this point, it&#8217;s the best computer investment that I&#8217;ve made so far. Aside from that first computer (and it was my dad&#8217;s investment then), that started me on the road I&#8217;m on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/24/not-going-back/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>More on the Wrong Question</title>
		<link>http://www.halostatue.ca/2007/10/20/more-on-the-wrong-question/</link>
		<comments>http://www.halostatue.ca/2007/10/20/more-on-the-wrong-question/#comments</comments>
		<pubDate>Sat, 20 Oct 2007 15:52:09 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/20/more-on-the-wrong-question/</guid>
		<description><![CDATA[In the comments of my previous question, John asked &#8220;what was the wrong question that he asked?&#8221; To which I replied:
The wrong question is the comparison between Vanilla Ice and Soulja Boy. Vanilla Ice was low rent back in the day — his second album was a live version of the first album, and his [...]]]></description>
			<content:encoded><![CDATA[<p>In the comments of my previous question, John asked &#8220;what was the wrong question that he asked?&#8221; To which I replied:</p>
<blockquote><p>The wrong question is the comparison between Vanilla Ice and Soulja Boy. Vanilla Ice was low rent back in the day — his second album was a live version of the first album, and his &#8220;superstardom&#8221; lasted about a year. Soulja Boy&#8217;s rap may be better than Vanilla Ice&#8217;s rap, but it&#8217;d be better to compare Coldplay or Oasis (people with more than one album to their name) to The Beatles or Pink Floyd when asking whether the singles price on iTunes is good, or whether they should be variably priced.</p>
<p>Radiohead may have hit on the right way to handle variable pricing, but that only works when you know you&#8217;re sending the majority of your money directly to the band. Most people don&#8217;t want to make the soul-suckers at the labels any richer than they need to be.</p>
</blockquote>
<p>John replied last night with:</p>
<blockquote><p>interesting — i read that differently. soulja boy is currently listed as one of the top 10 downloaded songs on itunes, which gave me the impression that his point was about demand. (right now, lots of people want that new hit single, and far fewer people want the old single that now sounds like crap.)</p>
<p>so i thought it wasn’t about which musician was &#8220;better&#8221; — i don’t especially like either of those songs, personally — but about which musician’s product was currently more &#8220;in demand.&#8221;</p>
</blockquote>
<p>The record execs <em>want</em> you to think that it&#8217;s about demand, but it&#8217;s not. Demand pricing makes sense when there&#8217;s scarcity and you have a lock on the market. Newer music is <em>anything</em> but scarce. You can hardly go anywhere without hearing it as a ringtone, an advertising jingle, or just on the radio. I listen to a &#8220;classic rock&#8221; format station, yet they&#8217;re playing new music from Neil Young and Kim Mitchell, and they consider U2 (up until <em>All That You Can&#8217;t Leave Behind</em>, at least) classic rock. So music has the opposite problem of scarcity; there&#8217;s a glut.</p>
<p>The radio brings up another important point—as much as record execs would love to pretend otherwise, they&#8217;re not competing like you do in other markets. They&#8217;re competing against free. There&#8217;s plenty of songs out there that I like, but that I don&#8217;t like enough to even consider buying <em>even at 99¢</em>—not when I can hear them periodically on the radio. And if I wanted them, but they were more expensive than my lowest willing price, I can usually find them somewhere online. (I don&#8217;t; but I have used AllofMP3 before. I already pay the CRIA something every time I buy blank media, so I have the right to get songs that others share that way.)</p>
<p>There is one other theory the record execs could be using here, which is the concept that one values something one has to pay for. Therefore, one values something <em>more</em> that one has to pay <em>more</em> for. If this had been possible when Vanilla Ice was in his (short-lived) heyday, people <em>may</em> have been willing to pay $3.00 for &#8220;Ice Ice Baby&#8221;, but how many people would have regretted it later and deemed themselves fools? (The song has <em>not</em> aged well.) So the value of a song isn&#8217;t really derived from how <em>hot</em> it is, but its <em>longevity</em>. And even then, you&#8217;re still competing against a model that treats songs as essentially valueless (radio or satellite radio).</p>
<p>So, demand pricing doesn&#8217;t work well if there&#8217;s no scarcity (or artificial scarcity). We also know that subscription pricing for portable devices doesn&#8217;t work. (More accurately, it doesn&#8217;t work for portable devices where you control the content. Satellite radios are portable, but you don&#8217;t control the content.) Subscription pricing works when it gives you a menu of things to choose from (cable television, satellite radios) but the value is provided by the <em>menu</em>, not the individual pieces that make up the menu. (The subscription price is too low per person for the individual songs or television shows to be worth much at all. In aggregate, they can make money, but individually they&#8217;re fractional pennies value.)</p>
<p>What does work? That&#8217;s where we get back to the Radiohead experiment. They asked people how much they <em>value</em> their music. Some folks bought it for the absolute minimum; others paid much more. Most paid about the same price that they&#8217;d pay on iTunes. But you have to have an environment where that will work, and I don&#8217;t think that the Radiohead experiment is generally applicable for the entire catalogue of some bands&#8217; music. (That is to say that I think that it&#8217;s a decent short-term strategy when the music is new, but I don&#8217;t think it&#8217;s sustainable for more than a few months.)</p>
<p>I don&#8217;t agree completely with Apple&#8217;s iTMS policy (you can have some songs album-only, but you can&#8217;t have an album-only album), as I&#8217;d <em>love</em> to see album-oriented rock make a return. (But I&#8217;d also love to see sound-bite politics go away.) I think, however, that the simplified pricing models make a lot more sense than pretending that something is more valuable because more people want it, when there&#8217;s no scarcity involved.</p>
<p>Souljaboy may be hot. Will he be next year? Or will he be dropped like Vanilla Ice?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/20/more-on-the-wrong-question/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When you ask the wrong question, you will get the wrong answer</title>
		<link>http://www.halostatue.ca/2007/10/18/when-you-ask-the-wrong-question-you-will-get-the-wrong-answer/</link>
		<comments>http://www.halostatue.ca/2007/10/18/when-you-ask-the-wrong-question-you-will-get-the-wrong-answer/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 17:58:06 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/18/when-you-ask-the-wrong-question-you-will-get-the-wrong-answer/</guid>
		<description><![CDATA[Ivan Askwith asks the wrong question and gets the wrong answer about iTunes pricing model…]]></description>
			<content:encoded><![CDATA[<p>In Slate&#8217;s <a href="http://www.slate.com/id/2176117/fr/nl/">What&#8217;s the future of iTunes?</a> by Ivan Askwith, the wrong question is asked. Not surprisingly, the wrong answer is reached. Specifically:</p>
<blockquote><p>…Whomever you believe, the fact remains that content providers have been pushing Apple to loosen up its pricing restrictions, and Apple has refused.</p>
<p>Regardless of demand, each song on iTunes costs 99 cents, each television program $1.99, and each feature-length movie $9.99. Most consumers are likely to agree that iTunes&#8217; pricing seems illogical; there&#8217;s no obvious reason that Vanilla Ice&#8217;s &#8216;Ninja Rap 2&#8242; should cost the same as the newest tracks from Soulja Boy. For content owners, this is more than illogical: It&#8217;s bad for business.</p>
</blockquote>
<p>The question isn&#8217;t about Vanilla Ice. The question is about Led Zeppelin, Pink Floyd, The Rolling Stones, The Who, and the Beatles. There&#8217;s no reason whatsoever that newer, &#8220;hotter&#8221;, music should be more expensive than legendary music by these bands. Is the latest Justin Timberlake even remotely as good as &#8220;Behind Blue Eyes&#8221; or &#8220;Paint It Black&#8221; or even &#8220;Yellow Submarine&#8221;?</p>
<p>The usual standard presented by the recording industry morons is variable pricing based on the freshness and popularity of the music, where the more popular and fresh the music is, the more expensive it is. This works in a scarcity model, but <em>music isn&#8217;t scarce</em>. Music&#8217;s value <em>increases</em> the more that it&#8217;s heard and the more people internalize it. But if you&#8217;re going to price Soulja Boy&#8217;s latest tracks more than Harrison&#8217;s masterpiece <a href="http://en.wikipedia.org/wiki/While_My_Guitar_Gently_Weeps">&#8220;While My Guitar Gently Weeps&#8221;</a>, you&#8217;re implying that Soulja Boy&#8217;s music has more <em>value</em> than the older, and better, music.</p>
<blockquote><p>Why does Apple stick with fixed pricing? Market analysts generally say that this is because iTunes sales are a means to an end, where the end is selling iPods. As such, Apple&#8217;s interest is ensuring that desirable content for the iPod costs as little as possible.</p></blockquote>
<p>John Gruber <a href="http://daringfireball.net/2007/09/more_amazon_mp3_store">addressed this quite nicely in September</a>. I&#8217;m not trying to say that Apple is perfect (far from it!), but I would assume the obvious: multiple price points confuse people unnecessarily. Those market analysts, of course, are wrong. Ivan Askwith gets this one right:</p>
<blockquote><p>The more likely explanation, however, lies with the company&#8217;s obsession with simplicity. ITunes has been a huge success because it&#8217;s easy to use, and (at least for now) has the most digital content of any online store. Apple&#8217;s refusal to budge on pricing indicates it&#8217;s prepared to defend simplicity at the expense of selection.</p></blockquote>
<p>That target of simplicity is important: the harder it is for people to play the media they want on the devices they want, the less they&#8217;ll buy the one they need less. (And, so far, the iPod is the device people overwhelmingly want. People will forgo on-line purchases if the rest of the device is easy enough to use. I&#8217;ve bought a total of <em>four</em> things from iTMS, and two of those were audiobooks.)</p>
<p>Simplicity matters. Amazon works, despite the pricing differences, precisely because it makes the shopping and shipping simple. Amazon&#8217;s music store works well because it integrates with iTunes, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/18/when-you-ask-the-wrong-question-you-will-get-the-wrong-answer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Are Social Networks Fads?</title>
		<link>http://www.halostatue.ca/2007/10/12/are-social-networks-fads/</link>
		<comments>http://www.halostatue.ca/2007/10/12/are-social-networks-fads/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 13:36:20 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[facebook social-networking]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/12/are-social-networks-fads/</guid>
		<description><![CDATA[Steve Ballmer warns that social networking may be a fad. Eric Schmidt, on the other hand, looks at it from a page view perspective.  Both are wrong about the details. Facebook and MySpace and the like will continue to be important destinations, much like Google, Yahoo, Netscape, and even the MSN homepage have been [...]]]></description>
			<content:encoded><![CDATA[<p>Steve Ballmer warns that social networking may be a <a href="http://www.portfolio.com/views/blogs/daily-brief/2007/10/02/fad-or-feint-microsofts-ballmer-on-facebook">fad</a>. Eric Schmidt, on the other hand, looks at it from a <a href="http://bits.blogs.nytimes.com/2007/10/11/google-hints-at-social-network-plan/">page view perspective</a>.  Both are wrong about the details. Facebook and MySpace and the like will continue to be important destinations, much like Google, Yahoo, Netscape, and even the MSN homepage have been destinations. They provide value to people.</p>
<p>What&#8217;s a fad, though, is <em>how</em> these networks work. I think that the people who are dealing with &#8220;open&#8221; social networking have the right approach. Facebook will have to adapt to input from outside (opening up the inputs), as it recently did with allowing applications the ability to set a user&#8217;s status, as with Twitter. Facebook has already said that it&#8217;s going to open certain things to the outside on an opt-in basis; if it can nail the user interface (and that&#8217;s a big if, given how many people stick with the standard privacy settings), then we&#8217;ll have an even bigger when as the network effect not only deals with people, but with sites.</p>
<p>Social networks as networks are fads; the value they provide, though, is real. The challenges that remain are better classification of friends and a reduction in the amount of effort it takes to allow users to segregate information between groups of friends. That last is important. I&#8217;m on Facebook. If I were looking for a new job (I&#8217;m not), I might talk about it on Facebook. There&#8217;s a problem, though: my boss and some of my coworkers are on Facebook and are friends with me. The moment I started talking about it publicly, they&#8217;d know something was up and it might make for bad relations at work (at a minimum).</p>
<p>Now, I&#8217;m pretty open, but if I wanted to do something like that, I would want an easy way of drawing a circle around them and saying: they can&#8217;t see these updates.</p>
<p>Before it&#8217;s too late.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/12/are-social-networks-fads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Would you go to a Fake Steve party?</title>
		<link>http://www.halostatue.ca/2007/10/06/would-you-go-to-a-fake-steve-party/</link>
		<comments>http://www.halostatue.ca/2007/10/06/would-you-go-to-a-fake-steve-party/#comments</comments>
		<pubDate>Sun, 07 Oct 2007 01:54:21 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/06/would-you-go-to-a-fake-steve-party/</guid>
		<description><![CDATA[I&#8217;m more than just a little behind on reading my feeds, and I noted that Daniel LyonsFake Steve is going to be in Toronto from October 17 through 19 and is considering having some &#8220;Fake Steve Jobs&#8221; parties.
Could be interesting. I&#8217;ll see.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m more than just a little behind on reading my feeds, and I noted that <del>Daniel Lyons</del>Fake Steve is going to be in Toronto from October 17 through 19 and is considering having some <a href="http://fakesteve.blogspot.com/2007/10/trying-to-arrange-some-fsj-parties.html">&#8220;Fake Steve Jobs&#8221; parties</a>.</p>
<p>Could be interesting. I&#8217;ll see.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/06/would-you-go-to-a-fake-steve-party/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Are you nuts or stupid?  Nevermind, I know the answer to that.</title>
		<link>http://www.halostatue.ca/2007/10/06/are-you-nuts-or-stupid-nevermind-i-know-the-answer-to-that/</link>
		<comments>http://www.halostatue.ca/2007/10/06/are-you-nuts-or-stupid-nevermind-i-know-the-answer-to-that/#comments</comments>
		<pubDate>Sat, 06 Oct 2007 13:46:57 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/06/are-you-nuts-or-stupid-nevermind-i-know-the-answer-to-that/</guid>
		<description><![CDATA[On the idiocy of people who would "buy a mac if they could just get…"]]></description>
			<content:encoded><![CDATA[<p>So, Mac OS Rumours &#8220;<a href="http://macosrumors.com/">reports</a>&#8221; that the Mac Mini <em>will</em> be killed in October and replaced with a &#8220;Mac Nano&#8221;. TUAW <a href="http://www.tuaw.com/2007/10/04/rumor-mac-mini-turns-nano-in-late-october/">picks up on it</a> and gives it enough legs to <a href="http://digg.com/apple/Rumor_Mac_mini_turns_Nano_in_late_October">reach Digg&#8217;s frontpage</a>.</p>
<p>Personally, I don&#8217;t care if Mac OS Rumours is right or not; I don&#8217;t listen to them. The idea of this move makes no sense anyway given that the Mini was just given an update in August. What interests me are the comment threads on TUAW and Digg.</p>
<p>Take, for example, the <a href="http://www.tuaw.com/2007/10/04/rumor-mac-mini-turns-nano-in-late-october/#c7982196">first comment</a> on TUAW, asking where the mid-range headless with upgradeable components is. Or <a href="http://digg.com/apple/Rumor_Mac_mini_turns_Nano_in_late_October?t=9638235#c9638235">this one</a> from Digg. What about <a href="http://digg.com/apple/Rumor_Mac_mini_turns_Nano_in_late_October?t=9636170#c9639522">this one</a> calling for a Mini with an upgradeable video card?</p>
<p>I gotta wonder whether these people are nuts or stupid. Actually, I don&#8217;t really have to wonder at all. Like it or not, Apple is about control. You&#8217;re never going to get a consumer-level Mac with much of an upgradeable anything. They&#8217;re not trying to compete with Dell, so they don&#8217;t need a minitower model for consumers. The Apple model distribution is simple—and that&#8217;s on purpose. The pricing is roughly accurate: you spend more, you get more. Contrast that with Dell, where spending more doesn&#8217;t always get you more—it gets you different. (It always took me a couple of hours to figure out the best base-model machine to configure from at Dell for the best bang for the buck. It doesn&#8217;t take long at all with Apple.)</p>
<p>Insanity is colloquially considered to be trying to do the same thing repeatedly while expecting different results. You can keep wishing that Apple will cater <em>to you</em> and not to what will actually make <em>them</em> money, but it won&#8217;t do you any good. So, keep wishing. You&#8217;ll keep me laughing at you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/06/are-you-nuts-or-stupid-nevermind-i-know-the-answer-to-that/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rainier Brockerhoff on the State of the iPhone</title>
		<link>http://www.halostatue.ca/2007/10/02/rainier-brockerhoff-on-the-state-of-the-iphone/</link>
		<comments>http://www.halostatue.ca/2007/10/02/rainier-brockerhoff-on-the-state-of-the-iphone/#comments</comments>
		<pubDate>Wed, 03 Oct 2007 03:51:15 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/02/rainier-brockerhoff-on-the-state-of-the-iphone/</guid>
		<description><![CDATA[Rainier Brockerhoff&#8217;s State of the iPhone is an excellent read. Even though, as a Canadian, I can&#8217;t get an iPhone here (damn you, Ted Rogers, knuckle under already you greedy bastard), I really want an iPhone SDK. I might even pay for one, but I think that&#8217;d be the wrong step for Apple to take [...]]]></description>
			<content:encoded><![CDATA[<p>Rainier Brockerhoff&#8217;s <a href="http://brockerhoff.net/bb/viewtopic.php?p=2191#2191">State of the iPhone</a> is an excellent read. Even though, as a Canadian, I can&#8217;t get an iPhone here (damn you, Ted Rogers, knuckle under already you greedy bastard), I <em>really</em> want an iPhone SDK. I might even pay for one, but I think that&#8217;d be the wrong step for Apple to take (listing and certifying in the iTunes store, perhaps).</p>
<p>(Via <a href="http://daringfireball.net">Daring Fireball</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/02/rainier-brockerhoff-on-the-state-of-the-iphone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Edgar Bronfman, Jr. is an idiot…</title>
		<link>http://www.halostatue.ca/2007/10/02/edgar-bronfman-jr-is-an-idiot%e2%80%a6/</link>
		<comments>http://www.halostatue.ca/2007/10/02/edgar-bronfman-jr-is-an-idiot%e2%80%a6/#comments</comments>
		<pubDate>Tue, 02 Oct 2007 20:46:20 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[mafiaa]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[riaa]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/02/edgar-bronfman-jr-is-an-idiot%e2%80%a6/</guid>
		<description><![CDATA[&#8220;Never before in the history of content has the hardware been more valuable than the software…You think about the VCR or the video cassette—the video cassette always had more value than the VCR that you shoved it into. Apple has been able to turn that model on its head.&#8221;
Edgar Bronfman, Jr. (Chairman, Warner Music Group), [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>&#8220;Never before in the history of content has the hardware been more valuable than the software…You think about the VCR or the video cassette—the video cassette always had more value than the VCR that you shoved it into. Apple has been able to turn that model on its head.&#8221;<br />
<cite>Edgar Bronfman, Jr. (Chairman, Warner Music Group), in <a href="http://www.wired.com/entertainment/music/news/2007/09/drm_part_one">Like Amazon&#8217;s DRM-Free Music Downloads? Thank Apple</a></cite></p></blockquote>
<p>Edgar Bronfman is an idiot who simply doesn&#8217;t get it. Apple hasn&#8217;t made the <em>hardware</em> more valuable, it&#8217;s made the <em>collection</em> more valuable. It used to be that you weren&#8217;t able to carry the majority of your media collection with you; now, that collection represents a valuable investment. Not the hardware.</p>
<p>Moron.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/02/edgar-bronfman-jr-is-an-idiot%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why I (now) wholeheartedly support MMP</title>
		<link>http://www.halostatue.ca/2007/10/01/why-i-now-wholeheartedly-support-mmp/</link>
		<comments>http://www.halostatue.ca/2007/10/01/why-i-now-wholeheartedly-support-mmp/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 17:42:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Politics]]></category>
		<category><![CDATA[Toronto]]></category>
		<category><![CDATA[MMP]]></category>
		<category><![CDATA[Ontario]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/01/why-i-now-wholeheartedly-support-mmp/</guid>
		<description><![CDATA[I&#8217;ve been doing some serious thinking about the referendum question facing Ontarians this fall. Spacing Votes has been quite useful in distilling some of the issues and features of MMP (Mixed Member Proportional) as opposed to FPTP (first-past-the-post, the current system), as evidenced by an earlier post I made. They continue to do so with [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing some serious thinking about the referendum question facing Ontarians this fall. <a href="http://spacing.ca/votes/">Spacing Votes</a> has been quite useful in distilling some of the issues and features of MMP (Mixed Member Proportional) as opposed to FPTP (first-past-the-post, the current system), as evidenced by an <a href="http://www.halostatue.ca/2007/09/21/ontario-votes-voting-format-referendum/">earlier post</a> I made. They continue to do so with <a href="http://spacing.ca/votes/?p=408">MMP Disproportionality, Part I (Local Seats)</a>; I&#8217;m looking forward to part two.</p>
<p>I have, however, been thinking about the &#8220;list&#8221; seats versus geographically-based seats (&#8221;ridings&#8221;) and come to the conclusion that the problem isn&#8217;t list seats, but ridings. My office-place is an interesting example in this problem, in that the office is in nominally in Oakville (it&#8217;s at Winston Churchill and Dundas, right at the very border between Oakville and Mississauga), but very few people live in Oakville. A lot of people live west of the office, in Hamilton, St. Catharines, or Burlington; a lot of people live in Mississauga proper. Some, like myself, live in Toronto. I spend nearly ⅓ of my life away from where I live, and of the ⅔ that I&#8217;m at home, roughly ⅓ of it is spent sleeping.</p>
<p>So while I care about my neighbourhood&#8217;s representation in parliament (both federally and provincially), I also care about the places where I work and (at a minimum) the transit corridor I travel to and from work every day. My concerns are less about where I live than how I get to and from work, which means that regional transit policies matter to me. I can&#8217;t effectively and efficiently use a transit system to get to work. (The local Go station is ~10 minutes from my house, the train doesn&#8217;t run <em>that</em> often and even <em>less</em> often coming home, and the nearest station is still ~15 minutes from work by bus; my total commute by car is under 35 minutes).</p>
<p>I care about how municipalities (who should be caring more about the local rights and responsibilities) are being run over roughshod by the OMB and developers and the province itself. Mike Harris did more damage to Toronto&#8217;s infrastructure through forced amalgamation and downloading than anyone else. He also reduced our democratic representation by cutting the number of city councillors from 57 to 44—the City of Toronto web site says this was adopted by City Council, but I recall reporting at the time was that the adoption was at electoral gunpoint, just like the almagamation itself.</p>
<p>In other words, 90% of my concerns aren&#8217;t limited to my relatively small geographic region of the Parkdale-High Park riding, and the concerns I do have about Parkdale-High Park should be addressed through City Council and my local councillor rather than my provincial representation.</p>
<p>Ultimately, I don&#8217;t know that I care whether my representation is regional, and even think that regional representation may be the oddity in today&#8217;s world. As such, I can only end up supporting MMP. It may not be perfect, and I may regret supporting it in the future, but I don&#8217;t believe that being held hostage to the past in this case is a good thing.</p>
<p><strong>Update:</strong> Reading a bit more, I have found another point that puts me in favour of MMP. The claim is that regional ridings represent the will of the people. This is only partially true, in that there are plenty of examples of parties parachuting in &#8220;star&#8221; candidates. I think Ken Dryden was this way for the federal Liberal party; while the people of his riding ended up voting for him, he did not have to win his party&#8217;s nomination for the seat.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/01/why-i-now-wholeheartedly-support-mmp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Andrew Coyne: Why conservatives should support proportional representation</title>
		<link>http://www.halostatue.ca/2007/10/01/andrew-coyne-why-conservatives-should-support-proportional-representation/</link>
		<comments>http://www.halostatue.ca/2007/10/01/andrew-coyne-why-conservatives-should-support-proportional-representation/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 16:33:38 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Politics]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/10/01/andrew-coyne-why-conservatives-should-support-proportional-representation/</guid>
		<description><![CDATA[I never thought I'd agree with Andrew Coyne about much of anything…]]></description>
			<content:encoded><![CDATA[<p>In September 22nd&#8217;s <a href="http://www.canada.com/nationalpost/">National Post</a>, <a href="http://www.canada.com/nationalpost/columnists/andrewcoyne.html">Andrew Coyne</a> wrote an editorial in support of MMP, entitled <a href="http://www.canada.com/nationalpost/news/editorialsletters/story.html?id=5dd45bb7-b8d2-49f6-b20d-1e69690b8838&#038;p=1">Why conservatives should support proportional representation</a>.</p>
<p>Let me be perfectly clear: I disagree with Andrew Coyne on most of what he says and writes. I don&#8217;t believe the way he believes. He believes that Mike Harris was <em>good</em> for Ontario (when exactly the opposite has proven true). But he is absolutely right when he says:</p>
<blockquote>
<p>A Tory government…of Ontario would look much the same under Mr. Tory as under Dalton McGuinty. It would do much the same things, at much the same cost, with much the same results.</p>
<p>Oh, Mr. Tory would fiddle at the margins &#8212; cut a tax or two, expand funding to a few thousand kids in religious schools &#8212; issues that both leaders would like you to think show the vast gulf between them. But they&#8217;re not kidding anyone. Whoever wins, the forecast is for McGuintory governments, as far as the eye can see.…</p>
<p>[The current voting system creates most of what we find in] Canadian politics &#8212; viciously partisan, yet unspeakably trivial; much ado about nothing much. McGuintoryism, in short.</p>
</blockquote>
<p>I think that John Tory would be bad for the province (he keeps pretending that he&#8217;s like Bill Davis, but he&#8217;s much more like Mike Harris), but that doesn&#8217;t mean that I think that Howard Hampton or Dalton McGuinty are <em>good</em> for the province. Something has to change; MMP may not be the best change, but we have to <em>try</em>.</p>
<p>(Via <a href="http://spacing.ca/votes/?p=466">Spacing Votes</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/10/01/andrew-coyne-why-conservatives-should-support-proportional-representation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Is there anybody going to listen to my story…</title>
		<link>http://www.halostatue.ca/2007/09/29/is-there-anybody-going-to-listen-to-my-story%e2%80%a6/</link>
		<comments>http://www.halostatue.ca/2007/09/29/is-there-anybody-going-to-listen-to-my-story%e2%80%a6/#comments</comments>
		<pubDate>Sun, 30 Sep 2007 03:16:23 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/09/29/is-there-anybody-going-to-listen-to-my-story%e2%80%a6/</guid>
		<description><![CDATA[All about the girl who came to stay?
She&#8217;s the kind of girl you want so much
It makes you sorry
Still you don&#8217;t regret a single day.
Ah girl! Ffff&#8230;Girl!
With Lennon&#8217;s &#8220;Girl&#8221; begins Julie Taymore&#8217;s latest film, Across the Universe. The film is visually rich, musically gifted, and utterly confused. Nonetheless, I really enjoyed it.
This movie is divisive, [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>All about the girl who came to stay?<br />
She&#8217;s the kind of girl you want so much<br />
It makes you sorry<br />
Still you don&#8217;t regret a single day.<br />
Ah girl! Ffff&#8230;Girl!</p></blockquote>
<p>With Lennon&#8217;s &#8220;Girl&#8221; begins <a href="http://www.imdb.com/name/nm0853380/">Julie Taymore</a>&#8217;s latest film, <a href="http://www.imdb.com/title/tt0445922/"><em>Across the Universe</em></a>. The film is visually rich, musically gifted, and utterly confused. Nonetheless, I really enjoyed it.</p>
<p>This movie is divisive, make no mistake. <a href="http://www.rottentomatoes.com/m/across_the_universe/">Rotten Tomatoes</a> marks it &#8220;Rotten&#8221; as of the date of this post, as shown below. Only 51% of the critical reviews are positive. Look at those reviews, though, and you&#8217;ll see strong feelings for or against the film.</p>
<p style="text-align: center"><img src="http://www.halostatue.ca/wordpress/wp-content/uploads/2007/09/across-the-universe-rotten-tomatoes.jpg" alt="Across the Universe: 51% / Rotten (Rotten Tomatoes)" border="0" height="73" width="300" /></p>
<p>Disclaimer: I went to see this movie because my brother&#8217;s in it, as a dancer (when Max goes into the induction centre and is stripped to his boxers, Kenneth is the first soldier to Max&#8217;s right, and dances behind him; later, he is two beds to the left of Max). I also didn&#8217;t pay anything to see it (due to some complimentary—or compensatory—tickets provided by the theatre for a screening of <em>Pirates of the Carribean</em> that was interrupted by a 5-year-old).</p>
<p>I was prepared to hate the film, because going in you know it will take every possible cliché that it can. Despite a very slow start and an often muddled middle with the various characters flitting in and out of the film, the film managed to keep me entertained for more than two hours, and came across as relevant today, at least to me.</p>
<p>This is art, but it&#8217;s not high art. It&#8217;s candy on the order of <em>Moulin Rouge!</em>, but perhaps not as well executed in the end. Still, if you enjoy the Beatles, enjoy in-jokes, and are prepared to accept a caricature of the 60s (but what movie <em>isn&#8217;t</em> a caricature of an era), you will probably enjoy this film.</p>
<p><strong>Update: I have (hopefully) fixed the comment-posting issue.<br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/09/29/is-there-anybody-going-to-listen-to-my-story%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>On Derek Siver&#8217;s Return to PHP…</title>
		<link>http://www.halostatue.ca/2007/09/23/on-derek-sivers-return-to-php%e2%80%a6/</link>
		<comments>http://www.halostatue.ca/2007/09/23/on-derek-sivers-return-to-php%e2%80%a6/#comments</comments>
		<pubDate>Mon, 24 Sep 2007 01:23:48 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/09/23/on-derek-sivers-return-to-php%e2%80%a6/</guid>
		<description><![CDATA[Derek Siver's rewrite of CD Baby with Rails failed, but it's not Ruby's fault.]]></description>
			<content:encoded><![CDATA[<p>Derek Sivers, <a href="http://www.oreillynet.com/ruby/blog/2007/09/7_reasons_i_switched_back_to_p_1.html">recently abandoned</a> his CD Baby rewrite from PHP to Rails. This isn&#8217;t bad news for Rails or Ruby, nor is it good news for PHP. It&#8217;s good news for CD Baby. Anyone who reads it otherwise is missing the lesson.</p>
<p>There are plenty of reasons to dislike PHP (although all of my criticisms have to be aimed at PHP4 right now, as I haven&#8217;t done anything with PHP5), but it is a useful general purpose language. It has different philosophies than Ruby, and I think that <em>in general</em> it isn&#8217;t nearly as good a language as either Ruby or Python. But it is just fine for a lot of people and projects.</p>
<p>Derek&#8217;s planned migration to Rails was probably doomed from the beginning for several reasons:</p>
<ol>
<li>Derek chose the technology for the wrong reasons. He chose it partially based on the hype of Rails, but he envisioned it as a silver bullet that would magically make his application better just because it&#8217;s in Rails. Rails has advantages (not least of which is its language, Ruby), but it has drawbacks and weaknesses, too.</li>
<li>Rails didn&#8217;t fit Derek&#8217;s application model for CD Baby, and Derek&#8217;s application model is more important than the technology to be used, since it represents a business he understands well. Rails requires that your application fits its model, not the other way around. As Derek says:<br />
<blockquote><p>I hired one of the best Rails programmers…Jeremy [Kemper] could not have been more amazing, twisting the deep inner guts of Rails to make it do things it was never intended to do. But at every step, it seemed our needs clashed with Rails’ preferences.</p></blockquote>
</li>
<li>He ignored his existing experts for the new technology. Neither he nor his employees knew Ruby aside, perhaps, from playing around with it. This wasn&#8217;t a technology that was deemed to be appropriate from experience; this was a technology deemed appropriate by management (sorry Derek, you might still be getting your hands dirty with code, but you&#8217;re still management).<br />
<blockquote><p>I&#8217;ve wanted to introduce Ruby in my workplace for several years, but aside from a number of compile-time helper scripts, it hasn&#8217;t been appropriate to do so. First, our product isn&#8217;t in Ruby&#8217;s sweet spot. Second, none of my co-workers know how to deal with it or its development environment. Even when Ruby is a superior choice, it&#8217;s hard to introduce it, because I&#8217;m the only Ruby expert at work.</p></blockquote>
</li>
<li>Derek approached the project as a whole-environment ground-up rewrite with a One Big Day deployment, without considering ways to phase it in over time. It&#8217;s almost always possible to find interface points where you can replace one broken piece at a time. Ultimately, this is what the Rails folks <del>would</del><ins>should</ins> tell you anyway: replace one area at a time, each with a different codebase. Interface them as REST-ful services. Don&#8217;t make them depend on a single database schema.</li>
</ol>
<p>Derek is wrong, though: language matters. A <em>&#8220;better&#8221;</em> language may not be the right choice for your environment, but its lessons will help you immensely. Without the Ruby and Rails experience, Derek would not have known to apply the lessons Ruby teaches to his PHP rewrite. I find that I write both C++ and C# with strong Ruby flavours these days. My boss, who has only used Ruby casually, has come to prefer the Ruby method naming convention (like_this) and a number of Rubyisms that I&#8217;ve introduced.</p>
<p>Ultimately, though, Derek&#8217;s Rails rewrite failed because he made a number of classic technology management mistakes. Not because of Ruby, Rails, or PHP. Because of management decisions made for the wrong reasons. Fortunately, he recognised this and was willing to reverse an expensive decision to fit his business better.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/09/23/on-derek-sivers-return-to-php%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ontario Votes: Voting Format Referendum</title>
		<link>http://www.halostatue.ca/2007/09/21/ontario-votes-voting-format-referendum/</link>
		<comments>http://www.halostatue.ca/2007/09/21/ontario-votes-voting-format-referendum/#comments</comments>
		<pubDate>Fri, 21 Sep 2007 17:54:58 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Politics]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/09/21/ontario-votes-voting-format-referendum/</guid>
		<description><![CDATA[There&#8217;s a referendum going on in Ontario on how we will vote in the future. Others summarize it far better than I do:

Spacing.ca — MMP Primer Part I
Spacing.ca — MMP Primer Part II
Spacing.ca &#8211; Web Resources for MMP

I don&#8217;t think that it&#8217;s a bad system, but I am concerned about the reduction in the number [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a referendum going on in Ontario on how we will vote in the future. Others summarize it far better than I do:</p>
<ul>
<li><a href="http://spacing.ca/votes/?p=356">Spacing.ca — MMP Primer Part I</a></li>
<li><a href="http://spacing.ca/votes/?p=394">Spacing.ca — MMP Primer Part II</a></li>
<li><a href="http://spacing.ca/votes/?p=357">Spacing.ca &#8211; Web Resources for MMP</a></li>
</ul>
<p>I don&#8217;t think that it&#8217;s a bad system, but I am concerned about the reduction in the number of geographically-bound seats (ridings) from 107 to 90; I&#8217;d rather see us have 120 geographically-bound seats and an <em>additional</em> 29 &#8220;list&#8221; seats. I haven&#8217;t really decided which way I&#8217;m going to vote on it, but I am edging in favour of it.</p>
<p>Still, it&#8217;s interesting stuff and if you&#8217;re an Ontarian, you really need to vote on this.</p>
<p><strong>Updated 2007.09.24</strong>: Added the link to the Spacing web resources for MMP. It&#8217;s important to note that MMP isn&#8217;t just a random proposal, but something strongly considered by fellow Ontarians.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/09/21/ontario-votes-voting-format-referendum/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FogBugz World Tour in Toronto</title>
		<link>http://www.halostatue.ca/2007/09/21/fogbugz-world-tour-in-toronto/</link>
		<comments>http://www.halostatue.ca/2007/09/21/fogbugz-world-tour-in-toronto/#comments</comments>
		<pubDate>Fri, 21 Sep 2007 12:28:45 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/09/21/fogbugz-world-tour-in-toronto/</guid>
		<description><![CDATA[So, Joel Spolsky has been making his world tour demonstrating the latest version of FogBugz (6.0), and I was able to attend last night&#8217;s demonstration. It was a small pleasure to be able to meet someone whose blog I&#8217;ve been reading for several years.
Joel doesn&#8217;t present FogBugz as a bug tracking tool, but as a [...]]]></description>
			<content:encoded><![CDATA[<p>So, Joel Spolsky has been making his world tour demonstrating the latest version of FogBugz (6.0), and I was able to attend last night&#8217;s demonstration. It was a small pleasure to be able to meet someone whose blog I&#8217;ve been reading for several years.</p>
<p>Joel doesn&#8217;t present FogBugz as a bug tracking tool, but as a communications tool. FogBugz is definitely an example of opinionated software, and works better when you adapt your work practices to it rather than trying to make it adapt to your work practices. After the demo, I asked Joel how he felt FogBugz and Basecamp work together or differ. His response suggests that there&#8217;s some similarities in how the two tools work, although he sees limitations in how Basecamp handles tasks and schedule changes. (Disclaimer: I have not used either FogBugz or Basecamp at this point.)</p>
<p>The software development lifecycle as presented by FogBugz is presented in its five major modules:</p>
<ul>
<li>Vision and design (wiki)</li>
<li>Implementation (project management)</li>
<li>Release planning (evidence based scheduling)</li>
<li>QA (bug tracking)</li>
<li>Support (email and discussion)</li>
</ul>
<p>Of all of the features that I saw, the wiki seemed the least useful, although the WYSIWYG editor for it was pretty impressive. The value in the wiki is not the editing space that it provides, but that it provides it in the same place as you track your implementation, releases, QA, and support.</p>
<p>The other three pieces are all based around case management. A case in FogBugz can be a feature, a bug, or even a development task. Cases have time estimates and work times that are used in calculating estimated ship dates. FogBugz uses R-squared analysis of a developer&#8217;s estimates and actual work time to determine their reliability of estimates, and then runs Monte Carlo simulations to determine when the last feature or bug required to be fixed will likely be completed based on current task assignment, giving an estimated ship date. It&#8217;s all very impressive. (Estimates and work times aren&#8217;t immune to gaming, but that&#8217;s more of a social problem than a technological problem.)</p>
<p>Case entry and management is insanely simple. There are no required fields (which will, of course, bother some people), but it makes adding cases (which are tasks, bugs, and even support requests) dead simple. There&#8217;s no implicit dependency tracking, but you can easily link two cases together simply by adding a note (e.g., &#8220;waiting for case 72&#8243;) and FogBugz automatically provides a link between them. One clones bugs the same way. There&#8217;s good SCM integration into FogBugz (including for Perforce), and there&#8217;s even a VisualStudio plug-in for task/case management.</p>
<p>The demo was useful to see, but the hard part will be in seeing exactly how it would integrate into work&#8217;s development cycle. It&#8217;s not that expensive, so it may be worth getting a few licenses (or trying a few months of the hosted version) so that we can see whether it would work for us.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/09/21/fogbugz-world-tour-in-toronto/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Beyond time</title>
		<link>http://www.halostatue.ca/2007/08/04/beyond-time/</link>
		<comments>http://www.halostatue.ca/2007/08/04/beyond-time/#comments</comments>
		<pubDate>Sun, 05 Aug 2007 02:26:35 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby PDF]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/08/04/beyond-time/</guid>
		<description><![CDATA[In Twitteriffic today, I hit the wrong button on a message sent by Nathaniel Talbott and it took me to his blog, which had his entry about handing off test/unit to Ryan Davis. It has taken me a long time to reach this point, but it has to happen: I no longer have time to [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://iconfactory.com/software/twitterrific" title="Twitteriffic by Iconfactory">Twitteriffic</a> today, I hit the wrong button on a message sent by <a href="http://www.twitter.com/ntalbott" title="Nathaniel's Twitter Profile">Nathaniel Talbott</a> and it took me to his <a href="http://blog.talbott.ws" title="Nathaniel's Blog">blog</a>, which had his entry about <a href="http://blog.talbott.ws/articles/2007/6/20/test-unit-a-time-to-maintain-and-time-to-hand-off" title="test/unit: A time to maintain, and a time to hand off">handing off test/unit</a> to Ryan Davis. It has taken me a long time to reach this point, but it has to happen: I no longer have time to maintain PDF::Writer and most of its support libraries. I need a successor. Over the last year (since RubyConf &#8216;06), I have been talking with several people, but no one has actually submitted patches for me to review so we could push out some fixes.</p>
<p>I don&#8217;t really want to give up PDF::Writer or its ancillary libraries, but I owe it to the community to find a maintainer who will be more responsive and put more effort into it than I have. There are some issues to sort out regarding the pieces of the projects, and some changes that I would like to see someone implement. There are basically three projects:</p>
<ol>
<li>Transaction::Simple. This has improved significantly since the last release, but I have not yet implemented the Ruby 1.9 Marshal.load block trick that Matz implemented for me after a minimal case for a <code>#become</code>-like behaviour was shown.</li>
<li>color-tools: This involves someone else, because after some preliminary discussion last year, I moved the color-tools codebase to the Color project on RubyForge and restructured things to be a bit smarter. There&#8217;s also some work that should happen hear regarding colour profiles, but that&#8217;s manageable. I basically want to work with the current owner of the Color project to hand this entire project off to someone who is interested in the math behind colours, and has the expertise to do something with it.</li>
<li>PDF::Writer. The big one. <strike>I need someone to take care of this.</strike> No, the community needs someone to take care of this. I&#8217;m more than willing to share some thoughts about the code, but it&#8217;s a bit of a mess, and there are better ways to do what I did. The code can&#8217;t support the ultimate goal of reading.</li>
</ol>
<p>None of this means that I&#8217;m giving up on Ruby, or on PDF generation; if I find time, you may yet find a different set of PDF tools from me in the future. But PDF::Writer is here and it needs someone to help maintain it.</p>
<p>Could that be you? Comments open on this post for interested parties to let me know. Be warned: I&#8217;m not just handing off PDF::Writer. I&#8217;m going to be looking at code samples; wanting patches. I need to know that you&#8217;re going to give the care the PDF::Writer needs and deserves before I hand off the virtual keys to the project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/08/04/beyond-time/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Changes Coming</title>
		<link>http://www.halostatue.ca/2007/08/02/changes-coming/</link>
		<comments>http://www.halostatue.ca/2007/08/02/changes-coming/#comments</comments>
		<pubDate>Fri, 03 Aug 2007 03:49:46 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/08/02/changes-coming/</guid>
		<description><![CDATA[So far, I&#8217;ve had two abortive attempts at personal blogging; I still want to blog, but I have to figure out what I want it to be about, and how much I want to talk about work (if at all).
I&#8217;m going to be playing with some new themes for WordPress and some new plug-ins while [...]]]></description>
			<content:encoded><![CDATA[<p>So far, I&#8217;ve had two abortive attempts at personal blogging; I still want to blog, but I have to figure out what I want it to be about, and how much I want to talk about work (if at all).</p>
<p>I&#8217;m going to be playing with some new themes for WordPress and some new plug-ins while I work with this. In the meantime, I will be disabling new user registrations (at least temporarily, and possibly permanently) and comments on existing posts that aren&#8217;t disabled (they should all be, but I haven&#8217;t verified). I may take Joel Spolsky&#8217;s advice on not having comments enabled, but I&#8217;m not sure. I will be deleting <em>all currently registered users</em>, too. There&#8217;s been a slow but steady tend of spam-users being created. They can&#8217;t do anything, but it&#8217;s still annoying.</p>
<p>I&#8217;m also looking for a single webhost to give me a reasonable yearly price for good performance (the hosts at OLM and 1&amp;1 have been slowing down, and while I liked Linode, I find that I don&#8217;t actually want to manage everything that way) with shell access and compile rights (so I can put Ruby on their system if they haven&#8217;t). I might like a Linode-like system where I don&#8217;t have to manage everything. I don&#8217;t care about email; all of that needs to be directed through my Google Apps account. I&#8217;d like to consider running one of the Ruby/Rails blogging packages (and I&#8217;m not sure which one, to be honest), but I want it to be reasonably complete and easy to use with plug-ins like I can get for WordPress (I&#8217;m going to be adding twitter integration soon, via plug-ins). Any ideas? Email them to austin at zieglers dot ca and let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/08/02/changes-coming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Responding to Comments on “What’s Wrong…”</title>
		<link>http://www.halostatue.ca/2007/04/27/responding-to-comments-on-what-s-wrong/</link>
		<comments>http://www.halostatue.ca/2007/04/27/responding-to-comments-on-what-s-wrong/#comments</comments>
		<pubDate>Fri, 27 Apr 2007 19:03:41 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/04/27/responding-to-comments-on-%e2%80%9cwhat%e2%80%99s-wrong%e2%80%a6%e2%80%9d/</guid>
		<description><![CDATA[Huw Collingborne: I don&#8217;t know if Bitwise has an anti-Ruby agenda. I know that your initial articles that I read last year were…I don&#8217;t have anything nice to say about them, truthfully, I think they were that bad. On the other hand, you have committed some pretty serious resources with Sapphire in Steel, so I [...]]]></description>
			<content:encoded><![CDATA[<p><em>Huw Collingborne</em>: I don&#8217;t know if Bitwise has an anti-Ruby agenda. I know that your initial articles that I read last year were…I don&#8217;t have anything nice to say about them, truthfully, I think they were that bad. On the other hand, you <strong>have</strong> committed some pretty serious resources with Sapphire in Steel, so I know you like Ruby.</p>
<p>As far as editorial responsibilities, I think that you <em>do</em> have a responsibility to ensure that what an author writes is both sensibly written and doesn&#8217;t contain gross errors. Editing does <em>not</em> mean that you change the authors&#8217; words for them. You let them know when something isn&#8217;t clear or likley to be misunderstood. This was the policy at Artima&#8217;s <em>Ruby Code &amp; Style</em> under James Britt. The words for the article that I wrote (and another that hasn&#8217;t yet seen the light of day, so I will probably publish it here after rewriting it) are all mine. Not someone else&#8217;s.</p>
<p><em>Matthew Huntbach</em>: Somehow, I missed the reference to that other article. Aside from the fact that GameSpy made it nearly unreadable with stupid pagination, the original author&#8217;s point is as muddled as your own on this matter (of array addition). If a lot of people missed that point on array addition, I think that it&#8217;s clear your concept in writing that point was not.</p>
<p>You similarly missed my main point about Ada: Ada is actually a fine language and had reasonably &#8220;packaging&#8221; semantics that would act a lot <em>like</em> object orientation if used properly. Ada failed primarily because people could get cheap and easy compilers for C++, but Ada was completely proprietary. That&#8217;s why I pointed out Turbo C++ specifically. Pascal lasted a lot longer than it should have, because of Turbo Pascal and later Delphi. Similarly, Java would not have made the impact that it did without <code>javac</code> having been freely available.</p>
<p>You suggested that academics have had to be convinced that OOP was more than a fad. Personally, I have yet to be convinced that it&#8217;s more than a fad. I don&#8217;t mean, by that, that OO will go away. It will lose its primal position in CS at some point as people realise that it&#8217;s just another technique for organising your code, and it doesn&#8217;t automatically solve your problems. I&#8217;ve had enough arguments with people who don&#8217;t know how to do object modelling to strongly believe that most people don&#8217;t understand OO at all. I suspect that people like Booch and Rumbaugh understand it less than most, given how loudly they have trumpeted it without consideration for reality.</p>
<p>Let me make it clear: your impression that Ruby isn&#8217;t a silver bullet isn&#8217;t what&#8217;s embarrassing, in my opinion. Your arguments attempting to support your impression are muddled and sometimes simply incorrect.</p>
<p>You can say that you don&#8217;t think it&#8217;s all that radical. I&#8217;d agree with you. I&#8217;m not necessarily convinced that Ruby 1.8 is a good teaching language: there&#8217;s a few ugly, weird corner cases. Yet Chris Pine thought well enough that he wrote <em>Learn to Program</em>. Ruby will help people learn what it means to be intentional in their programming, and less rely on an IDE to write code for them (as is increasingly necessary with overwrought, overweight frameworks and languages like C#, Java, and to some degree C++). I have adapted my C++ code sytle to follow a very Ruby style in this—and it has really improved the readability and maintainability in the place where I work. So much so that there are people who now do the same things that I do.</p>
<p>For what it&#8217;s worth, I have little problems with academics, and I have significant problems with the asinine responses you received from members of the Ruby community. I do think that academics often forget that there is a real programming world out there while they&#8217;re teaching (having interviewed dozens of would-be programmers straight out of university with a CS degree but no knowledge)—but pushing for something bigger and better and smarter isn&#8217;t a bad thing, and academic researchers are necessary to push that forward. Non-researchers, though, seem to change very slowly and push ideas that, in practice, haven&#8217;t worked out very well in implementation—or, perhaps, were too early and need to be rediscovered again.</p>
<p>Static typing hasn&#8217;t proven to be all that useful—it catches a very small class of errors at compile-time while hiding much more serious errors (buffer overflows, for example) a run-time. (Ada wasn&#8217;t vulnerable to this, of course, because it put static typing into both compile- and run-time both.) Dynamic typing is much more likely to be useful in the long run, or some combination of it—either in Erlang&#8217;s &#8220;pattern matching&#8221; or in Haskell&#8217;s type inferencing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/04/27/responding-to-comments-on-what-s-wrong/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Oops…</title>
		<link>http://www.halostatue.ca/2007/04/27/oops/</link>
		<comments>http://www.halostatue.ca/2007/04/27/oops/#comments</comments>
		<pubDate>Fri, 27 Apr 2007 18:17:47 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/04/27/oops%e2%80%a6/</guid>
		<description><![CDATA[Sorry, folks. I&#8217;ve been so busy lately that I hadn&#8217;t even noticed that I had a number of unapproved comments on the Bitwise article that I wrote. They&#8217;re all approved now—I have no interest in censoring real comments. My mistake, and apologies.
]]></description>
			<content:encoded><![CDATA[<p>Sorry, folks. I&#8217;ve been so busy lately that I hadn&#8217;t even noticed that I had a number of unapproved comments on the Bitwise article that I wrote. They&#8217;re all approved now—I have no interest in censoring real comments. My mistake, and apologies.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/04/27/oops/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What&#8217;s Wrong With Bitwise Magazine?</title>
		<link>http://www.halostatue.ca/2007/03/17/whats-wrong-with-bitwise-magazine/</link>
		<comments>http://www.halostatue.ca/2007/03/17/whats-wrong-with-bitwise-magazine/#comments</comments>
		<pubDate>Sat, 17 Mar 2007 21:41:32 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/03/17/whats-wrong-with-bitwise-magazine/</guid>
		<description><![CDATA[I have a problem with <a href="http://www.bitwisemag.com/" title="Bitwise Magazine">Bitwise Magazine</a>. They have published several articles critical of Ruby—and those articles have been singularly devoid of informed content. I&#8217;ve seen better articles on Slashdot, to be honest. Huw Collingborne&#8217;s article from a while back was bad enough (although he has done significant work lately to redeem that [...]]]></description>
			<content:encoded><![CDATA[<p>I have a problem with <a href="http://www.bitwisemag.com/" title="Bitwise Magazine">Bitwise Magazine</a>. They have published several articles critical of Ruby—and those articles have been singularly devoid of informed content. I&#8217;ve seen better articles on Slashdot, to be honest. Huw Collingborne&#8217;s article from a while back was bad enough (although he has done significant work lately to redeem that with Sapphire in Steel), but the latest example, <a href="http://www.bitwisemag.com/2/What-s-Wrong-With-Ruby" title="What's Wrong with Ruby?">What's Wrong with Ruby?</a> is a shining example of ignorance masquerading as informed opinion.</p>
<p>It is obvious that Matthew Huntbach hasn&#8217;t done serious programming with Ruby or serious analysis of programs that are already in existence. Most of the vaporous commentary written (probably 80% of the article) would have been burned away by that simple exercise. Even <em>if</em> one were to accept the argument that <code>[1, 2, 3] + [10, 20, 30]</code> should be <code>[11, 22, 33]</code> instead of concatenation—an argument smashed as soon as one attempts to add heterogeneous arrays together, or arrays that don&#8217;t contain items that respond to <code>#+</code>—it would be trivial to add such a special case (and then abandon it because it <em>does</em> present such a special case to normal <code>Array#+</code>).</p>
<p>Mr Huntbach&#8217;s history is even questionable, with respect to Ada. Ada wasn&#8217;t accepted because it was something of a bastard language designed by committee (very similar to Pascal, but with amazingly strong type restrictions), not <em>just</em> because it was facing C++. Ada failed because Turbo C++ was cheap and, well, there was no Turbo Ada. It failed to capture the next generation of programmers because it wasn&#8217;t readily available the way that C and C++ were and introduced a number of significant development-time restrictions that made interacting with the rest of the operating system difficult. (It may not sound like it, but I actually <em>like</em> Ada, and I have ever since I took a class on it in early 1993. I still don&#8217;t program in it, although I have programmed in a descendant, PL/SQL.) If Java had not been available as a free download (as the JDK), no amount of computer science department gushing about it would have saved Java from the cheap and free C/C++ compilers available at the time. Ada was doomed because the whole world was changing (and not just to OO-style development) and it was stuck in a restrictive model.</p>
<p>The comparison of Ruby to Ada is a false one in any case: Ada was <em>designed</em> to solve a particular subset of programming problems (namely, those requiring exact specifications, e.g., military applications) that required a very strict specification and completely predictable behaviour. If a particular sensor can only return values between -128 and 127, then you can make a subtype of Integer restricted to those values—and you can be absolutely guaranteed that the values in variables of those types will never be outside of those ranges. So Ada wasn&#8217;t designed as a <em>silver bullet</em>; it was designed as a language where specifications, interfaces, and code <em>very</em> closely matched. Ruby, on the other hand, was designed to solve problems that Matz had. When he introduced it, other folks realized that it helped them solve problems that <em>they</em> had. And so it has grown from 1993 to 2007, where now literally <em>thousands</em> of developers realize that they are running into the limits of current programming languages. They&#8217;re writing tens of thousands of lines of code that <em>don&#8217;t solve their problems</em>, but provide scaffolding for their programming languages. Once those are written, they can <em>usually</em> write code to solve their problems. I believe that Matz has even said that if something came along that was better than Ruby and helped him solve his problems better, he&#8217;d use it. (At the very least, he&#8217;d take ideas from it to make Ruby even better, which he has shown himself willing to do many times over.)</p>
<p>A lot of Bitwise&#8217;s articles seem to lack editing. Mr Huntbach&#8217;s article was, at best, stream of consciousness, and had the feel of a blog posting, not an article in a magazine. If you&#8217;re going to call yourself a magazine, invest in editing resources. Ruby Code &amp; Style, the Artima Ruby magazine, is going through some transitions and will be experimenting with a CodeProject-style system, where articles can go live without editing, <em>but they will still be edited by a team of volunteers</em>, and will be marked <em>unedited</em> until they are well-considered. Editing would raise questions about why easily refuted examples are chosen, fix errors with historical inaccuracies, and prevent articles as embarrassing as this one from being published under the magazine&#8217;s banner in the first place.</p>
<p>Yet, that&#8217;s not the only problems. As a long-time Rubyist, I&#8217;m <strong>actively embarrassed</strong> to read many of the comments on Mr Huntbach&#8217;s article. There are a few well-informed comments on the article, but the vast majority of them are painful to read and unnecessarily insulting. Mr Huntbach needs to be better informed, and his article needs editing, but there is <em>no</em> to be as insulting as some of the comments were.</p>
<p><strong>Edit</strong>: I was alerted to this article through a <a href="http://redhanded.hobix.com/cult/whatSWrongWithRubyHahYeahItSMe.html" title="post on RedHanded">post on RedHanded</a>. I find <em>Why the Lucky Stiff</em>&#8217;s response to be useful, but there&#8217;s a lot of the same attitude that I didn&#8217;t like seeing in the Bitwise comments on RedHanded&#8217;s comments. Remember <abbr title="Matz is nice and so we are nice">MINASWAN</abbr>, folks. Regardless of what you think of Mr Huntbach&#8217;s credentials or where he teaches, it gains nothing to slag them; help him understand where he&#8217;s wrong and we&#8217;ll be that much better for it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/03/17/whats-wrong-with-bitwise-magazine/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Transaction::Simple 1.4.0</title>
		<link>http://www.halostatue.ca/2007/02/03/transactionsimple-140/</link>
		<comments>http://www.halostatue.ca/2007/02/03/transactionsimple-140/#comments</comments>
		<pubDate>Sun, 04 Feb 2007 02:30:20 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/02/03/transactionsimple-140/</guid>
		<description><![CDATA[So I&#8217;ve finally had an opportunity to start working on my projects again, after having not worked on them for the latter part of 2005 and all of 2006. (I had other things <a href="http://www.halostatue.ca/2007/02/03/married-70-days/" title="Married (+70 days)">going on</a>.) I spent last night and today working on <a href="http://rubyforge.org/projects/trans-simple" title="Transaction::Simple">Transaction::Simple</a> 1.4.0. I converted it to [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve finally had an opportunity to start working on my projects again, after having not worked on them for the latter part of 2005 and all of 2006. (I had other things <a href="http://www.halostatue.ca/2007/02/03/married-70-days/" title="Married (+70 days)">going on</a>.) I spent last night and today working on <a href="http://rubyforge.org/projects/trans-simple" title="Transaction::Simple">Transaction::Simple</a> 1.4.0. I converted it to use Ryan Davis&#8217;s <a href="http://seattlerb.rubyforge.org/hoe/" title="hoe">hoe</a>. I made the .gem and the .tar.gz files idempotent (yes, my Rakefile <a href="http://pkg-ruby-extras.alioth.debian.org/upstream-devs.html" title="depends on RubyGems">depends on RubyGems</a>—if you have problems with this, use the .tar.gz, thanks) and provide setup.rb 3.4.1 as part of the distribution. I also added a post-rewind hook (<code>#_post_transaction_rewind</code>) to fix the issues <a href="http://www.halostatue.ca/2006/10/22/ruby-conference-2006-day-1-evening-friday-20-october-2006/" title="Ruby Conference 2006 - Day 1 Evening (Friday, 20 October 2006)  ">discussed last year</a>. I went through and eliminated the warnings that appear, and I&#8217;ve decided that the <code>#transaction</code> method is bogus and <strong>will</strong> be removed with Transaction::Simple 2.0.</p>
<p>Transaction::Simple provides a generic way to add active transaction support to objects. The transaction methods added by this module will work with most objects, excluding those that cannot be Marshal-ed (bindings, procedure objects, IO instances, or singleton objects).</p>
<p>I&#8217;m going to need to look at hoe a little closer to provide a patch that will support the way that I need to use it (hoe&#8217;s default behaviour is pretty good, if not <em>great</em> for greenfield development; I have legacy behaviours I need to support). If Ryan doesn&#8217;t accept it (or at least the functionality I need, even if it&#8217;s in a different form), I may need to keep a private version around, because I had to do entirely too much manually even <em>after</em> I reorganized the project to match a lot of Ryan&#8217;s expectations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/02/03/transactionsimple-140/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Married (+70 days)</title>
		<link>http://www.halostatue.ca/2007/02/03/married-70-days/</link>
		<comments>http://www.halostatue.ca/2007/02/03/married-70-days/#comments</comments>
		<pubDate>Sun, 04 Feb 2007 02:01:17 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2007/02/03/married-70-days/</guid>
		<description><![CDATA[As some folks may remember, I talked a lot last year about the fact that I was getting married. Well, 70 days ago, I did. On the 25th of November to my long-time (ten years!) girlfriend, Anne-Marie. It was a perfect wedding and a perfect day for the wedding. I have posted the pictures that [...]]]></description>
			<content:encoded><![CDATA[<p>As some folks may remember, I talked a lot last year about the fact that I was getting married. Well, 70 days ago, I did. On the 25th of November to my long-time (ten years!) girlfriend, Anne-Marie. It was a perfect wedding and a perfect day for the wedding. I have posted the pictures that I took on my Flickr account (<a href="http://flickr.com/photos/halostatue/sets/72157594410511098/" title="Austin &amp; Anne- Marie's Wedding">Austin &amp; Anne- Marie's Wedding</a>). There&#8217;s a lot more pictures that the wedding photographer took on his site: <a href="http://www.luxography.ca/gallery/amaustin/1/flash.html" title="Ceremony">Ceremony</a>, <a href="http://www.luxography.ca/gallery/amaustin/2/flash.html" title="Formals">Formals</a>, and <a href="http://www.luxography.ca/gallery/amaustin/3/flash.html" title="Reception">Reception</a>. Those will probably be taken down later this year; I may replicate them on my site when he does that. He has a real eye for what will work, and he has generous licensing terms. If anyone is looking for an event photographer in Toronto (or out of Toronto—he travels!), Brian is a great guy.</p>
<p>I will get back to work on the Ruby PDF Tools soon, as I will also be updating this blog a bit more often. The nature of my posts will also be expanding to include more non-Ruby topics, but Ruby-related content will remain the majority of what I post here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2007/02/03/married-70-days/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wow!</title>
		<link>http://www.halostatue.ca/2006/11/06/wow/</link>
		<comments>http://www.halostatue.ca/2006/11/06/wow/#comments</comments>
		<pubDate>Mon, 06 Nov 2006 22:56:15 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/11/06/wow/</guid>
		<description><![CDATA[RubyForge has interesting bandwidth requirements...]]></description>
			<content:encoded><![CDATA[<p>Tom Copeland just <a href="http://tomcopeland.blogs.com/juniordeveloper/2006/11/another_new_rub.html">reported</a> that there&#8217;s a new RubyForge mirror in town. My mirror has had its ups and downs, but we hit on a great approach a while back: I&#8217;m just serving the Windows installer (and I&#8217;m the only one serving it, for now). I&#8217;m serving about a terabyte a month doing that. I&#8217;m glad I can do something to help with the growing bandwidth requirements for RubyForge. Right now, RubyForge and its mirrors are serving three and quarter terabytes monthly. Just wow.</p>
<p>(I&#8217;m deep in the middle of wedding planning, so more on the Transaction::Simple stuff later.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/11/06/wow/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 3, Afternoon (Sunday, 22 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-afternoon-sunday-22-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-afternoon-sunday-22-october-2006/#comments</comments>
		<pubDate>Tue, 24 Oct 2006 19:00:13 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-afternoon-sunday-22-october-2006/</guid>
		<description><![CDATA[This afternoon we heard from Adam Keys with a one-act “play”, originally from the RejectConf evening. For your viewing pleasure,  USSRuby: Star Trek meets Ruby. Funny as can be.
I gave a quick introduction to the Google Summer of Code process and what it did for Ruby. The introduction was an adaptation of the talk [...]]]></description>
			<content:encoded><![CDATA[<p>This afternoon we heard from <a href="http://mvm.therealadam.com/articles/trackback/332">Adam Keys</a> with a one-act “play”, originally from the RejectConf evening. For your viewing pleasure,  <a href="http://halostatue.info/AdamKeys-USSRuby-Medium.mov">USSRuby: Star Trek meets Ruby</a>. Funny as can be.</p>
<p>I gave a quick introduction to the Google Summer of Code process and what it did for Ruby. The introduction was an adaptation of the talk that I gave at LRUG in July. The numbers: 17 volunteers; 96 applications; 84 eligible; ~25 desired; 10 accepted; 7 or 8 completed (I know we had 8 at the beginning of July; I think one more dropped out in the interim).</p>
<p>Greg Brown presented about his experience of doing Ruport for the Summer of Code. He was mentored by David Pollak.</p>
<p>Jeff Hughes talked about porting Ruby to Symbian phones. He was mentored by Dibya Prikash.</p>
<p>Jason Morrison spoke on Ruby Type Inference &#038; Code Completion for RDT. The approach he used was naïve, but based on DDP by Lex Spoon (S. Alexander Spoon), which is Demand-Driven Analysis with Goal Pruning. Type flow analysis; it unions types over contours. He was mentored by Chris Williams.</p>
<p>That ended RubyConf 2006. I’m looking forward to next year, and I’m campaigning very hard to have it in Toronto.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-afternoon-sunday-22-october-2006/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://halostatue.info/AdamKeys-USSRuby-Medium.mov" length="20111994" type="video/quicktime" />
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 3 (Sunday, 22 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-sunday-22-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-sunday-22-october-2006/#comments</comments>
		<pubDate>Tue, 24 Oct 2006 15:47:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-sunday-22-october-2006/</guid>
		<description><![CDATA[Justin Gehtland presented the sole Rails-related talk, as he was presenting <a href="http://www.streamlinedframework.org" title="Streamlined">Streamlined</a>. I’m quite impressed and would have loved to have known about this for my simple wedding guest list manager application that I wrote in Rails. The purpose of Streamlined is to fill in the stuff that’s necessary for the [...]]]></description>
			<content:encoded><![CDATA[<p>Justin Gehtland presented the sole Rails-related talk, as he was presenting <a href="http://www.streamlinedframework.org" title="Streamlined">Streamlined</a>. I’m quite impressed and would have loved to have known about this for my simple wedding guest list manager application that I wrote in Rails. The purpose of Streamlined is to fill in the stuff that’s necessary for the administrative work for a Rails application. It wholly rocks. By the new year, Streamlined will have a visual configuration mode for this.</p>
<p>While waiting for Sasada Koichi to set up, I suggested to Matz that perhaps something like RubyInline be included with the Ruby 1.9/2.0 release so that Transaction::Simple can dump singleton objects and the marshal format would be compatible between the various interpreters.</p>
<p>Sasada Koichi presented on the current state of YARV. He has recently gotten a job in Akihabara Sanctuary. The advances of YARV look impressive. He was running a Rails application on YARV with no problems. Nice.</p>
<p>John Lam reported on his Ruby/CLR bridge, which was started because he writes programs for his son’s birthday. Fascinating work, and amazing enough that Microsoft finally twisted his arms well enough for him to work on them to improve the CLR so that it better supports dynamic language. As someone—possibly James Gray—suggested at lunch: we’ve heard from three major platform vendors that they are taking Ruby very seriously. That rocks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-3-sunday-22-october-2006/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; matznote, Day 2 (Saturday, 21 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-matznote-day-2-saturday-21-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-matznote-day-2-saturday-21-october-2006/#comments</comments>
		<pubDate>Tue, 24 Oct 2006 04:32:51 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/24/ruby-conference-2006-matznote-day-2-saturday-21-october-2006/</guid>
		<description><![CDATA[Matz’s keynote this year was entitled “The Return of the Bikeshed, or Nuclear Plant in the Backyard.” Ruby is often seen by people as either a scripting language (which in the west is often seen as derogatory), a programming language (so vague as to be useless), a lightweight language (popular in Japan), and a dynamic [...]]]></description>
			<content:encoded><![CDATA[<p>Matz’s keynote this year was entitled “The Return of the Bikeshed, or Nuclear Plant in the Backyard.” Ruby is often seen by people as either a scripting language (which in the west is often seen as derogatory), a programming language (so vague as to be useless), a lightweight language (popular in Japan), and a dynamic language (relatively new). Matz applied the insights of the <a href="http://agilemanifesto.org/">Agile Manifesto</a> to programming languages (Steve Yegge is right that most people take the Agile Manifesto wrong and do it wrong; Steve Yegge is wrong in thinking that it’s therefore useless).</p>
<ul>
<li>Individuals and interactions over processes and tools: the language design should focus on users.</li>
<li>Working software over comprehensive documentation: the language should encourage readability.</li>
<li>Customer collaboration over contract negotiation: the language should be expressive, and helps communication between developers.</li>
<li>Responding to change over following a plan: the language should embrace changes, and be dynamic.</li>
</ul>
<p>Looking at this, matz concludes that Ruby is an <strong>Agile Language</strong>.</p>
<p>Matz noted that Ruby has Good things (it’s a sweet language, Rails, the community—as Martin Fowler says, Ruby people are nice); Ugly things (eval.c, parse.y); and Bad things (Ruby 2 being vapourware for such a long time: it’s close to being the longest vapourware in open source—Rite the concept is older than Parrot and Perl 6).</p>
<p>The Bikeshed represents an easy problem. People tend to argue about little things that they know enough about to do so, such as what colour a bikeshed should be. The amount of argument caused by a change is inversely proportional to the size of the change. Ruby has several bikesheds: the discussions on String and Symbol; the possible removal of private and protected; whether Ruby needs (optional) static typing.</p>
<p>On the other hand, nuclear plants are complex and important, so we tend to leave discussing them to the experts. So we spend most of our time discussing relatively unimportant things, leaving important things yet to be discussed.</p>
<p>Some consider Ruby a fragile language, but Ruby 1.8 is generally good enough. This means that although Matz would like to get Ruby 2.0 out, we’re not in a hurry and each idea has its own value which must be discussed. Instead of stopping bikeshed arguments, matz says we should accelerate them: Extreme Arguing. If arguing is good, we should make things easy enough to be argued by anyone.</p>
<p><span id="more-39"></span></p>
<p>The RCR process hasn’t worked out as well as matz wanted it to. Some people didn’t take RCRs very seriously; some took RCRs far too seriously. Thus, matz is introducing what he calls the Design Game. The purpose of the Design Game is to open language design to everyone in an accessible manner. It will:</p>
<ul>
<li>Gather Wild &#038; Weird Ideas</li>
<li>Try to make Ruby the Best Language Ever</li>
<li>Shed light to undefined corners of Ruby</li>
<li>Finally (if possible), document Ruby specification.</li>
</ul>
<p>There are some fundamental rules of the Design Game:</p>
<ol>
<li>Ruby will stay Ruby. We’re not creating a new language or a new Smalltalk or a new Lisp. About 80% &#8211; 90% compatibility will be preserved, if not more. Each proposal must follow the same philosophy we love about Ruby.</li>
<li>Design Game proposals must not be vague ideas. It’s hard to impossible to start useful discussions with vague ideas.</li>
<li>Design Game proposals must have rationale and analysis. Entries that don’t have a rationale and analysis section will be rejected out of hand. Matz will probably use a format similar to the Python Enhancement Proposal (PEP).</li>
<li>Discussion will happen on one or more mailing lists, possibly a single mailing list per proposal. <a href=”http://www.rcrchive.net/”>RCRchive</a> will probably be a starting point, but there may be a new system to control traffic: possibly qwik or trac.</li>
<li>Proposals with a prototype implementation will be favourably smiled upon as concrete code helps a fruitful discussion.</li>
<li>matz is still the Benevolent Dictator…but promises to be as open as possible.</li>
</ol>
<p>Matz is doing this because he wants to share the fun of language design among the community and is tired of the slow evolution of Ruby (despite him being the bottleneck). Most of us are using technology from three years ago and if we (Ruby) don’t accelerate, others will catch up. This is also to help educate developers in the community: language design shares much in common with other software design. Additionally, matz wants the process to be continuable if he were to be hit by a truck (heaven forfend).</p>
<p>Matz may or may not set a deadline for the Design Game and has tentatively considered 2007-04-30 as such a date. After that, we (the community) will classify proposals as either Good, Bad, or Ugly and as targeted for 1.9 or 2.0. The good proposals will be implemented, and if they are ready, they will be merged. If the game doesn’t work, it’s not a problem: we’ll try something else, we’ve lost nothing but time.</p>
<p>Matz is still planning on releasing a stable version of Ruby 1.9 (1.9.1) for Christmas 2007 with YARV and other changes to come.</p>
<p><a href=”http://www.rubyist.net/~matz/slides/rc2006/”>matznote slides</a></p>
<p>Important notes:</p>
<ul>
<li>The Game will apply to changes to core and standard libraries, but core is preferred.</li>
<li>They will be keeping up with Windows changes as Vista came.</li>
<li>Not necessarily for enterprisey stuff.</li>
<li>Tests should probably included with proposals, too.</li>
<li>The parser could theoretically be replaced in a non-backwards-compatible form.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-matznote-day-2-saturday-21-october-2006/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 2 (Saturday, 21 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-2-saturday-21-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-2-saturday-21-october-2006/#comments</comments>
		<pubDate>Tue, 24 Oct 2006 04:02:54 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-2-saturday-21-october-2006/</guid>
		<description><![CDATA[I overslept today and have a high-altitude headache. I ended up missing Nathaniel’s talk, which was how he’s running his Ruby consulting company and approaches that others can take.
Laurent Sansonetti’s demonstration on OS X integration with Ruby was very well done, with excellent demonstrations of controlling iTunes with Ruby from irb and with a Ruby/Cocoa [...]]]></description>
			<content:encoded><![CDATA[<p>I overslept today and have a high-altitude headache. I ended up missing Nathaniel’s talk, which was how he’s running his Ruby consulting company and approaches that others can take.</p>
<p>Laurent Sansonetti’s demonstration on OS X integration with Ruby was very well done, with excellent demonstrations of controlling iTunes with Ruby from irb and with a Ruby/Cocoa GUI. It’s nice to see Apple committing at least Laurent’s time to Ruby support. It’d be nice to see Microsoft committing resources, too.</p>
<p>My headache was too bad for me to attend Glenn Vandenburg’s talk about Rinda in the real world, which is too bad, because the parts of it that I caught seemed really interesting. Lunch, and then I came back half-way through the lightning talks. Very interesting stuff.</p>
<p>Rich Kilmer presented because Jim Weirich couldn’t be here this year, and he presented about the Indi service that he and Tom have been working on. Very interesting, and I think it could be an interesting service. I’ll probably play with it soon. (Or at least as he makes it available.)</p>
<p>Tim Bray presented on I18N and M17N as they relate to Ruby. The most extensive effort so far for identifying characters in human writing forms is Unicode; the Unicode Standard 5.0 is soon to be released. Unicode 5.0 and ISO 10646 are identical. Unicode characters are represented in 17 planes; the first plane is called the Basic Multilingual Plane. There’s only 9% usage in the total plane (1,114,112 available). Tim’s presentation was mostly a survey over what various languages do—and what Ruby should do. I had a chat with him after his presentation to clarify a few things, and I think we’re mostly in agreement. One interesting point: when Tim asked the audience if they understood Unicode, only about FIVE of us raised our hands (myself included). Tim recommends reading <a href="http://www.amazon.ca/gp/product/0195079930?ie=UTF8&#038;tag=halostatue-20&#038;linkCode=as2&#038;camp=15121&#038;creative=330641&#038;creativeASIN=0195079930">The World&#8217;s Writing Systems</a> by Peter T. Daniels, the W3C&#8217;s <a href="http://www.w3.org/TR/charmod" title="Character Model for the WWW 1.0: Fundamentals">Character Model for the WWW 1.0: Fundamentals</a> and the upcoming <a href="http://www.amazon.ca/gp/product/0321480910?ie=UTF8&#038;tag=halostatue-20&#038;linkCode=as2&#038;camp=15121&#038;creative=330641&#038;creativeASIN=0321480910">Unicode Standard, Version 5.0</a>.</p>
<p>Michael Granger presented the Linguistics package. Really neat. When it was done, I offered him the Text::Hyphen package for multilingual hyphenation. I need someone to pick it up and maintain it as I no longer have time to maintain most of the projects that I work on. He seemed interested, but I’ll catch him tomorrow and talk with him in more detail—or I’ll try to catch him after the conference by email.</p>
<p>Dinner was acceptable (barely; the vegetarian dish was the same thing that they had served for lunch on Day 1), but I met Kirill Sheynkman who may end up joining the PDF::Writer project in the near future to work on things that I don’t have time to work on, freeing me up from having to worry about certain maintenance issues so I can work on the next generation that includes reading. After that, the matznote.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/24/ruby-conference-2006-day-2-saturday-21-october-2006/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 1 Evening (Friday, 20 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/22/ruby-conference-2006-day-1-evening-friday-20-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/22/ruby-conference-2006-day-1-evening-friday-20-october-2006/#comments</comments>
		<pubDate>Sun, 22 Oct 2006 13:57:37 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby PDF]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/22/ruby-conference-2006-day-1-evening-friday-20-october-2006/</guid>
		<description><![CDATA[Dinner tonight was at Old Chicago with Hal Fulton, Ara Howard, Patrick Hurley, Tim Pease, and various others whose names I can’t remember offhand. Great dinner, and I was able to fully explain the problem with WHY the Ruby extension situation on Windows is so bad. I also started talking about THE big problem that [...]]]></description>
			<content:encoded><![CDATA[<p>Dinner tonight was at Old Chicago with Hal Fulton, Ara Howard, Patrick Hurley, Tim Pease, and various others whose names I can’t remember offhand. Great dinner, and I was able to fully explain the problem with WHY the Ruby extension situation on Windows is so bad. I also started talking about THE big problem that I have with Transaction::Simple and haven’t figured out how to solve in a general way (details below). They weren’t quite understanding it, so before the matz Roundtable came up, I showed them a test case that I had come up with while talking with Francis Cianfrocca (who is behind EventMachine and the implementation of Net::LDAP).</p>
<p>The matz Roundtable was pretty short; not too many questions were asked this year, and the discussion didn’t continue for an hour as it did the year before. I was shot down when asking for “become” behaviour (related to the Transaction::Simple bug). After the Roundtable, I managed to snag matz to talk about the problem which led me to request this. I showed him the test case:</p>
<p><span id="more-37"></span></p>
<pre>#!/usr/local/bin/ruby
require 'rubygems'
require 'transaction/simple'

class Child
  attr_accessor :parent
end

class Parent
  include Transaction::Simple

  attr_reader :children
  def initialize
    @children = []
  end

  def < <(child)
    child.parent = self
    @children << child
  end
end

parent = Parent.new
puts "parent.object_id: #{parent.object_id}"
parent << Child.new
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
puts "starting transaction"
parent.start_transaction
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"
puts "aborting transaction"
parent.abort_transaction
puts "aborted transaction"
puts "parent.object_id: #{parent.object_id}"
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"</pre>
<p>producing the output:
</pre>
<pre>parent.object_id: 3265800
parent.children[0].parent.object_id: 3265800
starting transaction
parent.children[1].parent.object_id: 3265800
aborting transaction
aborted transaction
parent.object_id: 3265800
parent.children[0].parent.object_id: 3265500
parent.children[1].parent.object_id: 3265800</pre>
<p>This bug affects PDF::Writer’s table generation and contributes significantly to the high memory usage. What’s happening is that when you call Parent#start_transaction, Transaction::Simple creates a transaction checkpoint with Marshal::dump. When you call Parent#rewind_transaction or or Parent#abort_transaction, the transaction checkpoint is reverted. This reversion is extremely robust except for this one item. What we really need is something like:</p>
<pre>self = Marshal::restore(checkpoint)</pre>
<p>Obviously, that won’t work and this leads to the problem that is illustrated above. After long discussion with Tim Pease, Patrick Hurley, and Matz, we came up with a workaround that can work for the example bug and for PDF::Writer. It’s not super-efficient, though. Essentially, I will modify Transaction::Simple to have callback methods for post-processing after a transactional operation. Something like this:</p>
<pre>class Parent
  def post_restore_hook
    @children.map! { |child|
      child.parent = self unless self.object_id == child.parent.object_id
      child
    }
  end
end

parent = Parent.new
puts "parent.object_id: #{parent.object_id}"
parent < < Child.new
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
puts "starting transaction"
parent.start_transaction
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"
puts "aborting transaction"
parent.abort_transaction
parent.post_restore_hook # would be called automatically in the real case
puts "aborted transaction"
puts "parent.object_id: #{parent.object_id}"
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"
</pre>
<p>Which produces the output:
</pre>
<pre>parent = Parent.new
puts "parent.object_id: #{parent.object_id}"
parent < < Child.new
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
puts "starting transaction"
parent.start_transaction
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"
puts "aborting transaction"
parent.abort_transaction
parent.post_restore_hook
puts "aborted transaction"
puts "parent.object_id: #{parent.object_id}"
puts "parent.children[0].parent.object_id: #{parent.children[0].parent.object_id}"
parent << Child.new
puts "parent.children[1].parent.object_id: #{parent.children[1].parent.object_id}"</pre>
<p>This isn't great: it doesn't feel very Ruby to me, but it does get the job done. It's also not very efficient. After thinking about this for the better part of an hour, matz has suggested that there might be a very ugly hack that’s possible that he’ll look at for me, which may be able to implement everything in Transaction::Simple.</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/22/ruby-conference-2006-day-1-evening-friday-20-october-2006/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 1 (Friday, 20 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/20/36/</link>
		<comments>http://www.halostatue.ca/2006/10/20/36/#comments</comments>
		<pubDate>Sat, 21 Oct 2006 01:44:52 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/20/36/</guid>
		<description><![CDATA[The Embassy Suites is a relatively nice hotel, although the air is far too dry for me to comfortably to sleep in. The breakfast area this morning was very nice; they make omelettes to your taste.
We were told that Bil Kleb and NASA have provided power cords throughout the room and we shouldn’t be daisy-chaining [...]]]></description>
			<content:encoded><![CDATA[<p>The Embassy Suites is a relatively nice hotel, although the air is far too dry for me to comfortably to sleep in. The breakfast area this morning was very nice; they make omelettes to your taste.</p>
<p>We were told that Bil Kleb and NASA have provided power cords throughout the room and we shouldn’t be daisy-chaining if we want to continue having power in the room. Josh Susser has the flu and so will not be presenting tomorrow (“More than enough rope to hang yourself”) and his talk will be replaced with nine five-minute lightning talks. I made an announcement that I’m in discussions with the VS developers at Microsoft and am trying to get real examples of problems with Win32 extensions. I’ll post a summary of the discussion so far to my blog a little later. When the discussion has been held, I’ll post a summary of what we got from it. Ryan Davis re-announced the RejectConf scheduled for after matz’s keynote. Wireless access has been spotty all day; the Embassy Suites isn’t much ready for a room of 300 people, all with computers that they want to get on wireless.</p>
<p>The first talk of the morning is Masayoshi Takahashi about the history of Ruby. As should be expected from the inventor of the Takahashi presentation method, he’s an excellent presenter. His talk was highly entertaining and informative. Most people know that there was no Ruby conference in Japan prior to 2006, although there were conferences that included Ruby (the LL day/weekend conferences, culminating in this year’s LL Ring; also the YAPRC (Yet Another Perl and Ruby Conference) events for a few years. The reason for this? There wasn’t enough passion in the Japanese Ruby community to spur the planning of such a conference. There were so many books published for Ruby in Japan that there was a bubble that burst in 2003.</p>
<p>The second talk was Evan Phoenix’s (née Webb) discussion of Sydney and Rubinius. This is a fascinating project that may provide some direction in the future, but is something Evan will be working on over the next while and will be worth watching as it possibly becomes another Ruby interpreter.</p>
<p>After lunch, Geoffrey Grosenbach gave his talk about the various dynamic graphic libraries in Ruby with demonstrations of why one would use graphical representation of data with example Ruby code on how to generate many of them. There’s definitely a lot of things to consider for future projects. I may be pulling some of this into PDF::Writer (both SVG and PNG generation will be directly useful) when I finally get back to working on that.</p>
<p>Kevin Clark’s presentation about mkrf (a Rake-based replacement for mkmf) was fascinating, and I think that there’s a possibility that it could be a very useful thing in the future, especially if dist-utils style capabilities are added in the near future, increasing the ability to use alternative compilers. I think it’ll be a little while before mkrf is really production-ready. Chad asked Kevin to write some code for RubyGems to help look for external capabilities (such as the presence of the MySQL library); I’d have some concern about this working well on Windows because mkrf doesn’t yet really have good Windows support, but I think it’s very important to add.</p>
<p>Zed Shaw gave an interesting presentation about security testing with fuzzing and and some statistical analysis. If you&#8217;re doing anything with anything that has to do security checking, you really want to read his slides when he’s posted them—the concepts he presents are good for that. By the way: if you’re writing software that people use, you’re writing something that needs security checking.</p>
<p>Finally, John Long talked about Radiant, the Rails-based CMS which now runs ruby-lang.org. It seems like it could turn out to be a very interesting CMS in the future, but it has a ways to go now.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/20/36/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ruby Conference 2006 &#8211; Day 0 (Thursday, 19 October 2006)</title>
		<link>http://www.halostatue.ca/2006/10/20/ruby-conference-2006-day-0-thursday-19-october-2006/</link>
		<comments>http://www.halostatue.ca/2006/10/20/ruby-conference-2006-day-0-thursday-19-october-2006/#comments</comments>
		<pubDate>Fri, 20 Oct 2006 19:07:31 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[RubyConf]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/10/20/ruby-conference-2006-day-0-thursday-19-october-2006/</guid>
		<description><![CDATA[I landed safely in Denver and managed to find the express shuttle to the Embassy Suites. Somehow, I didn’t manage to find the ticket desk for the express shuttle, but I was allowed on the shuttle and paid cash when we arrived. Both Caleb Claussen and Ogino Jun-ichi were on the platform. Of the eleven [...]]]></description>
			<content:encoded><![CDATA[<p>I landed safely in Denver and managed to find the express shuttle to the Embassy Suites. Somehow, I didn’t manage to find the ticket desk for the express shuttle, but I was allowed on the shuttle and paid cash when we arrived. Both Caleb Claussen and Ogino Jun-ichi were on the platform. Of the eleven people in the van, five of us were Rubyists coming to the conference (I believe the other two were Mike and Claire from England; I may have the names wrong).</p>
<p>Shortly after arriving, Jim Freeze, Bil Kleb, Hal Fulton, Chris Lehman, and Alan Whitaker and I went to Casa Bonita: a Mexican restaurant with third-rate food (especially the vegetarian food; Velveeta is not Mexican) and second-rate entertainment, including a sketch artist, a too-loud Mariachi band, and a gal who did high dives into a pool not too far from our table. I’m not sure I’d go back to it, but it was well worth the visit, especially with the folks who were there. We had a really good time and had some interesting discussions. RubyConf is off to a great start.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/10/20/ruby-conference-2006-day-0-thursday-19-october-2006/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby on Windows: A Note for Microsoft</title>
		<link>http://www.halostatue.ca/2006/09/21/ruby-on-windows-a-note-for-microsoft/</link>
		<comments>http://www.halostatue.ca/2006/09/21/ruby-on-windows-a-note-for-microsoft/#comments</comments>
		<pubDate>Fri, 22 Sep 2006 02:46:12 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/09/21/ruby-on-windows-a-note-for-microsoft/</guid>
		<description><![CDATA[Good evening. I have finally sat down to try to pull together the issues related to building Ruby with Visual Studio 8. I apologize for the lengthy delay in producing this so that the conversation can continue on this matter.
As I said back in June, the primary concern that most Ruby developers have is the [...]]]></description>
			<content:encoded><![CDATA[<p>Good evening. I have finally sat down to try to pull together the issues related to building Ruby with Visual Studio 8. I apologize for the lengthy delay in producing this so that the conversation can continue on this matter.</p>
<p>As I said back in June, the primary concern that most Ruby developers have is the difficulty in compiling extensions on Windows, especially those developers who have extensive background with UNIX-like environments, where you can easily do:</p>
<pre>./configure &amp;&amp; make &amp;&amp; make test &amp;&amp; sudo make install</pre>
<p>or</p>
<pre>ruby extconf.rb &amp;&amp; make &amp;&amp; make install</pre>
<p>or</p>
<pre>gem install &lt;name-of-extension-gem&gt;</pre>
<p>Visual Studio 2005 (VS8) does not make this easier because of the choice to require manifests for the unmanaged assemblies with SxS installation. Much of this can be automated, but some common tools are completely missing from the VS8 tool chain that make building harder than it needs to be. To be fair, there are tools missing from the Ruby environment that make building extensions harder than it needs to be.</p>
<p>Ruby needs tools similar to the Python distutils, but this is something that the Ruby community must provide, not Microsoft. So far, though, no one has stepped forward to create such a beast, although tools like mkrf from this year’s Google Summer of Code could be used to improve this situation considerably.</p>
<p>This does not mean that Microsoft has nothing that it can do to help here. If Microsoft wishes to win the Ruby community toward using VS8 instead of continuing to use VC6 or stepping sideways toward the MinGW/MSYS combination, it needs to offer positive steps toward increased compatibility even between Microsoft’s tools and offer some way of making it easier to build tools that are primarily developed on UNIX-like platforms for Windows.</p>
<p>Let me be clear: I consider using MinGW/MSYS a step <em>backwards</em> (not sideways) for the Ruby community to take, because it goes to a known-buggy runtime (VC6’s MSVCRT.DLL) and will have a harder time interfacing with Microsoft’s modern technologies moving forward. Not everyone considers this a problem; they need Windows versions of tools that they have been using on UNIX-like environments more than they need the advanced capabilities offered by the later runtimes. This is a compelling argument, but I do not find it wholly convincing.</p>
<p>There is a vocal contingent of Ruby developers that would like to be able to have a version of the Ruby One-Click Installer that <em>includes</em> a compiler as part of its distribution, possibly as a separate download. This is something that would matter significantly for people who use Ryan Davis’s RubyInline or ZenOptimize, and other development environments. Again, I don’t find this compelling (and would prefer <strong>not</strong> having such a thing as a single distribution package because it would be unnecessarily large). It is a significant concept, though, because the one thing that the Microsoft tool chain has over MinGW/MSYS is that it is easier to install and get running, even though it’s significantly harder to build extensions with.</p>
<h3 id="toc-what-do-we-need-from-microsoft">What Do We Need From Microsoft?</h3>
<p>This question is the source of considerable debate and anger. There is a level of mistrust of Microsoft in the Ruby community (especially the Japanese community) based on missteps by the Microsoft developer community with regards to backwards compatibility. For this, I’m going to quote Usa Nakamura, who builds the Ruby binaries that Curt uses for the Ruby One-Click Installer for 1.8.4 and 1.8.5 with some clarification by myself and URABE Shyouhei. The original messages were provided in response to a post that I made on the 26<sup>th</sup> of June, 2006 if they are needed.</p>
<blockquote><p>The problem of errno is not serious, I think. We will be able to avoid the problem with some simple code (for example, replace it with a function call by macro.) The real problems [arise from separate resource management per runtime DLL version, keeping independent file descriptor tables, memory management, etc., that are internally maintained and not open through any API].</p>
<p>The decision [by Microsoft to break] binary compatibility between versions of runtime […] is foolish. [Did they think] that passing file descriptors between DLLs [would not happen]? As time goes by, there will be some [need] to introduce such incompatibility, I know. […] VC7, VC7.1, and VC8 were shipped [in rapid succession], and they are mutually incompatible[…]. It&#8217;s crazy, to say the least.</p>
<p>I decided to [stay] with VC6 for the above-mentioned reasons. If MS keeps shipping incompatible versions at each upgrade, I will throw away VC and shift to MinGW. If MinGW also follows [MS’s binary incompatibility], I&#8217;ll shift to Cygwin or throw away Windows as development environment.</p>
<p>[I] hope [that] Microsoft [could provide a] wrapper DLL [for] MSVCRT80.DLL named MSVCRT.DLL. If MS prepares such a mechanism, [there will be] binary compatibility[…]. If so, [it wouldn’t matter whethera program links against MSVCRT80.DLL or MSVCRT.DLL].</p>
</blockquote>
<p>It’s bad enough where we have the source but prefer using pre-compiled binaries either because of time, trustworthiness, or compilation complexity. Ara Howard notes that compiling the GNU Scientific Library (GSL) on Windows is so complex without Cygwin or MinGW that there is a company that charges $600 for a compiled version of the source. Others have noted similar issues with other code.</p>
<p>It’s worse when we have third-party binary DLLs compiled with an earlier or later version of Microsoft tools. Ruby is receiving a lot of attention now because of Rails, and I suspect that Microsoft would love to have people using SQL Server as their database underneath Rails, but if there are problems compiling the binary extensions to link against the SQL Server interface drivers, this is less likely to happen or be common. Oracle drivers present a similar problem. We don’t have the source to recompile with the tool that we prefer, and the binary DLL we must use may have been compiled with an earlier incompatible version of the compiler.</p>
<p>(Let me digress for a moment and make it clear that this is an overall problem on all platforms, not just Windows; I have experienced it most often on Linux in my day job where I do C/C++ development. It is far more apparent on Windows, however, because it is unusual for there to be more than one C/C++ runtime on a UNIX-like system. Not impossible, but unusual.)</p>
<p>Thus, the first thing that we feel that would be beneficial from Microsoft would be some sort of runtime shim or wrapper that would allow us to use programs built with VC6, VC7, VC7.1, VC8 or even MinGW compatibly.</p>
<p>The second thing that we feel that would be beneficial from Microsoft would be a better command-line tool chain that is preferably compatible with many of the UNIX-style build commands. A minimal start for this would be command-wrappers that allow you to use a gcc/g++ front-end that actually calls VS8’s cl.exe with the appropriate command-line parameters. Microsoft’s move away from command-line support and toward devenv as the primary build environment helps most Windows developers, but hurts those who do their primary development on platforms other than Windows.</p>
<p>The third thing reaches into core functionality problems that Nobu Nakada posted about in late July:</p>
<ul>
<li>more unified I/O
<ul>
<li>nonblocking flag can be set on only sockets.</li>
<li>WaitForMultipleObjects doesn&#8217;t work with sockets.</li>
<li>APIs to tell how many bytes can be read immediately differfor ordinary file, console, socket and pipe.</li>
</ul>
</li>
<li>pseudo tty: pty feature is not supported at all now.</li>
</ul>
<p>Charlie Savage had some interesting things to say in a lengthy discussion in July while I was in Europe with limited Internet access:</p>
<blockquote><p>From my experience using both tool chains on Windows (for the ruby-prof extension and SWIG-based extensions for GEOS and GDAL).</p>
<ul>
<li>You can build Ruby extensions using MingW that run against Ruby built with VC++. I&#8217;ve done this with Ruby 1.8.2/1.8.4, various MingW releases and VC++ 2003 and VC++ 2005. This used to require changing a small bug in ruby.h for Ruby 1.8.2, but that bug has been fixed with 1.8.4.[…]</li>
<li>
<p>However, you cannot do this with MingW using VC++ built Ruby.</p>
<pre>ruby extconf.rb
make
make install</pre>
<p>The problem is that extconf is quite limited &#8211; it will assume you are building your extension with the same compiler that built Ruby (VC++). Python avoids this issue because disutils will recognize the compiler being used (MingW, VC++) for the extension and provide the correct command line parameters.</p>
</li>
<li>If mkrf can work like Python distutils, then it will become simple to use MingW to build extensions that work with VC++</li>
<li>When compiling with MingW do not link against the ruby *.lib files. Instead, just link directly against the DLL (msvcrt-ruby18.dll). It&#8217;s faster (links much faster) and works better.</li>
<li>So you need to manually compile your extension or create a makefile to do it. This actually turns out be the way GEOS and GDAL work &#8211; they have autoconf based build systems so extconf.rb wouldn&#8217;t fit in anyway.</li>
<li>The advantage of MingW is that it avoids the unmanaged assemblies that VC++8 uses, so its simpler to deal with[…]</li>
<li>VC++ has several large advantages on Windows.
<ul>
<li>First, it lets you debug your extensions while GDB does not support this on Windows (or if it does, its never worked for me).</li>
<li>Second, it compiles much faster</li>
<li>Third, there is a lot more help available.</li>
<li>[Fourth], its quite easy to build Ruby extensions.</li>
</ul>
</li>
<li>Using MingW on Windows is a huge barrier to entry. Gettting MingW setup, along with msys, is a time consuming process that only experienced *Nix developers will understand and be able to do.</li>
<li>MingW on Windows is not very easy to use. It&#8217;s nice to think that you can download an open source project, type ./configure, make, make install and it will work. Alas, it doesn&#8217;t really work that way. There are myriad of issues you run into. First you&#8217;ll need msys. Then many projects have prequisites that you&#8217;ll have to download and compile. In addition, you often times have to change the CFLAGS and LDFLAGS to get successful compiles. Linking is a pain and requires hand-holding, and sometime just doesn&#8217;t work. Libtool is really flakey on Windows. For some projects, you&#8217;ll have to need to download/build/install the latest version of it. You also need to get autoconf/automake installed. Many projects require bison &#8211; something I&#8217;ve never been able to successfully compile on Windows. All in all &#8211; it literally took me weeks to figure out how to get everything to work together. The MingW/msys tool chain is quite complex on Windows, and most people won&#8217;t have the time or desire to put forth the effort to get it to work.</li>
</ul>
<p>My recommendation:</p>
<ul>
<li>Use VC++ 2005 and get Microsoft to tell us how to properly use unmanaged assemblies so that we can avoid dll hell</li>
<li>Make sure that mkrf supports building Ruby extensions &#8220;out-of-the-box&#8221; on Windows using MingW if you have it installed. I think this would be the best of both worlds &#8211; you support both tool chains. VC++ is the default one, but MingW should work fine for building extensions.</li>
</ul>
<p>Hope this helps &#8211; I&#8217;d be glad to share more of my experiences if its helpful.</p>
</blockquote>
<p>So, what can we do to move Ruby toward a highly usable environment that is based on modern Microsoft compiler technology yet remains backwards compatibility with the tools that for many reasons we cannot give up?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/09/21/ruby-on-windows-a-note-for-microsoft/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Brief Note</title>
		<link>http://www.halostatue.ca/2006/09/21/a-brief-note/</link>
		<comments>http://www.halostatue.ca/2006/09/21/a-brief-note/#comments</comments>
		<pubDate>Thu, 21 Sep 2006 20:44:06 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/09/21/a-brief-note/</guid>
		<description><![CDATA[Some folks complained that they were unable to comment on my blog yesterday. I have purposely disabled anonymous comments at all times on my blog. This means that I will get fewer comments, perhaps, but I don&#8217;t even want to start fighting comment spam if at all possible. As such, I am requiring user registration [...]]]></description>
			<content:encoded><![CDATA[<p>Some folks complained that they were unable to comment on my blog yesterday. I have <em>purposely</em> disabled anonymous comments at all times on my blog. This means that I will get fewer comments, perhaps, but I don&#8217;t even want to start fighting comment spam if at all possible. As such, I am requiring user registration at least until I can figure out how to integrate OpenID or some other federated identifier with my blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/09/21/a-brief-note/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ola Bini&#8217;s Ducktator and Controversial Topics</title>
		<link>http://www.halostatue.ca/2006/09/21/ola-binis-ducktator-and-controversial-topics/</link>
		<comments>http://www.halostatue.ca/2006/09/21/ola-binis-ducktator-and-controversial-topics/#comments</comments>
		<pubDate>Thu, 21 Sep 2006 20:35:35 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/09/20/duck-typing-getting-it-name-calling-and-ola-bini/</guid>
		<description><![CDATA[Clearing the air about some posts that happened yesterday, and ultimately agreeing with Ola Bini about Ducktator.]]></description>
			<content:encoded><![CDATA[<p><em>UPDATE September 21: Yesterday, I got a little annoyed at Ola Bini and something he said. He was surprised by the reaction he got to his use of a term which is very common in Ruby parlance, but has overloaded meanings. At some point in the mailing-list discussion, he stepped away and made what some (myself included) felt was a sideswiping response at the participants of the on-list discussion. We have resolved the conflict and clarified our positions toward each other, and rather than pretending that the whole episode didn&#8217;t happen, he and I have agreed to edit our respective blog posts so that they are far more explanatory and less inflammatory overall. Ola certainly didn&#8217;t mean any harm by his post, and I believe him. As such, the title of this post has changed. I&#8217;m sure that for a while at least, you&#8217;ll be able to find the originals in the Google Cache, or maybe the Wayback machine, but understand this: what is below and on Ola&#8217;s updated post reflects how things <strong>are</strong>.</em></p>
<p>After releasing <a href="http://rubyforge.org/projects/ducktator">Ducktator</a>, Ola Bini was surprised at the responses that were received toward his use of the term &#8220;duck typing.&#8221; The discussion went on for a while, and Ola eventually decided to make a post to his blog <a href="http://ola-bini.blogspot.com/2006/09/dynamic-ruby-power-and-static-balance.html">about it</a>. I think that the library is cutely named (as others on the ruby-talk mailing list, I like puns) and several people have suggested that it&#8217;s going to be very useful for them. However, I don&#8217;t think that Ducktator is about duck typing, and its name is unfortunate in that sense, because it has the chance of confusing the discussion surrounding duck typing even further.</p>
<h3 id="toc-what-is-duck-typing">What <em>is</em> Duck Typing?</h3>
</p>
<p>The simplistic answer to this, of course is, &#8220;if it walks like a duck, and<br />
it quacks like a duck, then it must be a duck.&#8221; This is certainly true, but the<br />
real question is more &#8220;how do I know if I&#8217;m duck typing?&#8221; Many people, myself<br />
included, consider duck typing a matter of trusting one&#8217;s callers and<br />
documenting your API well enough to ensure that the callers can trust that you<br />
won&#8217;t do something they&#8217;re not expecting. The canonical example of this is a<br />
logger.</p>
<pre><code>class SimpleLogger
  def initialize(recipient = nil)
	@out = recipient || $stderr
  end

  def log(message)
	@out &amp;lt;&amp;lt; "#{message}\n"
  end

  attr_reader :out
end

l = SimpleLogger.new([])
l.log "Hello"</code></pre>
<p>SimpleLogger simply trusts its users to give it recipient classes that respond to <code>#&amp;lt;&amp;lt;</code>. Now, this is a simple case, but what about something a little more complex? Well, Text::Format can accept a hyphenator object, which must implement a particular method that has a particular arity. So when you assign a hyphenator object, Text::Format does object signature validation for both the presence of the <code>#hyphenate</code> method and its arity (two, I believe). I consider Text::Format&#8217;s approach <em>less</em> duck-typed (possibly even <em>not</em> duck-typed, although it is more dynamic than class-based validation) than I consider the SimpleLogger class above. Both are useful techniques, but to Text::Format is <em>less flexible</em> than SimpleLogger.</p>
<p>That&#8217;s OK, though. The increased complexity of the API for hyphenation suggests that validation is not a bad thing. When you get into the realms of problems that Ola wrote Ducktator for, you need even more complex &#8212; and arguably less flexible &#8212; validation. As I said yesterday:</p>
<blockquote><p>As Eric Mahurin noted in a spin-off post from the main thread about Ducktator, there&#8217;s a number of possible definitions for duck typing, so it&#8217;s understandable that people find themselves confused. I&#8217;m not Dave Thomas (he and Andy applied the term first to Ruby, as far as I can tell), but as far as I&#8217;m concerned, object signature validation is not duck typing. It never has been, and it never will be. It&#8217;s object signature validation.</p>
<p>I don&#8217;t care whether you do object signature validation by the class of the object (in which case you&#8217;d usually be unnecessarily restricting yourself in Ruby) or by the actual method or methods you need, you&#8217;re still not doing duck typing.</p>
</blockquote>
<p>I still believe this to be true. By all means, <em>use</em> Ducktator if it&#8217;s going to help you. It isn&#8217;t what I consider to be duck-typing, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/09/21/ola-binis-ducktator-and-controversial-topics/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>More on Ruby Performance</title>
		<link>http://www.halostatue.ca/2006/09/02/more-on-ruby-performance/</link>
		<comments>http://www.halostatue.ca/2006/09/02/more-on-ruby-performance/#comments</comments>
		<pubDate>Sat, 02 Sep 2006 11:35:16 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/09/02/more-on-ruby-performance/</guid>
		<description><![CDATA[After yesterday's post (Joel on Ruby), Vidar of edgeio (a classified advertising site) posted to ruby-talk his experience with using Ruby in a high-performance environment.]]></description>
			<content:encoded><![CDATA[<p>After <a href="2006/09/01/joel-on-ruby/" title="yesterday's post">yesterday's post</a>, Vidar of <a href="http://www.edgio.com/" title="edgeio">edgeio</a> (a classified advertising site) <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/212285" title="posted to ruby-talk">posted to ruby-talk</a> his experience with using Ruby in a high-performance environment. He previously had a simple messaging middleware that he had written in C++ and replaced it with a 700-line Ruby middleware that had more features that took less time to write. (Granted, some of the less time to write is because the second time you implement something, you know what you&#8217;re doing and know what shortcuts you can take.) The interesting bits from his article, though, suggest he&#8217;s done some serious profiling:</p>
<blockquote><p>We hardly ever max out [CPUs]. … The messaging middleware app handles millions of messages per day and rarely takes up 10% of a single CPU on the servers it runs on.</p>
<p>Most of the CPU time used by our Ruby apps is spend waiting for IO. … about 80% of the time [for the middleware] is spent <em>in the kernel</em> in <code>read()</code> or <code>write()</code> syscalls.…</p>
</blockquote>
<p>Ruby doesn&#8217;t have to be the absolute fastest at everything. Until you&#8217;ve tried it or not, though, you won&#8217;t even know if it&#8217;s fast enough for your problem. It might be—or it might not be. I&#8217;ve got some code that I&#8217;ve been hacking at work for our build process. I should have just made the programs (a collection of shell scripts) involved with Ruby. It would have taken me less time, left me something more manageable overall, and be more capable in the future. The downside? I would have had to make sure that Ruby is installed on all of my machines, which isn&#8217;t necessarily easy (I have some AIX boxes in the mix). Unfortunately, by time I really reached that conclusion, I had already spent enough time to make it non-economical to switch for at least another year (the programs don&#8217;t need to be maintained <em>that</em> often). I guarantee you, though, that the Ruby code would have performed just fine and it would have been easier for people to add features to than the shell scripts that I have.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/09/02/more-on-ruby-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joel on Ruby</title>
		<link>http://www.halostatue.ca/2006/09/01/joel-on-ruby/</link>
		<comments>http://www.halostatue.ca/2006/09/01/joel-on-ruby/#comments</comments>
		<pubDate>Fri, 01 Sep 2006 17:26:55 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/09/01/joel-on-ruby/</guid>
		<description><![CDATA[Joel Spolsky wrote a little piece today on web programming. In the main, I think he's right. But he makes some statements about Ruby that are dead wrong.]]></description>
			<content:encoded><![CDATA[<p>Joel Spolsky <a href="http://www.joelonsoftware.com/items/2006/09/01.html" title="wrote a little piece today">wrote a little piece today</a> on web programming. In the main, I think he&#8217;s right. But he makes some statements about Ruby that are dead wrong. He says:</p>
<blockquote><p>I for one am scared of Ruby because (1) it displays a stunning antipathy towards Unicode and (2) it&#8217;s known to be slow, so if you become The Next MySpace, you&#8217;ll be buying 5 times as many boxes as the .NET guy down the hall.</p></blockquote>
<p>They&#8217;re wrong enough that the creator of the Ruby, Matz, has said something about it on the ruby-talk mailing list:</p>
<blockquote><p>[W]e disagree in the middle.[…]</p>
<p>(1) Although we took different path to handle m17n issue from other Unicode centric languages, we don&#8217;t have any &#8220;stunning antipathy&#8221;.</p>
<p>(2) Although Ruby runs slower than other languages in those micro-benchmarks, real bottleneck in the most application lies in either network connection or databases. So we don&#8217;t have to buy 5 times as many boxes.</p>
</blockquote>
<p>What can be said about Ruby and Unicode right now is that it shows <em>apathy</em> toward Unicode. It neither helps you nor hinders you; it leaves you in about the same place as if you were programming C or C++ without using ICU or something similar. The future is something different. I&#8217;ve done enough Unicode and m17n work to know that while Unicode is a great choice for new data, it doesn&#8217;t help you much with your legacy data&mdash;and all the languages which have chosen to be Unicode to the core have <strong>trouble</strong> with legacy-encoded data to some degree. Ruby&#8217;s m17n support is being planned to be legacy-encoding aware. That way, <em>whatever</em> encoding you have to deal with, it should properly be handled in Strings.</p>
<p>Further, Ruby may be &#8220;Known To Be Slow&#8221;, but what people Know is bunk. There&#8217;s long discussions about this on ruby-talk. There&#8217;s clear examples where changing one&#8217;s algorithm results in a dramatic performance improvement&mdash;to the point where people don&#8217;t care that the program is written in Ruby. Can Ruby&#8217;s performance improve? You bet it can. But anyone who tries to tell you that Ruby is Known To Be Slow is simply repeating outdated and inaccurate information and is not speaking from actual experience. Whether Ruby is too slow depends on what you are trying to do.</p>
<p>That said, I don&#8217;t use Ruby exclusively. I&#8217;m not paid to. Even if I were able to use it as an option, I <strong>know</strong> that Ruby is too slow for the specific domain problems that I have to solve at work. But for other problems (including some picture sorting that I&#8217;ve had to do at home and have written an article about), Ruby is as fast or faster than other tools.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/09/01/joel-on-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ARIEL: A Mentor&#8217;s Mini-Review</title>
		<link>http://www.halostatue.ca/2006/08/24/ariel-a-mentors-mini-review/</link>
		<comments>http://www.halostatue.ca/2006/08/24/ariel-a-mentors-mini-review/#comments</comments>
		<pubDate>Fri, 25 Aug 2006 03:59:19 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/08/24/ariel-a-mentors-mini-review/</guid>
		<description><![CDATA[As some of you may or may not know (all three readers of my blog, I&#8217;m sure), I was the mentor of Alex Bradbury&#8217;s ARIEL project, which was submitted as &#8220;Automated Wrapper Generation for Information Extraction&#8221; and was dubbed ARIEL (A Ruby Information Extraction Library) after some discussion.
Alex was great. The program was great. The [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you may or may not know (all three readers of my blog, I&#8217;m sure), I was the mentor of Alex Bradbury&#8217;s ARIEL project, which was submitted as &#8220;Automated Wrapper Generation for Information Extraction&#8221; and was dubbed ARIEL (A Ruby Information Extraction Library) after some discussion.</p>
<p>Alex was great. The program was great. The result he&#8217;s produced is great—and I&#8217;m not the only one that thinks so. Justin Baily said:</p>
<blockquote><p>Very impressive library! I remember when you posted about this at the beginning of the summer. I took the library and pointed it at the USCCBs online version of the Bible and got some very impressive results! It was able to identify book, chapter and verse with only[…]3 sample pages[…] [ruby-talk:210002]</p></blockquote>
<p>My biggest regret is that I have been so <b>insanely busy</b> that I don&#8217;t think that I&#8217;ve been able to give Alex the amount of time he deserved as a mentor. I only hope that the bits I was able to give him truly helped and didn&#8217;t just come across as koans because I was too busy to do much more than I did.</p>
<p>But Alex created something useful, and something that I believe he will continue to work on—ultimately I hope that he will be able to attract others to help him build on ARIEL. It&#8217;s just a very cool technology that I think will help people make sense of the static web in the transition toward a Semantic Web.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/08/24/ariel-a-mentors-mini-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Three Paragraphs on Duck Typing</title>
		<link>http://www.halostatue.ca/2006/08/22/three-paragraphs-on-duck-typing/</link>
		<comments>http://www.halostatue.ca/2006/08/22/three-paragraphs-on-duck-typing/#comments</comments>
		<pubDate>Wed, 23 Aug 2006 03:46:41 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/08/22/three-paragraphs-on-duck-typing/</guid>
		<description><![CDATA[Not counting my paragraphs, of course. In the course of the thread &#8220;Static typing ain&#8217;t so bad, after all…&#8221; on ruby-talk, David Vallner and Francis Cianfrocca came up with three great paragraphs on duck typing and why it makes so much sense:
David Vallner:
David Vallner: In dynamically typed languages, the type of an object isn&#8217;t its [...]]]></description>
			<content:encoded><![CDATA[<p>Not counting my paragraphs, of course. In the course of the thread &#8220;Static typing ain&#8217;t so bad, after all…&#8221; on ruby-talk, David Vallner and Francis Cianfrocca came up with three great paragraphs on duck typing and why it makes so much sense:</p>
<p><strong>David Vallner:</strong></p>
<blockquote><p>David Vallner: In dynamically typed languages, the type of an object isn&#8217;t its &#8220;class&#8221; or any other predictable concept, it&#8217;s just the protocol it adheres to during its lifetime. Most such languages also make no presumption that this protocol, or the behaviour of an object remains the same during its lifetime &#8211; which makes compile-time checks rather pointless.</p>
<p>Of course, you rarely use even this aspect of dynamic typing &#8211; in fact, I can&#8217;t come up with a single noncontrived example for it, these things just don&#8217;t occur in daily coding. But dynamic languages sure a heck faster to type, and the fact the compiler rarely bitches at all is very, very appealing to people that know what they&#8217;re doing most of the time.</p></blockquote>
<p><strong>Francis Cianfrocca:</strong></p>
<blockquote><p>That was a perceptive comment. The fact that there are so few true cases of objects that metamorphose in flight also accounts for the observed &#8220;magical&#8221; behavior that &#8220;duck-typing&#8221; seems to &#8220;just work&#8221; almost all of the time. (By magical, I mean unexpected for people like me with too many years of experience programming in statically-typed languages.) The intention of a well thought-out code path is generally easy to express without typing all the types along the way. It doesn&#8217;t break often, and when it does break, it doesn&#8217;t make a big mess.</p></blockquote>
<p>This matters because when I write an API, I write it with an interface (protocol, to use David&#8217;s term) in mind. That interface might have the name of a class, say File. But if someone gives me something that <strong>acts</strong> like the portions of File that I use,(and I use sensible alternatives when possible, such as <code>#&amp;lt;&amp;lt;</code> instead of <code>#write</code>, then someone can give me something entirely different and I won&#8217;t care. But I don&#8217;t restrict the consumer of my library to only using File, and I handle it as best as I can because I expect that things will work the way that they should.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/08/22/three-paragraphs-on-duck-typing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Holiday Rubyist Meet Wrapup</title>
		<link>http://www.halostatue.ca/2006/08/07/holiday-rubyist-meet-wrapup/</link>
		<comments>http://www.halostatue.ca/2006/08/07/holiday-rubyist-meet-wrapup/#comments</comments>
		<pubDate>Tue, 08 Aug 2006 01:04:04 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/08/07/holiday-rubyist-meet-wrapup/</guid>
		<description><![CDATA[So while I was in Europe, I gave a talk to the London Ruby Users Group for which I ran out of time (I was just warming up!).]]></description>
			<content:encoded><![CDATA[<p>So while I was in Europe, I gave a <a href="2006/07/10/london-ruby-users-group/" title="talk">talk</a> to the  <a href="http://www.lrug.org" title="London Ruby Users Group">London Ruby Users Group</a> for which I ran out of time (I was just warming up!). Someone, and I knew I should have pulled out a pad and written down his name, was kind enough to buy me a Scotch after my talk when the group went to the pub. Thank you again, kind sir. I met with Hagen in Potsdam, and after some changed schedules that caused me to miss the München.rb meeting, I ended up meeting with Urban Hafner. I had really wanted to meet with Armin Roehrl while in München, but the aforementioned scheduling mishaps and a lack of reliable Internet access prevented that from happening. Maybe next time, because I do want to go back to München. I didn&#8217;t get to see quite enough.</p>
<p>Well, on the afternoon of the 27th of July for my only day in Amsteram, I checked my email and I had an email from the indomitable <a href="http://www.erikveen.dds.nl/" title="Erik Veenstra">Erik Veenstra</a> of <a href="http://www.erikveen.dds.nl/rubyscript2exe/index.html" title="RubyScript2Exe">RubyScript2Exe</a> fame. The scheduling was a bit tight, but we ate at what I consider the best pannekoeken (a Dutch pancake that is the size of a small pizza and often topped similarly) restaurant in all of Amsterdam, the <a href="http://www.pancake.nl/" title="Pancake House">Pancake House</a>. Like the other European Rubyists we met, Erik is a pleasant person with a great sense of humour and well-informed.  My fiancée was charmed by all of them that she met (Hagen, Urban, and Erik) and we had a lot of fun. Anne-Marie and I were supposed to meet her sister at 9:30, but it was closer to 9:45 when we managed it because we were enjoying our discussion with Erik so much. Thanks for emailing, Erik. It was a lovely evening. Sorry it&#8217;s taken so long to write about it.</p>
<p>And a general thank-you to the European Rubyists that I met. I really enjoyed meeting you guys and hearing how you use Ruby. For those whom I didn&#8217;t meet, I plan on going back to Europe in a couple of years (I want to do a North American trip for holidays next year) and I hope to meet you then. Otherwise, I hope to see you at this October&#8217;s RubyConf.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/08/07/holiday-rubyist-meet-wrapup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deutsches Rubyists</title>
		<link>http://www.halostatue.ca/2006/07/21/deutsches-rubyists/</link>
		<comments>http://www.halostatue.ca/2006/07/21/deutsches-rubyists/#comments</comments>
		<pubDate>Fri, 21 Jul 2006 09:59:13 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/07/21/deutsches-rubyists/</guid>
		<description><![CDATA[In the last ten days, I have met two charming German Rubyists: Hagen (whose surname I never learned) and Urban Hafner. I missed meeting Armin Roehrl because my travel schedule caused me to miss the München.rb meeting on the 15th and we were never able to connect otherwise (sorry, Armin; I really did want to [...]]]></description>
			<content:encoded><![CDATA[<p>In the last ten days, I have met two charming German Rubyists: Hagen (whose surname I never learned) and Urban Hafner. I missed meeting Armin Roehrl because my travel schedule caused me to miss the München.rb meeting on the 15th and we were never able to connect otherwise (sorry, Armin; I really did want to meet you).</p>
<p>Hagen has been using Ruby in his degree program and his practicum study for the transformation of business model descriptions to web sites, etc. He lives in Potsdam, just outside of Berlin, and we met him on the evening of Thursday the 13th after we picked up our rental car (an Opel Zafira). He showed us around the Sans Souci palace park built by the Austro-Hungarian emperor Frederick II. Absolutely beautiful and a worthy trip. He was very knowledgeable of his town and obviously likes it a lot. We made it back to the car just before the rain came down on us (after what had been a very hot—35 °C—and humid day in the Berlin area) and stepped into a nice Italian restaurant just as the deluge began. After a wonderful dinner, we drove Hagen back to his apartment and went on our way to Dresden and ultimately family in Lohr am Main.</p>
<p>We went to München on Monday, the 17th, and met up with Urban on the evening of the 18th. Urban saved my iPod from being useless on this trip by bringing his charger. (It had fully discharged and would only charge through my laptop; the USB-based charger that I had brought did not provide enough power for the iPod.) We met Urban near the fish fountain on Marienplatz where he was wearing his Munich.rb t-shirt and went to a nice Bayernisch restaurant east of Marienplatz. During dinner we learned that Urban used Ruby to process his raw data for his bio-informatics degree (equivalent to a master&#8217;s), although he was not asked that in his thesis defence.</p>
<p>My traveling companions are just computer users (not programmers at all!) and have pleasantly been pleasantly surprised by how nice, friendly, and well-rounded the Rubyists they have met have been.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/07/21/deutsches-rubyists/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>London Ruby Users Group</title>
		<link>http://www.halostatue.ca/2006/07/10/london-ruby-users-group/</link>
		<comments>http://www.halostatue.ca/2006/07/10/london-ruby-users-group/#comments</comments>
		<pubDate>Tue, 11 Jul 2006 00:16:41 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/07/10/london-ruby-users-group/</guid>
		<description><![CDATA[I spoke on a number of things tonight at the London Ruby Users Group…]]></description>
			<content:encoded><![CDATA[<p>I <a href="/wordpress/wp-content/uploads/2006/07/lrug-presentation.ppt" title="spoke">spoke</a> on a number of things tonight at the <a href="http://www.lrug.org/" title="London Ruby Users Group">London Ruby Users Group</a>, ranging from the Google Summer of Code, to the <a href="http://www.trug.ca/" title="Toronto Ruby Users Group">Toronto Ruby Users Group</a> <a href="http://www.trug.ca/TRUGhat" title="hackathon">hackathon</a>, to <a href="http://ruby-pdf.rubyforge.org" title="PDF::Writer">PDF::Writer</a>. It was a much larger crowd than I expected (about 25 people!).<a href="http://www.halostatue.ca/wordpress/wp-content/uploads/2006/07/lrug_attendees.jpg" rel="lightbox"  ><img src="http://www.halostatue.ca/wordpress/wp-content/uploads/2006/07/.thumbs/.lrug_attendees.jpg" alt="LRUG Attendees" title="LRUG Attendees" width="96" height="72" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/07/10/london-ruby-users-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beware First Impressions</title>
		<link>http://www.halostatue.ca/2006/07/01/beware-first-impressions/</link>
		<comments>http://www.halostatue.ca/2006/07/01/beware-first-impressions/#comments</comments>
		<pubDate>Sat, 01 Jul 2006 20:15:22 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/07/01//</guid>
		<description><![CDATA[Adam Connor doesn’t like a few things about Ruby. He’s certainly correct that there are warts in the Ruby language, but much of what he’s described aren’t warts.
There’s more than one way to do it. If you like baroque languages like Perl, maybe this is a feature. Ruby has 3 ways of constructing regexps, innumerable [...]]]></description>
			<content:encoded><![CDATA[<p>Adam Connor <a href="http://adamconnor.org/?p=63">doesn’t like</a> a few things about Ruby. He’s certainly correct that there are warts in the Ruby language, but much of what he’s described aren’t warts.</p>
<blockquote><p>There’s more than one way to do it. If you like baroque languages like Perl, maybe this is a feature. Ruby has 3 ways of constructing regexps, innumerable ways of producing strings, if and unless and… well. You get the idea. Reading Ruby is an exciting adventure in learning new ways to do the same old thing! Don’t like the old method name? Alias it! After all, languages should enable free expression in whatever manner best suits the developer’s personal style. “`Twas brillig, and the slithy toves…” and all that. Moderation is a virtue.</p></blockquote>
<p>This is a conflation of several issues. Let’s tackle them independently.</p>
<ul>
<li><strong>Multiple constructors for regular expressions</strong>: I am presuming here that Adam is referring to <code>/re/</code>, <code>%r{re}</code>, and <code>Regexp.new("re")</code>. Each one of these makes sense, but you only see two of them commonly present in most Ruby code. Most often, you’ll see the <code>/re/</code> format, like <code>/[ab].[d-f]/</code>. This works well until you need to match on a slash character, like <code>/\d{4}\/\d{2}\/\d{2}/</code>. The extended format is much more readable in this case: <code>%r{\d{4}/\d{2}/\d{2}}</code>. Note that Ruby doesn’t have problems with the braces because they match here. Ruby is smart that way. The third form exists because regular expressions &#8212; like everything else &#8212; are objects. One could construct a regular expression from a string you get externally in this case, like <code>str = "[ab].[d-f]"; Regexp.new(str)</code>.</li>
<li><strong>Multiple constructors for strings</strong>: Like regular expressions, there are good reasons for this, mostly related to quote escaping. With Ruby’s string interpolation (<code>"foo#{bar}"</code>) it becomes useful to have a form of the string that does not interpolate: <code>'foo#{bar}'</code>. (It is a minor quibble that there is no clean way to later take that string and interpolate it without calling Kernel#eval.) This means that it is useful to have string forms that make it easy to have quotes: <code>%Q{"foo#{bar}"}</code> and <code>%q{'foo#{bar}'}</code>. Finally, there is the HEREDOC format, which allows multiline strings without having to have line continuations or C++’s autojoin functionality (which wouldn’t work in Ruby because each line is an expression to be evaluated).</li>
<li><strong>Multiple method names for the same method</strong>: The biggest example of this is Enumerable#map and Enumerable#collect. These two methods do the same thing, but they are named such because Lisp-oriented developers understand #map implicitly; Smalltalk-oriented developers understand #collect. When I started with Ruby, I started with #collect; now I use #map. Other examples include Array#indexes and Array#indices. Grammatically speaking, #indices is correct, but #indexes is common, too. (The same applies to if/unless, although I only use unless as a modifier with a single test, most of the time.)</li>
</ul>
<blockquote><p>Perl-style two-character variables. Because dollar-sign-squiggle is such a mnemonic and meaningful name, and distinguishing $` from $’ is just a snap.</p></blockquote>
<p>These are not used often; it is more common to see <code>$LOAD_PATH</code> instead of <code>$:</code> these days.</p>
<blockquote><p>Other esoterica. The flip-flop operator [...]</p></blockquote>
<p>This has been deprecated and I’ve never used it in any of my code.</p>
<blockquote><p>Whitespace is significant. Didn’t this go out with JCL and punch cards? I guess Python has made it fashionable again. Anyhow, I can’t tell you how thrilled I am that<br />
  <code>1 + 2 +&lt;br /&gt;
	3</code><br />
evaluates one way and<br />
<code>1 + 2&lt;br /&gt;
  + 3</code><br />
evaluates another way.</p></blockquote>
<p>The problem here is not Ruby. Ruby evaluates each line as an expression. This doesn&#8217;t mean that whitespace is significant in Ruby (it isn&#8217;t), but that the two examples given are two different expressions. What is a bug, and Matz has said will be fixed is a subtly different problem, is:</p>
<pre>(1 + 2
 + 3)</pre>
<p>The parentheses should be sufficient indicator of an expression.</p>
<blockquote><p>Constants aren’t. You can assign to a constant multiple times. At least it will generate a warning.<br />
Variable/Method Ambiguity. That’s what the pickaxe book calls it, anyway… Ruby guesses whether a name is a variable or a function based on whether it has seen an assignment to that symbol before the point of call. I guess I’m naive; I thought that was so amazingly lame that I was surprised it wasn’t classified as a bug.</p></blockquote>
<p>Both of these are fully understandable and well-explained elsewhere. The latter is a consequence of what is often called “poetry mode” where parentheses aren’t required for method calls. Ruby <em>does</em> resolve this very well.</p>
<blockquote><p>The method to_i doesn’t return errors.</p></blockquote>
<p>Use Kernel#Integer if you need this. Most of the time, I don’t.</p>
<blockquote><p>Handling namespaces and mixins with modules. Since these concepts have no particular overlap, this just feels very kludgey to me. Apparently the Ruby community is OK with it, though.</p></blockquote>
<p>Actually, it&#8217;s not just modules. It&#8217;s classes. I can do <em>either</em>:</p>
<pre>class A; end
class A::B; end
module C; end
class C::D; end</pre>
<p>This, to me, is a lot more sane than yet another syntactical setup with no structure (<strong>package</strong>) or the way that C++ uses namespace.</p>
<p>Ultimately, I think that Ruby is what Lisp <em>would</em> be if it were a procedurally-oriented language. Nothing else certainly comes close.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/07/01/beware-first-impressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rubyists in London, Germany, Amsterdam?</title>
		<link>http://www.halostatue.ca/2006/06/23/rubyists-in-london-germany-amsterdam/</link>
		<comments>http://www.halostatue.ca/2006/06/23/rubyists-in-london-germany-amsterdam/#comments</comments>
		<pubDate>Fri, 23 Jun 2006 17:37:41 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/06/23//</guid>
		<description><![CDATA[I am going to be in Europe on vacation from July 8th and would love to have the opportunity to meet Rubyists from the London area, various places in Germany, and maybe around Amsterdam as well. I won’t be travelling alone and I am on vacation, so my time will be limited.
I will be landing [...]]]></description>
			<content:encoded><![CDATA[<p>I am going to be in Europe on vacation from July 8<sup>th</sup> and would love to have the opportunity to meet Rubyists from the London area, various places in Germany, and maybe around Amsterdam as well. I won’t be travelling alone and I am on vacation, so my time will be limited.</p>
<p>I will be landing in London mid-morning on July 8<sup>th</sup> and will be leaving for Berlin on July 11<sup>th</sup>. I will be attending the The Who concert on the night of the 12<sup>th</sup>, and picking up a car on the morning of the 13<sup>th</sup>. I may be able to meet with people in Berlin on the evening of the 11<sup>th</sup> or early afternoon on the 12<sup>th</sup> depending on my schedule. We’re probably headed to Lohr am Main (near Frankfurt) immediately, and will definitely be travelling to Munich, but will be in a lot of different places. We will be heading toward the northern Netherlands on the 24<sup>th</sup> or so and be in Amsterdam on the 27<sup>th</sup>.</p>
<p>I will probably have time to meet with London Rubyists on either the 9<sup>th</sup> or the 10<sup>th</sup>. My German and Dutch plans are much more flexible (of necessity), but can probably carve out some time either way. If you&#8217;re interested in meeting with me, please email me (<strong>austin</strong> at <strong>halostatue</strong> dot <strong>ca</strong>) and we’ll see what we can get worked out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/06/23/rubyists-in-london-germany-amsterdam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#trug on irc.freenode.net</title>
		<link>http://www.halostatue.ca/2006/06/09/trug-on-ircfreenodenet/</link>
		<comments>http://www.halostatue.ca/2006/06/09/trug-on-ircfreenodenet/#comments</comments>
		<pubDate>Fri, 09 Jun 2006 15:35:23 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[TRUG]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/06/09/trug-on-ircfreenodenet/</guid>
		<description><![CDATA[The Toronto Ruby Users Group has an IRC channel on Freenode.]]></description>
			<content:encoded><![CDATA[<p>Thanks to Bill Traynor (wmat), <a href="http://www.trug.ca/" title="TRUG">TRUG</a> now has a registered channel on <a href="http://freenode.net" title="irc.freenode.net">irc.freenode.net</a>. Hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/06/09/trug-on-ircfreenodenet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TRUGhat 2006:1 Recap</title>
		<link>http://www.halostatue.ca/2006/05/21/trughat-20061-recap/</link>
		<comments>http://www.halostatue.ca/2006/05/21/trughat-20061-recap/#comments</comments>
		<pubDate>Sun, 21 May 2006 21:50:21 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Toronto]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/05/21/trughat-20061-recap/</guid>
		<description><![CDATA[I&#8217;ve been very remiss in updating things lately, a promised update on what happened with TRUGhat 2006:1. Sy Ali put together a brief <a href="http://www.trug.ca/TRUGhat/May_2006" title="summary">summary</a> of the event right after it happened. We had a good turnout to this event, with twelve of us present. Unfortunately, I&#8217;ve been so busy with work over the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been very remiss in updating things lately, a promised update on what happened with TRUGhat 2006:1. Sy Ali put together a brief <a href="http://www.trug.ca/TRUGhat/May_2006" title="summary">summary</a> of the event right after it happened. We had a good turnout to this event, with twelve of us present. Unfortunately, I&#8217;ve been so busy with work over the last several months that I did <em>not</em> have time to prepare to the degree that I should have for what we wanted to do.</p>
<p>Everyone enjoyed themselves, and the project was interesting, but we didn&#8217;t get nearly as much done as I wanted to. The original goal was to fully reimplement libarchive in pure Ruby: we did not achieve that. In no way, though, would I call the hackahon a failure except on that measure. Most everyone who attended learned more about Ruby and about how tar files are constructed. There was high interested in continuing the work from a number of attendees, some of whom have continued to contribute to the SVN depot.<br />
I know a bit better what needs to be done to run a hackathon, and will be ready for the next event which has been suggested for August. I&#8217;m looking forward to it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/05/21/trughat-20061-recap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>This Saturday: TRUGhat 2006:1</title>
		<link>http://www.halostatue.ca/2006/05/03/this-saturday-trughat-20061/</link>
		<comments>http://www.halostatue.ca/2006/05/03/this-saturday-trughat-20061/#comments</comments>
		<pubDate>Wed, 03 May 2006 14:46:51 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[TRUG]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/05/03/this-saturday-trughat-20061/</guid>
		<description><![CDATA[Reminder: TRUGhat iswas Saturday, 6 May 2006!
The Toronto Ruby User Group&#8217;s first <a href="http://en.wikipedia.org/wiki/Hackathon" title="hackathon">hackathon</a> is this Saturday, 6 May 2006. If you are attending, please add your name to the <a href="http://www.trug.ca/TRUGhat" title="TRUGhat wiki page">TRUGhat wiki page</a>.
When and Where?
TRUGhat 2006:1 will be held on 6 May 2006, from 10:00 A.M. to 7:00 P.M. Tucows has generously [...]]]></description>
			<content:encoded><![CDATA[<h2 id="toc-reminder-trughat-iswas-saturday-6-may-2006"><strike>Reminder:</strike> <i>TRUGhat</i> <strike>is</strike>was Saturday, 6 May 2006!</h2>
<p>The Toronto Ruby User Group&#8217;s first <a href="http://en.wikipedia.org/wiki/Hackathon" title="hackathon">hackathon</a> is this Saturday, 6 May 2006. If you are attending, please add your name to the <a href="http://www.trug.ca/TRUGhat" title="TRUGhat wiki page">TRUGhat wiki page</a>.</p>
<h3 id="toc-when-and-where">When and Where?</h3>
<p><strong>TRUGhat 2006:1</strong> will be held on 6 May 2006, from 10:00 A.M. to 7:00 P.M. Tucows has generously provided the space and network availability for this event at its offices in Toronto, at <a href="http://maps.google.com/maps?f=q&#038;hl=en&#038;q=96+Mowat+Avenue,+Toronto+(Tucows+Office)&#038;ll=43.638995,-79.426088&#038;spn=0.022983,0.057549&#038;om=1" title="96 Mowat Avenue">96 Mowat Avenue</a>, one block <strike>west</strike>east of Dufferin, south of King. Transit accessibility is good, with both the King West streetcar and the Dufferin bus passing near the office. Parking is plentiful for those who will be driving.</p>
<h3 id="toc-what-do-i-need-to-bring">What Do I Need to Bring?</h3>
<ul>
<li>Yourself.</li>
<li>It would be good if you brought your own computer, although we will probably be practising pair programming.</li>
<li>Anything you want to drink during the course of the day.</li>
</ul>
<p>We will be providing wireless access, and the Tucows office has wireline access.</p>
<p>Pizza lunch will be provided from a nearby Pizza Pizza, courtesy of yours truly.</p>
<h3 id="toc-what-else">What else?</h3>
<ul>
<li>Make sure you have Ruby installed. We will generally be working with Ruby 1.8.4.</li>
<li>Have Subversion command-line or graphical tools installed. For people with Windows, I recommend <a href="http://tortoisesvn.tigris.org/" title="TortoiseSVN">TortoiseSVN</a>.</li>
<li>Create an account on RubyForge. You will be added as a committer to the project we will be using to manage this release.</li>
<li>If you have any Ruby documentation, such as either the first or second-edition Pickaxe books, this will be very useful.</li>
</ul>
<h3 id="toc-see-you-there">See you there!</h3>
<p>If you are worried that you might get lost, please email me at <strong>halostatue</strong>(at)<strong>gmail.com</strong> and I will provide you with my cellphone number to contact me on the day of the hackathon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/05/03/this-saturday-trughat-20061/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Net::LDAP</title>
		<link>http://www.halostatue.ca/2006/05/02/ruby-netldap/</link>
		<comments>http://www.halostatue.ca/2006/05/02/ruby-netldap/#comments</comments>
		<pubDate>Tue, 02 May 2006 21:32:20 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/05/02/ruby-netldap/</guid>
		<description><![CDATA[I did something different recently. Back in December 2003, when I had more time than I knew what to do with, I registered the <a href="http://rubyforge.org/net-ldap" title="net-ldap">net-ldap</a> project on <a href="http://rubyforge.org/" title="RubyForge">RubyForge</a>. I thought I had a need for LDAP, but as I delved into it, I found that I had needs more interesting and [...]]]></description>
			<content:encoded><![CDATA[<p>I did something different recently. Back in December 2003, when I had more time than I knew what to do with, I registered the <a href="http://rubyforge.org/net-ldap" title="net-ldap">net-ldap</a> project on <a href="http://rubyforge.org/" title="RubyForge">RubyForge</a>. I thought I had a need for LDAP, but as I delved into it, I found that I had needs more interesting and more pressing. LDAP is ugly. I&#8217;m not sure I <em>want</em> to understand LDAP.</p>
<p>So, a month ago, I put a call out for a developer for the Net::LDAP project. I had a couple of bites, but Francis Cianfrocca had the experience and drive that I was looking for as someone to ultimately hand the project to for development. Francis has exceeded my wildest dreams. He is a firm believer in the idea that API matters, and that a pure-Ruby implementation is of prime importance here.</p>
<p>He&#8217;s going as far as to suggest a pure-Ruby server implementation like WEBrick for LDAP details. More than that, he&#8217;s got a C++/Ruby library that he&#8217;s intent on making possible to use if it&#8217;s available on the user&#8217;s system, for performance reasons, but will <strong>still</strong> work well without it. If you use LDAP, or you think you might want to use LDAP, pay attention to this project. Francis is looking at the idea that people don&#8217;t get LDAP and trying to abstract the nastiness away. And that&#8217;s a good thing.</p>
<p>I wholeheartedly endorse the work that he&#8217;s doing now, and while there&#8217;s a long way to go, this is a project to watch.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/05/02/ruby-netldap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TRUGhat 2006:1</title>
		<link>http://www.halostatue.ca/2006/04/18/trughat-20061/</link>
		<comments>http://www.halostatue.ca/2006/04/18/trughat-20061/#comments</comments>
		<pubDate>Wed, 19 Apr 2006 03:10:03 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Archive]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[TRUG]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/04/18/trughat-20061/</guid>
		<description><![CDATA[TRUGhat: Toronto Ruby Users Group hackathon
TRUGhat is TRUG&#8217;s <a href="http://en.wikipedia.org/wiki/Hackathon" title="hackathon">hackathon</a> or codefest. In a hackathon, a group of people get together and will either work toward a common goal, or simply work in a common area on code that interests them. For our first TRUGhat, we have agreed upon a common goal.
During a codefest or hackathon, [...]]]></description>
			<content:encoded><![CDATA[<h2 id="toc-trughat-toronto-ruby-users-group-hackathon">TRUGhat: <i>T</i>oronto <i>R</i>uby <i>U</i>sers <i>G</i>roup <i>ha</i>cka<i>t</i>hon</h2>
<p>TRUGhat is TRUG&#8217;s <a href="http://en.wikipedia.org/wiki/Hackathon" title="hackathon">hackathon</a> or codefest. In a hackathon, a group of people get together and will either work toward a common goal, or simply work in a common area on code that interests them. For our first TRUGhat, we have agreed upon a common goal.</p>
<p>During a codefest or hackathon, there&#8217;s <strong>always</strong> lots of snacks available, and it&#8217;s common for the perfect developer&#8217;s food&mdash;pizza, of course&mdash;to be delivered.</p>
<p>The goal is for TRUG to have two TRUGhat events a year. Ruby developers of all skill levels will be welcomed.</p>
<h2 id="toc-trughat-20061">TRUGhat 2006:1</h2>
<h3 id="toc-when">When?</h3>
<p><strong>TRUGhat 2006:1</strong> will be held on 6 May 2006, from 10:00 A.M. to 7:00 P.M.</p>
<p>Since we&#8217;re all learning something on this first <strong>TRUGhat</strong>, we probably won&#8217;t get started programming until 11:00 A.M.</p>
<h3 id="toc-where">Where?</h3>
<p>Tucows has generously provided the space and network availability for this event at its offices in Toronto, at 96 Mowat Avenue, one block west of Dufferin, south of King. Transit accessibility is good, with both the King West streetcar and the Dufferin bus passing near the office. Parking is plentiful for those who will be driving. <a href="http://maps.google.com/maps?f=q&#038;hl=en&#038;q=96+Mowat+Avenue,+Toronto+(Tucows+Office)&#038;ll=43.638995,-79.426088&#038;spn=0.022983,0.057549&#038;om=1"" title="Map">Map</a></p>
<h3 id="toc-who">Who?</h3>
<p>The Tucows space can handle a total of fifteen people, with thirteen places available. If you&#8217;re interested in joining us, please put your name below and join the <strike>mailing list</strike>. <strong>UPDATE: This list is wrong. Visit the <a href="http://trug.ca" title="TRUG wiki">TRUG wiki</a> and use the <em>sewm</em> list to join.</strong></p>
<h2 id="toc-what">What?</h2>
<p>The current plan is to implement the functionality of <a href="http://people.freebsd.org/~kientzle/libarchive/"" title="libarchive">libarchive</a> and possibly <a href="http://www.feep.net/libtar/" title="libtar">libtar</a> for Ruby. The primary goal is pure Ruby support with a secondary goal of Ruby/C bindings so that those who have the requisite libraries can take advantage of the C code for performance reasons.</p>
<h2 id="toc-more">More?</h2>
<p>Some of the details are still being worked out, but Austin Ziegler has already committed to buying pizza for whomever does show up.  Check out the mailing list or the <a href="http://www.trug.ca/TRUGhat"" title="TRUGhat wiki page">TRUGhat wiki page</a> for more information.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/04/18/trughat-20061/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RTidyCD</title>
		<link>http://www.halostatue.ca/2006/01/01/rtidycd/</link>
		<comments>http://www.halostatue.ca/2006/01/01/rtidycd/#comments</comments>
		<pubDate>Sun, 01 Jan 2006 04:00:32 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[HaloStatue]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.halostatue.ca/2006/01/01/rtidycd/</guid>
		<description><![CDATA[RTidy for CityDesk is no longer supported or available at this site. Sorry for any inconvenience this may cause.
]]></description>
			<content:encoded><![CDATA[<p>RTidy for CityDesk is no longer supported or available at this site. Sorry for any inconvenience this may cause.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2006/01/01/rtidycd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eggplant Curry</title>
		<link>http://www.halostatue.ca/2004/10/29/eggplant-curry/</link>
		<comments>http://www.halostatue.ca/2004/10/29/eggplant-curry/#comments</comments>
		<pubDate>Fri, 29 Oct 2004 04:18:31 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2004/10/29/eggplant-curry/</guid>
		<description><![CDATA[Nice, warm, and perfectly spicy without being too hot. The heat can be adjusted to your taste, too.
I make this recipe every couple of weeks it&#8217;s so good. Again, I made it for today&#8217;s pot-luck at work, and have had several requests for the recipe, so here it is.


Eggplant Curry


1 onion
Chop into small pieces.
Saut&#233; on [...]]]></description>
			<content:encoded><![CDATA[<p>Nice, warm, and perfectly spicy without being too hot. The heat can be adjusted to your taste, too.</p>
<p>I make this recipe every couple of weeks it&#8217;s so good. Again, I made it for today&#8217;s pot-luck at work, and have had several requests for the recipe, so here it is.</p>
<table class="recipe">
<tr>
<th colspan="7" style="font-size: 1.25em !important">Eggplant Curry</th>
</tr>
<tr>
<td>1 onion</td>
<td>Chop into small pieces.</td>
<td rowspan="2">Saut&eacute; on low-medium heat until soft, about 5 minutes.</td>
<td rowspan="4" style="border-left: 0pt none !important">Add eggplant and zucchini and saut&eacute; on low-medium heat until soft, about 15 minutes. Stir regularly to prevent sticking.</td>
<td rowspan="5" style="border-left: 0pt none !important">Add to vegetables and cover pot; cook on medium heat another 15 minutes. Stir regularly to prevent sticking.</td>
<td rowspan="6" style="border-left: 0pt none !important">Add to vegetables; cook on medium heat another 3 minutes. Stir regularly to prevent sticking.</td>
<td rowspan="7" style="border-left: 0pt none !important">Stir in with vegetables; cook on medium heat another 5 minutes. Eggplant should disintegrate while stirring.</td>
</tr>
<tr>
<td>1 tbsp olive oil</td>
<td>Heat on low heat.</td>
</tr>
<tr>
<td>1 large eggplant</td>
<td>Slice into &frac12;” slices. Quarter the slices.</td>
<td style="border-right: 0pt none !important; border-bottom: 0pt none !important"></td>
</tr>
<tr>
<td>1 medium zucchini</td>
<td>Slice thinly.</td>
<td style="border-top: 0pt none !important; border-right: 0pt none !important"></td>
</tr>
<tr>
<td>&frac12; cup water</td>
<td colspan="3" style="border-top: 0pt none !important; border-right: 0pt none !important"></td>
</tr>
<tr>
<td>&frac14; cup raisins</td>
<td colspan="4" style="border-top: 0pt none !important; border-right: 0pt none !important"></td>
</tr>
<tr>
<td>2 tbsp medium curry paste</td>
<td colspan="5" style="border-top: 0pt none !important; border-right: 0pt none !important"></td>
</tr>
<tr>
<td colspan="7">Serve by itself, with rice or with naan. Optionally top with sour cream.</td>
</tr>
</table>
<ol>
<li>Heat olive oil and saut&eacute; chopped onion for about 5 minutes on low heat.</li>
<li>Saut&eacute; sliced and quartered eggplant and zucchini on low-medium heat for 15 minutes, until both are soft.</li>
<li>Add water to vegetables and cover the pot. Cook, stirring regularly, for 15 minutes.</li>
<li>Stir raisins and cook for another three minutes.</li>
<li>Add curry paste (Patak&#8217;s is great) and cook five minutes further.</li>
<li>Serve hot by itself, with rice or naan. Optionally top with sour cream.</li>
</ol>
<p>Thanks to <a href="http://www.cookingforengineers.com/">Cooking for Engineers</a> for highly functional the recipe format.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2004/10/29/eggplant-curry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pumpkin Cheesecake</title>
		<link>http://www.halostatue.ca/2004/10/29/pumpkin-cheesecake/</link>
		<comments>http://www.halostatue.ca/2004/10/29/pumpkin-cheesecake/#comments</comments>
		<pubDate>Fri, 29 Oct 2004 04:11:35 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Recipes]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2004/10/29/pumpkin-cheesecake/</guid>
		<description><![CDATA[A perfect Thanksgiving dessert and it&#8217;s far tastier than pumpkin pie&#8212;probably easier, too.I made this for Canadian Thanksgiving (where it was, as always, well-received) and for a pot-luck at work today. I&#8217;ve had several requests for the recipe, so here it is.


Pumpkin Cheesecake


Preheat oven to 350&#176; Fahrenheit


3 tbsp butter
Melt
Mix with ginger snaps and press into [...]]]></description>
			<content:encoded><![CDATA[<p>A perfect Thanksgiving dessert and it&#8217;s far tastier than pumpkin pie&mdash;probably easier, too.I made this for Canadian Thanksgiving (where it was, as always, well-received) and for a pot-luck at work today. I&#8217;ve had several requests for the recipe, so here it is.</p>
<table class="recipe">
<tr>
<th colspan="5" style="font-size: 1.25em ! important">Pumpkin Cheesecake</th>
</tr>
<tr>
<td colspan="5" style="font-weight: bold ! important">Preheat oven to 350&deg; Fahrenheit</td>
</tr>
<tr>
<td>3 tbsp butter</td>
<td>Melt</td>
<td colspan="2" rowspan="2" style="border-left: 0pt none ! important">Mix with ginger snaps and press into the bottom of a 9” springform pan. Bake at 350&deg; F for 10     minutes.</td>
<td rowspan="10">Pour cheesecake mixture into pan. Bake at 350&deg; F for 55     minutes.</td>
</tr>
<tr>
<td>1 cup crushed ginger snaps</td>
<td style="border: 0pt none  ! important"></td>
</tr>
<tr>
<td>2 packages (500g) cream cheese (light is okay)</td>
<td>Soften</td>
<td style="border-bottom: 0pt none ! important"></td>
<td rowspan="8" style="border-left: 0pt none ! important">Beat until smooth.</td>
</tr>
<tr>
<td>1&frac12; tsp vanilla</td>
<td rowspan="5" style="border-right: 0pt none ! important"></td>
<td rowspan="5" style="border-top: 0pt none ! important; border-left: 0pt none ! important">Beat until smooth.</td>
</tr>
<tr>
<td>1 tsp cinnamon</td>
</tr>
<tr>
<td>&frac12; tsp allspice</td>
</tr>
<tr>
<td>&frac14; tsp nutmeg</td>
</tr>
<tr>
<td>1 cup sugar</td>
</tr>
<tr>
<td>1 cup canned pumpkin pie mix or pure pumpkin</td>
<td colspan="2" rowspan="2" style="border-right: 0pt none ! important"></td>
</tr>
<tr>
<td>3 eggs (or 150 mL liquid whole eggs)</td>
</tr>
</table>
<ol>
<li>Preheat the oven to 350&deg; F.</li>
<li>Melt the butter and mix it with the crushed ginger snaps.</li>
<li>Press the ginger snap crust into a 9” springform pan and bake for ten minutes at 350&deg; F.</li>
<li>Soften the cream cheese and beat with the sugar, vanilla, and spices until smooth.</li>
<li>Beat pumpkin and eggs into cream-cheese mixture until smooth.</li>
<li>Pour cheesecake mixture into springform pan and bake for 55 minutes at 350&deg; F, or until a toothpick inserted into the centre comes out smooth.</li>
</ol>
<p>You can reduce the cracking of a cheesecake by putting a pan of water in the oven at the same time. This may be topped with caramelized sugar and pecans, as desired. &frac12; cup pecan pieces can also be mixed into the ginger snap crust.</p>
<p>Thanks to <a href="http://www.cookingforengineers.com/">Cooking for Engineers</a> for highly functional the recipe format.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2004/10/29/pumpkin-cheesecake/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruwiki 0.8.1 Coming Soon, Ruwiki 0.9.0 Soon After</title>
		<link>http://www.halostatue.ca/2004/09/21/ruwiki-081-coming-soon-ruwiki-090-soon-after/</link>
		<comments>http://www.halostatue.ca/2004/09/21/ruwiki-081-coming-soon-ruwiki-090-soon-after/#comments</comments>
		<pubDate>Wed, 22 Sep 2004 03:44:25 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruwiki]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/04/19/ruwiki-081-coming-soon-ruwiki-090-soon-after/</guid>
		<description><![CDATA[It&#8217;s been several weeks longer than I thought it would be for Ruwiki 0.8.1, but the scope has grown, too. Curt Hibbs asked me to step up my efforts on authentication to make it possible to deploy Ruwiki on RubyForge soon.
Basically, all of the work that I mentioned in <a href="2004/09/02/ruwiki-deployment" title="Ruwiki Deployment">Ruwiki Deployment</a> needed to be done, [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been several weeks longer than I thought it would be for Ruwiki 0.8.1, but the scope has grown, too. Curt Hibbs asked me to step up my efforts on authentication to make it possible to deploy Ruwiki on RubyForge soon.</p>
<p>Basically, all of the work that I mentioned in <a href="2004/09/02/ruwiki-deployment" title="Ruwiki Deployment">Ruwiki Deployment</a> needed to be done, plus work to support authentication on RubyForge, while trying to establish a solid API that won&#8217;t need much fixing before the 1.0 release of Ruwiki. This also meant that some of the work planned for 0.9.0, including robot exclusion based on user ID (including the exclusion of certain robots entirely because they are email harvesters).</p>
<p>I hope to have Ruwiki 0.9.0 out by RubyConf, but I have my doubts as I haven&#8217;t even finished testing the deployment code in Ruwiki 0.8.1. It won&#8217;t be out much longer after that, though. Maybe even during RubyConf.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2004/09/21/ruwiki-081-coming-soon-ruwiki-090-soon-after/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Minitar, Ruwiki, and Commands</title>
		<link>http://www.halostatue.ca/2004/09/07/minitar-ruwiki-and-commands/</link>
		<comments>http://www.halostatue.ca/2004/09/07/minitar-ruwiki-and-commands/#comments</comments>
		<pubDate>Wed, 08 Sep 2004 03:49:35 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Archive]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruwiki]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2004/09/07/minitar-ruwiki-and-commands/</guid>
		<description><![CDATA[I mentioned last week that I had detoured into Mauricio&#8217;s rpa-base code for packaging code. I was all set to finish the work on a deployable Ruwiki, complete with this code included in the release, when I realised: &#8220;that&#8217;s dumb.&#8221; Why was I going to release something that could and should be an independent library [...]]]></description>
			<content:encoded><![CDATA[<p>I mentioned last week that I had detoured into Mauricio&#8217;s rpa-base code for packaging code. I was all set to finish the work on a deployable Ruwiki, complete with this code <strong>included</strong> in the release, when I realised: &#8220;that&#8217;s dumb.&#8221; Why was I going to release something that could and should be an independent library embedded in Ruwiki, when the whole point of the exercise is to make Ruwiki a good RubyGem and RPA package that doesn&#8217;t include things which are logically separate.</p>
<p>It wasn&#8217;t as if I weren&#8217;t going to release Minitar as a separate package; I said that I would, last week. I just realised that doing it earlier was more important than doing it later and getting Ruwiki out quickly. Doing this also helped me find an answer to the next phase of Ruwiki development, too (following the deployment release).</p>
<p>While looking around at options for how to present the UI for the Ruwiki deployment utility and the <tt>minitar</tt> utility, I looked at the RubyGems code that emulates the <tt>cvs</tt> command-line in many ways. This made a lot<br />
of sense, to me, so I created CommandPattern:</p>
<pre>class CommandPattern
  class AbstractCommandError < Exception; end
  class UnknownCommandError < RuntimeError; end
  class CommandAlreadyExists < RuntimeError; end

  class << self
    def add(command); ...; end
    def <<(command); ...; end
    attr_accessor :default
    def command?(command); ...; end
    def command(command); ...; end
    def [](cmd); ...; end
    def default_ioe; ...; end
  end

  def [](args, opts = {}, ioe = {}); ...; end
  def name; ...; end
  def call(args, opts = {}, ioe = {}); ...; end
  def help; ...; end
end</pre>
<p>It seems to me that this is <em>exactly</em> the same pattern as I need to deal with for Actions in Ruwiki. Okay, so there are differences -- but not as many as I had initially thought. The amount of code to be reused, to be quite honest, is low, but the concept reuse is high. It's very cool, to say the least.</p>
<h4 id="toc-follow-up">Follow-up</h4>
<p>With the release of minitar, the examples originally given for deployment could become:</p>
</pre>
<pre>% minitar extract ruwiki-0.8.0.tar.gz
% cd ruwiki-0.8.0
% ruwiki_servlet</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2004/09/07/minitar-ruwiki-and-commands/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruwiki Deployment</title>
		<link>http://www.halostatue.ca/2004/09/02/ruwiki-deployment/</link>
		<comments>http://www.halostatue.ca/2004/09/02/ruwiki-deployment/#comments</comments>
		<pubDate>Fri, 03 Sep 2004 03:42:00 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruwiki]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2006/04/19/ruwiki-deployment/</guid>
		<description><![CDATA[When Alan originally wrote Ruwiki, he wrote it as a single-user or small-group Wiki clone. When I first started hacking against Ruwiki, I kept it the same. There is increased interest in Ruwiki on large Ruby sites now, as well as interest in having Ruwiki delivered via RubyGems or RPA.
Ruwiki works extremely well under the [...]]]></description>
			<content:encoded><![CDATA[<p>When Alan originally wrote Ruwiki, he wrote it as a single-user or small-group Wiki clone. When I first started hacking against Ruwiki, I kept it the same. There is increased interest in Ruwiki on large Ruby sites now, as well as interest in having Ruwiki delivered via RubyGems or RPA.</p>
<p>Ruwiki works extremely well under the &#8220;unpack and run&#8221; model that we&#8217;ve delivered it as so far. Unfortunately, when considering how to deliver Ruwiki as a RubyGem (as Mauricio and the RPA team will deliver Ruwiki as an RPA package), it was brought to my attention that the installation is in a central location, and this is not desirable: this means that you could only have one Wiki per machine<sup>1</sup> and that the data would be in a location that is less than ideal (under RubyGems, it would be under <code>${prefix}/rubygems/gems/ruwiki-&lt;em&gt;version&lt;/em&gt;/data</code>), making it hard to have a private Wiki on a public server. Originally, I thought this would be a trivial thing to fix, but it isn&#8217;t, especially when the goal is to keep Ruwiki as simple as possible for the end user. Solving this installation problem, however, seems to solve other possible deployment scenarios.</p>
<p>The first step is to make it so that one doesn&#8217;t even need to have the main Ruwiki programs in the same directory as the Wiki. Some of this has been enabled for a long time, but I&#8217;ve never really tested this configuration. I determined that it would be beneficial to have the ability to keep a configuration file separate from the Ruby code.</p>
<p>The Flatfiles tagged format (<code>section!item:value</code>) was ideal for this<sup>2</sup>, and I generalised it to handle any two-level hash (e.g., <code>{ 'ruwiki' =&gt; { 'version' =&gt; 0.8.1 } }</code>). This became Ruwiki::Exportable; I verified that my implementation was correct and complete by modifying Ruwiki::Backend::Flatfiles and Ruwiki::Page to use Ruwiki::Exportable, and then implemented it in Ruwiki::Config. This required one incompatible change: previously, storage options had been stored like <code>@opts[:&lt;em&gt;type&lt;/em&gt;][:&lt;em&gt;name&lt;/em&gt;]</code>. While the storage type is still referred to as a Symbol, the options for each storage type are now stored as strings. That is, what used to be <code>@storage_options[:flatfiles][:data_path]</code> is now <code>@storage_options[:flatfiles]['data-path']</code>. Note that the name has changed slightly, too.</p>
<p>The second step is initial deployment. This led me into a week-long diversion into Mauricio&#8217;s RPA::Package code, leading to the creation of my Tar module (based very heavily on Mauricio&#8217;s code, but also incorporating a number of changes); this will be released as a separate package with a limited tar/untar program at a later date. I now have the ability to pull Ruwiki data, templates, and executables from a central location. Because the feature was so easy to add, I have made it possible for users to package their wiki (into a <code>.pkg</code> file) and unpackage it elsewhere. I am completing the deployment command-line now. It used to be that one would do:</p>
<pre>% tar xvfz ruwiki-0.8.0.tar.gz
% cd ruwiki-0.8.0
% ruwiki_servlet</pre>
<p>Now, one will do:</p>
<pre>% gem install ruwiki
% ruwiki install --to ruwiki # installs the data/ and templates/ to ruwiki/
% cd ruwiki
% ruwiki_servlet # pulls from the stub installed by RubyGems</pre>
<p>The third and final step for this is packaging. My packaging requirements have become far more complex, so I have to automate the packaging process. When I release Ruwiki, now, I will need to check out the codebase, create a default configuration file (<code>ruwiki_servlet --save-config</code>) for the current release, create the default deployment package for the current release, build the gem with those files, and <em>then</em> create the <code>.tar.gz</code> distribution. I also need to PGP/GPG sign the released files.</p>
<p>Those who have looked at my releases will have noted that I <code>touch</code> all of my released files to the date and time of the release; this will actually be easier to deal with using an automated packaging process, but this is part of the process.</p>
<p style="margin-left: 3em;"><sup>1</sup> Yes, you could copy the executable files (ruwiki.cgi or ruwiki_servlet) and modify those before running, but this is less than ideal for many things.</p>
<p style="margin-left: 3em;"><sup>2</sup> I didn&#8217;t use YAML because of various problems with YAML across versions of Ruby, including parts which still do not work with Ruby 1.8.2 preview2 on Windows&ndash;and I am not in a position to test post-preview2 code at the moment. I didn&#8217;t use XML because that would add another dependency to Ruwiki. Finally, I didn&#8217;t use Marshal because I wanted the files to be human editable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2004/09/02/ruwiki-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on the Tablet PC</title>
		<link>http://www.halostatue.ca/2003/05/15/notes-on-the-tablet-pc/</link>
		<comments>http://www.halostatue.ca/2003/05/15/notes-on-the-tablet-pc/#comments</comments>
		<pubDate>Thu, 15 May 2003 04:07:40 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2003/05/15/notes-on-the-tablet-pc/</guid>
		<description><![CDATA[Back in February, I got the Compaq TC1000 Tablet PC. Aside from the <a href="2003/02/28/support-policies-and-tablet-pcs" title="initial problem">initial problem</a> I had with HP/Compaq support, I&#8217;ve liked the machine. It&#8217;s a good first generation, but it&#8217;s still not a perfect platform.
I chose the TC1000 over other versions available in Canada for several reasons. The Compaq is significantly (CDN $900) cheaper [...]]]></description>
			<content:encoded><![CDATA[<p>Back in February, I got the Compaq TC1000 Tablet PC. Aside from the <a href="2003/02/28/support-policies-and-tablet-pcs" title="initial problem">initial problem</a> I had with HP/Compaq support, I&#8217;ve liked the machine. It&#8217;s a good first generation, but it&#8217;s still not a perfect platform.</p>
<p>I chose the TC1000 over other versions available in Canada for several reasons. The Compaq is significantly (CDN $900) cheaper than either the Toshiba or Acer versions for similar feature-sets. With a 15% discount available at the time that I purchased it, this was an even better deal. Additionally, it was the Tablet PC form-factor I desired: a &#8220;convertible.&#8221;</p>
<p>All versions of the TC1000 are equipped with a Transmeta Crusoe 1GHz processor; 10.4” 1024&#215;768 XGA display; 256Mb or 512Mb RAM; a 30Gb, 40Gb, or 60Gb HDD; and a one or three year warranty. All versions can be expanded to 768Mb RAM. As with all laptops, the more RAM present, the more effect on the battery life, but note that the Crusoe requires 24Mb of RAM for its Code Morphing, so more RAM will result in better performance in Windows. All versions except the cheapest come with a mini-PCI 802.11b card. It also has standard VGA, ethernet (RJ45), modem (RJ11), and audio (headphones, microphone, and headset) connectors. For expansion, it has two USB 2.0 ports, a CompactFlash slot, and a PC Card slot. Just for reference, I have the TC1000/470045-149 (30Gb, 256Mb, 802.11b).</p>
<p><span id="more-10"></span><span style="font-weight: bold">The Physical Tablet</span></p>
<p>Like all Tablet PCs, the TC1000 screen can be oriented in any of four directions (two each portrait [768x1024] and landscape [1024x768]). When in primary portrait mode, the COMPAQ label is at the bottom of the PC. There is a microphone below the A and Q with stereo speakers on the bottom of the PC. On the lower left-hand corner are three LEDs for AC power, battery charging, and WLAN status (solid when a WLAN connection has been made; blinking when seeking). On the top left face of the tablet are three pen hotspots that default to Windows Journal, Entry Panel, and Rotate Screen Orientation. These are backed with LEDs which light up when the hotspot is selected with the pen.</p>
<p>Above these hotspots is a plastic cover covering the USB ports, ethernet and phone connectors, and video connector. The AC connection is to the left of the cover; the PC Card and CF slots are to the right of the cover. The pen is stored in a spring-loaded slot to the right of the card slots. On the top right corner of the tablet is the power button, a sunken button, three raised buttons, and a rocker tab. I&#8217;ll deal with these buttons later as I talk about using the system. The power button is backed by an LED which blinks when the tablet is suspended; the button is pushed up to turn the tablet on or suspend; it is held up to turn the device off.</p>
<p>As I noted above, the TC1000 is a &#8220;convertible&#8221; Tablet PC, but it differs from other convertible tablets significantly. The TC1000 has a detachable keyboard, allowing use as a dedicated slate, much like the Viewsonic and other pure slates. The keyboard itself can be connected to an included pseudoleather zipcover. The connections between the three pieces are solid; they don&#8217;t come apart unless you have pulled the unlock mechanism on the back of the keyboard or tablet. The tablet can rotate on the keyboard and lay flat with the keyboard locked against the tablet. It adds about a centimetre in depth and a bit more than half a pound of weight to the tablet PC.</p>
<p>The keyboard is about 90%&ndash;95% normal size; only a few things are annoying about the keyboard (the location and size of the function keys, plus the fact that F12 is only accessible with the Fn key). The keyboard also has a joystick pointer in the normal &#8220;notebook&#8221; position. What is most unusual about using the keyboard with the TC1000 is the same thing that has been noted in various reviews&mdash;the tablet screen sits flush with the keyboard, making some of the function keys hard to hit reliably. Annoying, but necessary, as this is the only thing which gives the TC1000 stability in &#8220;notebook&#8221; mode.</p>
<p><span style="font-weight: bold">The Tablet Pen</span></p>
<p>The pen is stored in a spring-loaded silo near the power button. When the pen is inserted into the silo, it sticks out about two or three centimetres. The pen can then be pushed almost fully into the tablet with some resistance as the spring mechanism locks so that only the rounded head of the pen sticks out of the tablet, perhaps a couple of millimetres. Pushing on the pen again pops the pen about halfway out (it&#8217;s a strong spring).</p>
<p>The pen itself is relatively thick, which is strange for those of us who are used to thinner styli from PDAs (unlike most people, I have actually become fond of the thin Sony stylus that came with the T615C and the NR70V). I think that I would have preferred the thinner stylus from the Acer or the Toshiba; those styli are only slightly larger than the AAAA battery that powers the stylus, as this stylus is thicker than the typical sort of pen that I would purchase in any case.</p>
<p>The tip of the stylus is equivalent to the left mouse button; there is a button on the barrel of the stylus that acts as the right mouse button. Unlike some styli, there is no &#8220;inverse&#8221; operation of the stylus (the Acer stylus works both normally and inverted, where the inverted operation acts as an eraser). The tablet PC is based on an active digitizer, meaning that when the stylus is floated over the screen, the mouse pointer will track with the stylus. The tip of the stylus must be in contact with the screen to &#8220;write&#8221;, although I have found a bit of stickiness to the tip of the stylus, resulting in a bit of &#8220;overwriting&#8221; from time to time. I can&#8217;t reproduce it reliably, so I haven&#8217;t reported it to HP.</p>
<p><span style="font-weight: bold">Windows XP Tablet Edition</span></p>
<p>While I agree with most folks about the odiousness of WPA, I also think that Windows XP is an amazingly good operating system, such that it is the only Windows-based operating system that I run anymore. Windows XP Tablet Edition (XPTE) takes XP Pro and improves upon the existing alternative input mechanisms. The pen-based input is reliable and reasonably good at interpreting most of my handwriting. I&#8217;ve also enabled and tried the &#8220;block recogniser&#8221;, but don&#8217;t care for it (it always seemed a poor imitation of Graffiti). The voice input mechanism is inconvenient for me, so I haven&#8217;t really used it.</p>
<p>I use the tablet PC in &#8220;notebook&#8221; mode most often because I&#8217;m a programmer. However, in my consulting, I have used the Windows Journal to sketch designs and take notes; for this, the tablet PC is perfect. I&#8217;ve also used the tablet PC to mark up a book that I have reviewed for a publisher, which was good stuff. I printed to the journal virtual printer and marked up the document just as if I had printed the document out. I can&#8217;t emphasize how nice this was.</p>
<p>There are a variety of reasons (aside from programming) I don&#8217;t use the TC1000 in tablet mode more often. First, and foremost, the recognition still isn&#8217;t quite good enough. I&#8217;ve had to rewrite some sentences too often, and the spacing is too aggressive (and not configurable), meaning that I have to correct a number of smaller things. Second, while many Microsoft programs are acceptably modified for XPTE, too many other programs aren&#8217;t. Third, the text input area takes up too much space (yes, I know it&#8217;s resizable) and the &#8220;whole area&#8221; isn&#8217;t really good enough (and interferes with normal operation). Fourth, there simply aren&#8217;t enough buttons available.</p>
<p>That last point, to me, is the killer. There are several customizable buttons and hotspots available on the TC1000. There&#8217;s a &#8220;mail&#8221; button (recessed, immediately below the power buttton); I use it often. There&#8217;s a Q button (raised, below the mail button) which by default launches the &#8220;Q menu&#8221;. This menu is configurable, but by default allows for quick muting, brightness controls, hibernation, and even the wireless controller. Next to the Q button are buttons labeled ESC and Tab (and are by default assigned to those keystrokes). Between these buttons is a hole that the stylus tip will fit through; this brings up the Task Manager (it&#8217;s the equivalent of Ctrl-Alt-Del). Below these buttons is the jog rocker (defaulting to up arrow, down arrow, and enter). Additionally, there are the hotspots on the top of the portrait screen noted earlier.</p>
<p>The problem is that the settings for these buttons is system-wide. So while it may be useful in some programs to have an ESC key defined, it is not going to be the case in all programs. In web browsing, I would prefer the jog rocker act as page up and down; in word processing, I might prefer it be left and right (so that I can move by character). It gets worse when you realise that you cannot tap the pen and select the second button at the same time, losing the ability to emulate a third mouse button. My preferred web browser, Mozilla, allows me to affect behaviours by selecting Ctrl, Alt, and Shift versions of both left and right mouse clicks.</p>
<p>Imperfect? Absolutely. Usable? You bet. The TC1000 has become my primary computer, primarily because of its size (just over three pounds with the keyboard attached).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2003/05/15/notes-on-the-tablet-pc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Support Policies and Tablet PCs</title>
		<link>http://www.halostatue.ca/2003/02/28/support-policies-and-tablet-pcs/</link>
		<comments>http://www.halostatue.ca/2003/02/28/support-policies-and-tablet-pcs/#comments</comments>
		<pubDate>Fri, 28 Feb 2003 04:02:44 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2003/02/28/support-policies-and-tablet-pcs/</guid>
		<description><![CDATA[I sent my Tablet PC off for repair on Thursday. I like my Tablet PC a lot, but I highly recommend buying an &#8220;extended care&#8221; warranty if it&#8217;s available. Tablet PC manufacturers (I can speak specifically toward HP, since I&#8217;m using the Compaq TC1000) haven&#8217;t yet figured out the best way to handle drops.
I dropped [...]]]></description>
			<content:encoded><![CDATA[<p>I sent my Tablet PC off for repair on Thursday. I like my Tablet PC a lot, but I highly recommend buying an &#8220;extended care&#8221; warranty if it&#8217;s available. Tablet PC manufacturers (I can speak specifically toward HP, since I&#8217;m using the Compaq TC1000) haven&#8217;t yet figured out the best way to handle drops.</p>
<p>I dropped the TC1000 off the couch and the top layer was scratched. When I called HP support about this, the initial quote was a minimum of CDN $1,200 (the cost of replacing the entire LCD assembly). I paid about $2,800 for the device, and HP wanted 40% of the cost to repair a scratch. Right. PalmOS devices have typically been about CDN $150 to repair the screen. I can&#8217;t find the details on Sony NR-70V screen, but I wouldn&#8217;t be surprised if it&#8217;s similar. I bought the NR-70V last May for about CDN $1,100. To me, the proper cost would be about 2 times the cost of repairing a PalmOS device (call it CDN $375)&mdash;the same cost ratio. It&#8217;s costing me about that much to have the TC1000 repaired anyway, but the initial quote was just insane.</p>
<p>What bothers me most about the cost of support repairs is that in many cases, the manufacturer can then repair parts with lesser damage (like the scratch on my tablet PC) and then use the repaired part in future repairs. My LCD wasn&#8217;t broken; this was the top layer of plastic or glass on the TC1000. In other words, for a CDN $170 piece of equipment, I may have been charged CDN $1,200. I&#8217;m not saying that HP would have done this, and they&#8217;ve worked wonderfully with me on this to reduce the cost significantly, but I had to work harder on this than I should have. This also would have been avoided with the Compaq &#8220;CarePaq&#8221; (their name for the insurance/warranty available which allows for one repair per year for three years). Unfortunately, I don&#8217;t think that it was available when I bought the device. I will get it, but it still annoys me how much I had to work to get this repaired. (It&#8217;s also not as good as the Dell plan that I have, which is three years of on-site service.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2003/02/28/support-policies-and-tablet-pcs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Complex Data Structures in PL/SQL</title>
		<link>http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/</link>
		<comments>http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#comments</comments>
		<pubDate>Sun, 10 Nov 2002 22:11:11 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2002/11/10/complex-data-structures-in-plsql/</guid>
		<description><![CDATA[

The Shape of the Problem

Example 1: The C Array


The Limitations of the Language
The Shape of the Solution

Example 2: The C Linked-List


The Solution

Example 3: The PL/SQL Linked-Array


Further Options
Lessons Learned
Further Reading
Source Listings

Listing 1: Data Split Package (data_split_pkg.sql)
Listing 2: Data Split Package Body (data_split_pkg_body.sql)
Listing 3: Schema (data_split_tables.sql)
Listing 4: Data (test_data_split.sql)




In an ideal software development project, the development environment [...]]]></description>
			<content:encoded><![CDATA[<div class="toc">
<ol>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-the-shape-of-the-problem">The Shape of the Problem</a></p>
<ol>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-example-1-the-c-array">Example 1: The C Array</a></li>
</ol>
</li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-the-limitations-of-the-language">The Limitations of the Language</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-the-shape-of-the-solution">The Shape of the Solution</a>
<ol>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-example-2-the-c-linked-list">Example 2: The C Linked-List</a></li>
</ol>
</li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-the-solution">The Solution</a>
<ol>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-example-3-the-plsql-linked-array">Example 3: The PL/SQL Linked-Array</a></li>
</ol>
</li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-further-options">Further Options</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-lessons-learned">Lessons Learned</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-further-reading">Further Reading</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-source-listings">Source Listings</a>
<ol>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-listing-1-data-split-package-data_split_pkg-sql"><a name="listing1"></a>Listing 1: Data Split Package (data_split_pkg.sql)</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-listing-2-data-split-package-body-data_split_pkg_body-sql"><a name="listing2"></a>Listing 2: Data Split Package Body (data_split_pkg_body.sql)</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-listing-3-schema-data_split_tables-sql">Listing 3: Schema (data_split_tables.sql)</a></li>
<li><a href="http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/#toc-listing-4-data-test_data_split-sql">Listing 4: Data (test_data_split.sql)</a></li>
</ol>
</li>
</ol>
</div>
<p>In an ideal software development project, the development environment (that is, the languages, tools, and libraries) will be chosen that best suits the nature of the problem domain and the skills of the professionals involved. In the real world, the development environment is dictated by any number of constraints. The most common is that the project is a modification to or enhancement of an existing project. Just because one cannot &#8211; for whatever reason &#8211; use the language most suited to the solution does not mean that one can&#8217;t take lessons from those languages.</p>
<p>At one of my previous jobs, I worked on a project where the code was written in PL/SQL called by a C driver. A lot of developers, in my experience, don&#8217;t think much of PL/SQL because they believe that it performs slowly, or because its functionality is limited. (Most of the time, however, this prejudice is present because the developers involved do not know the language itself.) For this project, PL/SQL performed the tasks (mostly data manipulation) as fast or faster than an equivalent C implementation could have done because there were fewer context switches and no network communication involved. (If you aren&#8217;t familiar with PL/SQL, see the <a href="2002/11/10/an-extremely-brief-introduction-to-plsql" title="accompanying article">accompanying article</a>.)</p>
<p>As useful as it is, PL/SQL is not without its limitations, mostly surrounding complex data structures. These limitations presented what seemed to be an insurmountable roadblock to the project, but the time-frame of this subproject did not allow for the language to be changed to one where the data structures required could be represented more &#8216;naturally.&#8217;</p>
<p>The subsystem in question required that the time-series data be viewed in ways which are not supported by Oracle SQL queries on the original data; it was necessary to restructure the data. This turned out to be more of a problem than I had originally anticipated, and the eventual solution to the problem came from an interesting combination of techniques. In the end, I adapted data structures that are more naturally represented in languages like C, C++, and Java in PL/SQL.</p>
<p><span id="more-14"></span></p>
<h2 id="toc-the-shape-of-the-problem">The Shape of the Problem</h2>
<p><a id="table1"></a></p>
<table summary="Records with values spanning time">
<tr>
<th style="text-align: right">Type</th>
<th>Start</th>
<th>End</th>
<th>Value</th>
</tr>
<tr>
<td>ABC</td>
<td>06/01/01</td>
<td>06/01/01</td>
<td align="right">1</td>
</tr>
<tr>
<td>DEF</td>
<td>06/01/01</td>
<td>06/05/01</td>
<td align="right">15</td>
</tr>
<tr>
<td>ABC</td>
<td>06/01/01</td>
<td>06/03/01</td>
<td align="right">3</td>
</tr>
<tr>
<td>GHI</td>
<td>06/02/01</td>
<td>06/03/01</td>
<td align="right">10</td>
</tr>
</table>
<p>The data was stored in the database as multiple records representing the data class, the starting and ending dates, and the value. Records could have any value (positive or negative) that spans any amount of time. Multiple entries of the same data class for overlapping time periods could be present. <a href="#table1">Table 1</a> shows how records for a five-day period might be present in the database. <a href="#figure1">Figure 1</a> shows how these records could be considered on a timeline, which is how these values must be considered by the program.</p>
<p><a id="figure1"></a></p>
<div style="text-align: center">
  <img title="Graphical representation of table 1" alt="Graphical representation of table 1" src="http://www.halostatue.ca/images/plsql_data_structures/01-sample-data-timeline.png" /></p>
<p>Figure 1: Sample Data</p>
</div>
<p>This particular program needed to divide and combine the records such that there was one record for each data class per day, containing the portions of values which occurred on that day. If a record crossed multiple days, it was the program needed to see it within the daily summary for each of the days in which it existed and only for the proportion of the record that existed in that day. That is, because record GHI spans two days, the program has to treat it as if it were two separate GHI records, each of value 5. Similarly, there will be a total of three ABC records; the first record will have value 2 because that is the <strong>total</strong> of the portions of ABC records on that date. Data 2 shows how the data needs to be reorganized on a daily basis. <a href="#table2">Table 2</a> shows how the data needs to be reorganized on a daily basis. <a href="#figure2">Figure 2</a> shows the same information against a timeline. Compared against <a href="#figure1">figure 1</a>, the way that the records have been massaged becomes clear.</p>
<p><a id="table2"></a></p>
<table summary="Records split into daily values">
<tr>
<th>Date</th>
<th>Type</th>
<th>Value</th>
</tr>
<tr>
<td>06/01/01</td>
<td style="text-align: center">ABC</td>
<td style="text-align: center">2</td>
</tr>
<tr>
<td>06/01/01</td>
<td style="text-align: center">DEF</td>
<td style="text-align: center">3</td>
</tr>
<tr>
<td>06/02/01</td>
<td style="text-align: center">ABC</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td>06/02/01</td>
<td style="text-align: center">DEF</td>
<td style="text-align: center">3</td>
</tr>
<tr>
<td>06/02/01</td>
<td style="text-align: center">GHI</td>
<td style="text-align: center">5</td>
</tr>
<tr>
<td>06/03/01</td>
<td style="text-align: center">ABC</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td>06/03/01</td>
<td style="text-align: center">DEF</td>
<td style="text-align: center">3</td>
</tr>
<tr>
<td>06/03/01</td>
<td style="text-align: center">GHI</td>
<td style="text-align: center">5</td>
</tr>
<tr>
<td>06/04/01</td>
<td style="text-align: center">DEF</td>
<td style="text-align: center">3</td>
</tr>
<tr>
<td>06/04/01</td>
<td style="text-align: center">DEF</td>
<td style="text-align: center">3</td>
</tr>
</table>
<p>The easiest way to handle this problem would be to make it so that as each record is added to the original table, a trigger is fired that does the record division as noted in <a href="#table2">table 2</a> and adds the resulting records to a daily summary table. This solution has three major problems with it:</p>
<ol>
<li>The source table from which the original records were pulled was a very high volume table (and significantly larger than the sample data shown). Performing the split on a per-insert basis is computationally expensive, as each data class was generally expected to have at least one record and more likely several records each day (note that the examples given in this article assume only a single data source).</li>
<li>The total volume of the data in the source table was very high, and the daily summary table would be at least as large, and most likely several times larger than the source table. Since these values are computed and are used in a single subsystem (this one) only, it didn&#8217;t make sense to use that much storage for what was essentially a temporary table.</li>
<li>Each of the records in the data source table had a limited lifespan; once the analysis had been run on the record successfully, the analyzing program would never see it again. This would have increased the volume of the summary table unacceptably, because the summaries would have to be differentiated by visibility.</li>
</ol>
<p><a id="figure2"></a></p>
<div style="text-align: center">
  <img title="Graphical representation of table 2" alt="Graphical representation of table 2" src="http://www.halostatue.ca/images/plsql_data_structures/02-sorted-timeline.png" /></p>
<p>Figure 2: Sample Data Converted into Daily Records</p>
</div>
<p>Without a temporary summary table, there was no way to do solve this problem with SQL queries (after all, the temporary summary table solved the problem of the data structure), so I needed to approach this programmatically. The data structure immediately suggested by <a href="#figure2">figure 2</a> is an array of daily records, each of which has a dynamically-resized array of item records. If I were using a C-like language, I might use data structures like <a href="#example1">example 1</a> to solve this, which would produce an array like the one shown in <a href="#figure3">figure 3</a>.</p>
<p><a id="example1"></a></p>
<div>
<h3 id="toc-example-1-the-c-array">Example 1: The C Array</h3>
<pre class="code"><strong>typedef struct</strong> item_rec
{
  <strong>char</strong>    grouping[4];
  <strong>double</strong>  value;
} item_rec;

<strong>typedef struct</strong> day_rec
{
  <strong>int</strong>       date; <em>/* an integer in yyymmdd format */</em>
  item_rec* item_list;
} day_rec;

day_rec* day_list;</pre>
</div>
<p><a id="figure3"></a></p>
<div style="text-align: center">
  <img title="An array pointing to arrays" alt="An array pointing to arrays" src="http://www.halostatue.ca/images/plsql_data_structures/03-c-array.png" /></p>
<p>Figure 3: An array containing dynamically resized arrays</p>
</div>
<h2 id="toc-the-limitations-of-the-language">The Limitations of the Language</h2>
<p>This realization was very good, except for the fact that I couldn&#8217;t rewrite the program in C or C++ for this project<sup title="This was done in a later project that took roughly twice as long as this project did.">1</sup>. As stated previously, there was no time to explore that option. The answer had to be reached, quickly, with the tools available. The simple solution was not an option because the PL/SQL limitations around complex data structures. PL/SQL simply does not support nested collections. The array of structures containing arrays would not work in PL/SQL.</p>
<p>I looked through my library of PL/SQL books for a hint on how to solve this problem, but no one had publicly tackled this problem. There was, however, a hint toward a possible solution in <em>Programming PL/SQL (2<sup>nd</sup> Edition)</em> [Feuerstein 1998]. Steve Feuerstein has noted and lamented this limitation of PL/SQL, and he presented a section on how fixed-size multi-dimensional arrays could be simulated. He presented this as a package allowing the developer to predefine (almost &#8220;allocate&#8221;) an array of size <em>r</em> &times; <em>c</em> complete with accessor functions. Because the implementation is hidden in the body of the package, it looks and works much like a two-dimensional array in other languages.</p>
<p>The technique presented was to use a PL/SQL <tt class="keyword">INDEX BY BINARY_INTEGER</tt> memory table and map the two-dimensional array to this single table. The position of an element at [<em>m</em>, <em>n</em>] in an array of <em>r</em> &times; <em>c</em> elements are found in the index-by table with the forumula:</p>
<p><a id="figure3"></a></p>
<p style="text-align: center;"><tt>i := ((<em>m</em> &times; (<em>c</em> - 1)) + <em>n</em>)</tt></p>
<p>That is, in a 10 &times; 10 array, position [7, 3] is at position <span title="(7 &times; (10 - 1)) + 3">66</span> in a single-dimensional array of size 100. Similar calculations could be used for more than two dimensions, but it only works when you have fixed-size dimensions. There are other limitations best explained by Mr Feuerstein in his book.</p>
<p>As noted earlier, the problem to be solved had an indeterminate number of columns (dates) and rows (data class entries per day), so this technique could not offer a solution. It did, however, offer some ideas on how more complex data structures might be emulated in PL/SQL.</p>
<h2 id="toc-the-shape-of-the-solution">The Shape of the Solution</h2>
<p>Part of the problem that I faced when originally implementing this was that I was letting my knowledge of PL/SQL and its limitations dictate where I was willing to look for solutions. I knew that because I couldn&#8217;t do nested arrays, I didn&#8217;t look as closely as I should have at first. However, PL/SQL is a general-purpose language where one can define new data types, so it&#8217;s simply a matter of needing to adapt to the limitations. To consider how I might do this, I considered alternative options in C-like languages, knowing that I could able to adapt the solution to PL/SQL.</p>
<p><a href="#figure3">Figure 3</a> represents the data as it might be implemented in C. It&#8217;s a single array (<tt>day_list</tt>) where each entry in that array is linked to another array (<tt>item_list</tt>). Because it needed to be a dynamically resizable array, I would probably implement it as <tt>item_rec *item_list</tt>, a pointer to an item. If I allocated memory in increments of <tt><span class="keyword">sizeof</span>(item_rec)</tt>, then I could able to take advantage of C pointer arithmetic and treat the pointer as if it were an array &#8211; making it an implicitly linked list.</p>
<p>Most people don&#8217;t consier an array to be a linked list because it doesn&#8217;t act like one. While most arrays or vectors are implemented as contiguous memory blocks, this is not necessarily the case. Any given vector class could be implemented as a contiguous memory block or a linked list and the programmer using that vector class should never know the difference. The linking relationship in an array is based on proximity, not on an explicit link. If I modified the <tt>item_rec</tt> definition to include an explicit link to the next item in the array, as in <a href="#example2">example 2</a>, then the linked-list relationship becomes explicit, allowing me to consider the implementation of the solution from a different angle. <a href="#figure4">Figure 4</a> shows the modified structure graphically.</p>
<p><a id="figure4"></a></p>
<div style="text-align: center">
  <img title="An array pointing to linked lists" alt="An array pointing to linked lists" src="http://www.halostatue.ca/images/plsql_data_structures/04-c-linked-list.png" /></p>
<p>Figure 4: An array pointing to linked lists</p>
</div>
<p><a id="example2"></a></p>
<div>
<h3 id="toc-example-2-the-c-linked-list">Example 2: The C Linked-List</h3>
<pre class="code"><strong>typedef struct</strong> item_rec
{
  <strong>char</strong>              grouping[4];
  <strong>double</strong>            value;
  <strong>struct</strong> item_rec*  next;
} item_rec;

<strong>typedef struct</strong> day_rec
{
  <strong>int</strong>       date; <em>/* an integer in yyymmdd format */</em>
  item_rec* item_list;
} day_rec;

day_rec* day_list;</pre>
</div>
<p>Further analysis of the problem revealed that this particular problem did not need the biggest strength of arrays: random access to the records stored in an array. I only needed to access the records in date order and then in the order in which they appeared in the database, so sequential access was sufficient, making it very clear that a linked-list was most likely to lead to the &#8220;correct&#8221; implementation. It does not, however, reach the solution, becuase PL/SQL only has automatic memory management and references are only allowed to SQL cursor variables (in Oracle8<em>i</em>). Since there is no way to allocate memory programmatically like one would with <tt class="keyword">malloc</tt> or <tt class="keyword">new</tt>, I needed a modified approach for PL/SQL.</p>
<p>As it happens, PL/SQL has three different collection types, and only one of them is an array in the traditional sense (the varying array, <tt class="keyword">VARRAY</tt>). Varying arrays and object tables are the newest additions to the PL/SQL language and are present to support the Oracle8<em>i</em> object-relational extensions. Both data types are very useful, but they are Oracle8<em>i</em>-specific features and are not available in Oracle7; they also require more effort and planning to use than the normal PL/SQL index-by tables. Both varying arrays and object tables are close in interface to arrays in other languages (the developer is responsible for extending the array to add values to the end of the array, and the indexes are always created in order).</p>
<p>The third type of collection in PL/SQL, the index-by table, was my only option in Oracle7, but index-by tables are still probably the optimal choice for this sort of problem. Index-by tables are sparse tables indexed by a binary integer value. A sparse table is rather like a set or a Perl hash (using integer keys): only one value may exist at any given index. Unlike varying arrays and object tables, index-by tables <em>automatically allocate the space required for the variables</em> in the collection, more like a vector class than a C array. Index values may be non-contiguous (e.g., 1, 2, 5, 7). If the keys are created contiguously, they look and act in many ways like a C array, but otherwise they allow for smart indexing just as a set or hash allows.</p>
<p>Because index-by tables can be non-contiguous, PL/SQL provides alternate means for navigating them. There are four methods associated with index-by tables: <tt class="keyword">FIRST</tt>, <tt class="keyword">NEXT</tt>, <tt class="keyword">PREV</tt>, and <tt class="keyword">LAST</tt>. Using <tt class="keyword">FIRST</tt> or <tt class="keyword">LAST</tt> will provide the index of the first or last entry in the table, respectively. <tt class="keyword">NEXT</tt> and <tt class="keyword">PREV</tt> are called with a parameter (e.g., <tt>day_list.<span class="keyword">NEXT</span>(day_idx)</tt>) of the index for which you wish to find the next (or previous) index value. If there is nothing in the table, <tt class="keyword">FIRST</tt> and <tt class="keyword">LAST</tt> will return <tt class="scalar">NULL</tt>; if there is no record that exists after (before) the requested index, <tt class="keyword">NEXT</tt> (<tt class="keyword">PREV</tt>) will return <tt class="scalar">NULL</tt>. One other interesting behaviour in a non-contiguous sparse table is that the index value provided as a parameter for <tt class="keyword">NEXT</tt> or <tt class="keyword">PREV</tt> does not need to represent a value that actually exists. In this way, I can have an index-by table that has values at [5, 10, 15, 20] and <tt><span class="keyword">NEXT</span>(<span class="scalar">7</span>)</tt> will return 10. The possibilities for this are extensive and exciting.</p>
<p>Using <tt class="keyword">NEXT</tt> and <tt class="keyword">PREV</tt> with an index-by table makes it appear to work much like a doubly linked list, so if I consider the binary integer type as if it were a pointer, I can interweave several linked lists within a single contiguous vector.</p>
<p>By mapping the linked list from <a href="#figure4">figure 4</a> to a vector structure, I get something that looks like <a href="#figure5">figure 5</a>; example 3 gives the data structures (in PL/SQL) to implement it. The first index-by table (<tt>day_list</tt>) contains an index reference to the head of its item list, which is an entry in the second index-by table (<tt>item_list</tt>). The item records have index references to the next item in its chain, with a <tt class="scalar">NULL</tt> value representing the end of the chain for that particular entry. In this way, I&#8217;m using the random-access nature of array indexing to my advantage while sequentially winding my way through my linked-list imposed on top of the index-by table.</p>
<p><a name="figure5"></a></p>
<div style="text-align: center">
  <img title="An array pointing to arrays" alt="An array pointing to arrays" src="http://www.halostatue.ca/images/plsql_data_structures/05-plsql-list-array.png" /></p>
<p>Figure 5: The PL/SQL data structure &#8211; an array pointing to a linked list created from another sparse array.</p>
</div>
<p>The lists in question must be treated as an inseparable pair. The &#8220;real&#8221; lists must be declared in one place and one place only. In Oracle7 or Oracle8, then it is in your best interest to declare these as private package global (not public package global, unless you <strong>want</strong> the users of your package messing with these values and possibly messing up your linked list). You can declare these in a function and pass them around as a pair to other functions that use them, but you must remember that if one of them is <tt class="keyword">IN OUT</tt> the other must be <tt class="keyword">IN OUT</tt> as well. It&#8217;s not recommended that you do this for large data sets that are transformed in this way unless you&#8217;re using Oracle8i and can use the <tt class="keyword">NOCOPY</tt> keyword to pass these tables by reference between functions and procedures.</p>
<h2 id="toc-the-solution">The Solution</h2>
<p><a name="example3"></a></p>
<div>
<h3 id="toc-example-3-the-plsql-linked-array">Example 3: The PL/SQL Linked-Array</h3>
<pre class="code"><strong>TYPE</strong> day_rec <strong>IS RECORD</strong>
    (day_date   <strong>DATE</strong>,
     item_head  <strong>BINARY_INTEGER</strong>);

<strong>TYPE</strong> day_tab <strong>IS TABLE OF</strong> day_rec
    <strong>INDEX BY BINARY_INTEGER</strong>;

<strong>TYPE</strong> item_rec <strong>IS RECORD</strong>
    (type_code  <strong>VARCHAR(3)</strong>,
     amount     <strong>NUMBER</strong>,
     next_item  <strong>BINARY_INTEGER</strong>,
     prev_item  <strong>BINARY_INTEGER</strong>);

<strong>TYPE</strong> item_tab <strong>IS TABLE OF</strong> item_rec
    <strong>INDEX BY BINARY_INTEGER</strong>;</pre>
<p>I have provided a sample implementation that reads a data value table (like <a href="#table1">table 1</a>), parses the values according to the rules stated above (assuming a single data source) into the structures shown in <a href="#example3">example 3</a>, and then writes the resulting data to a summary table (like <a href="#table2">table 2</a>). In the real application for which this technique was used, the summary is kept only in memory while analysis is performed, and then only the results of the analysis are saved (in part because the summary is easily replicable). I have written the code such that a portion of the dates required can be returned in the summary table. The results are different if run for 2001-06-01-2001-06-05 and 2001-06-03-2001-06-04.</p>
<p><a href="#listing1">Listing 1</a> provides the specification for my package. I have only provided the one function as publicly visible because there is no need to expose the intimate operational details.</p>
<p><a href="#listing2">Listing 2</a> defines three different data types: <tt>data_value_tab</tt>, which is used exclusively for the storage of the incoming data in <tt>load_data</tt>; <tt>day_tab</tt>, which defines the daily list of values; and <tt>item_tab</tt>, which defines the list to which the linked list will be mapped. Special attention should be paid to how I use the index in <tt>day_tab</tt> later in the code: it illustrates the flexibility of the sparse index-by table.</p>
<p>I provide a simple wrapper procedure, <tt>pl</tt>, that wraps the Oracle built-in package <tt>DBMS_OUTPUT</tt> procedure <tt>PUT_LINE</tt>. This isn&#8217;t absolutely required, and other debug mechanisms can be used as desired. Following <tt>pl</tt>, there are three more private functions that are called by the implementation of <tt>process_data</tt>: <tt>load_records</tt>, <tt>split_records</tt>, and <tt>save_records</tt>.</p>
<p><tt>load_records</tt> reads the values from the <tt>DATA_VALUE</tt> table. Because I wanted this to be able to interpret partial values, I did not immediately start splitting the records into the data structures that I discovered solve the overall problem.</p>
<p><tt>split_records</tt> is the meat of the program. After determining the number of data values, it gets the first and last date as Julian day values. This conversion is significant. It gives us the number of days between the two dates (last &#8211; first + 1) and the per diem amount (amount &divide; (last &#8211; first + 1). More importantly for the <tt>day_list</tt>, it gives us a smart index for use with our index-by. The index value represents the date on which the <tt>item_list</tt> will be used. Because we may get values out of date order or where there might be gaps in the date order that would be filled by division, it allows us to fill in the blanks as we need to, not as the code forces us to.</p>
<p>Thus, for each date in the duration of the data value, we check to see if it&#8217;s in the requested boundaries. If it is, then we manage our <tt>item_list</tt>. If the date hasn&#8217;t been added yet, we know that this partial value is going to be our first entry on the <tt>item_list</tt> and we process it as such. If we find that this date does exist, then we need to see if this particular <tt>type_code</tt> has already been added to the list &#8211; and if it hasn&#8217;t, we add the value to the end of the <tt>item_list</tt> and make the required links from the previous item in the list to the current item in the list. If the <tt>type_code</tt> already exists for the date in question, then we simply add onto the existing record. In this way, we obtain a structure in memory that looks substantially like <a href="#figure5">figure 5</a> and will allow us to produce the required summary data at will, though in a given order for the day or days in question. The key act of item creation is found here:</p>
<p style="text-align: center">item_idx := NVL(item_list.LAST, 0) + 1;</p>
<p>From here, we get the last item that was created on the list (and if the list is empty, we get a NULL value that gets transformed to 0 by NVL) and add one to the item. In this way, we&#8217;re adding to the item vector incrementally, but we&#8217;re maintaining the relationship in the management of the <tt>prev_item</tt> and <tt>next_item</tt> values in the record we&#8217;re dealing with.</p>
<p>Finally, <tt>save_records</tt> walks through the <tt>day_list</tt> records (which need not be contiguous, but in the sample data are contiguous) and then follows the <tt>item_list</tt> chain for each day, saving it to the database in the <tt>DATA_OUTPUT</tt> table. This table is the summary table that I noted would be prohibitive space-wise, and the number of records produced suggests this very clearly: ten output records are created in <tt>DATA_OUTPUT</tt> for four input records. This procedure demonstrates the navigation of both non-contiguous index-by tables and the linked list that I&#8217;ve placed on top of a contiguous index-by table.</p>
<h2 id="toc-further-options">Further Options</h2>
<p>This technique could be made more programmatic by writing it in a package &#8211; encapsulating the functionality so that it appears to be an object -but each type of list would require its own package, because the details of the data can&#8217;t be generalized (as PL/SQL has no template support) even though the techniques used in this article are highly portable.</p>
<h2 id="toc-lessons-learned">Lessons Learned</h2>
<p>It&#8217;s difficult, sometimes, to think outside of the language that you&#8217;re working with. Reaching beyond the limitations of the language I was using allowed me to quickly solve the problem at hand without undertaking a change in language that would have had a prohibitive cost in time and effort. With languages like Java and C++, the option to import techniques from other languages is easier because the languages are easily extended to handle new data structures with user-defined data types, but as long as a language supports a minimum set of features (user-definable types and arrays that can be composed of user-definable types), this particular implementation could be carried to any programming language at all.</p>
<p>One of the reasons I try to stay aware of the capability and use of several programming languages is so that I have a variety of ways of looking at a problem. Because of this tendency, I was able to identify the way that I might solve this problem with the limited time available for the project. I intend to use this experience to remind me of the necessity of constantly looking elsewhere for the ideas to solve the problems at hand &#8211; and creatively applying the ideas that I find with the capabilities of the language of the problem at hand.</p>
<h2 id="toc-further-reading">Further Reading</h2>
<p>If you&#8217;re not familiar with the PL/SQL programming language and would like to read further, I heartily recommend any book by Steve Feuerstein and published by O&#8217;Reilly. In particular, <em>Programming in PL/SQL (2<sup>nd</sup> Edition)</em> and <em>Oracle Built-In Packages</em> are extremely valuable. They also have pocket guides that summarise the main points of usage that are useful.</p>
</div>
<h2 id="toc-source-listings">Source Listings</h2>
<h3 id="toc-listing-1-data-split-package-data_split_pkg-sql"><a name="listing1"></a>Listing 1: Data Split Package (data_split_pkg.sql)</h3>
<pre class="code"><em>-- Licensed under the Mozilla Public Licence 1.1</em>

<strong>CREATE OR REPLACE PACKAGE</strong> data_split <strong>AS</strong>
  info_data_split_pkg <strong>CONSTANT VARCHAR2</strong>(120) := 'Version 1.0';

  <strong>PROCEDURE</strong> process_data
    (start_date <strong>IN  DATE DEFAULT SYSDATE</strong>,
     end_date   <strong>IN  DATE DEFAULT SYSDATE</strong>,
     debug      <strong>IN  BOOLEAN DEFAULT FALSE</strong>);
<strong>END</strong> data_split;</pre>
<h3 id="toc-listing-2-data-split-package-body-data_split_pkg_body-sql"><a name="listing2"></a>Listing 2: Data Split Package Body (data_split_pkg_body.sql)</h3>
<pre class="code"><em>-- Licensed under the Mozilla Public Licence 1.1</em>

<strong>CREATE OR REPLACE PACKAGE BODY</strong> data_split <strong>AS</strong>
  info_data_split_body <strong>CONSTANT VARCHAR2</strong>(120) := 'Version 1.0';

  <strong>TYPE</strong> data_value_tab <strong>IS TABLE OF</strong> data_values%<strong>ROWTYPE</strong>
    <strong>INDEX BY BINARY_INTEGER</strong>;

  <strong>TYPE</strong> day_rec <strong>IS RECORD</strong>
    (day_date   <strong>DATE</strong>,
     item_head  <strong>BINARY_INTEGER</strong>);

  <strong>TYPE</strong> day_tab <strong>IS TABLE OF</strong> day_rec
    <strong>INDEX BY BINARY_INTEGER</strong>;

  <strong>TYPE</strong> item_rec <strong>IS RECORD</strong>
    (type_code  <strong>VARCHAR</strong>(3),
     amount     <strong>NUMBER</strong>,
     next_item  <strong>BINARY_INTEGER</strong>,
     prev_item  <strong>BINARY_INTEGER</strong>);

  <strong>TYPE</strong> item_tab <strong>IS TABLE OF</strong> item_rec
    <strong>INDEX BY BINARY_INTEGER</strong>;

  debug_on    <strong>BOOLEAN</strong> := <strong>FALSE</strong>;

  <strong>PROCEDURE</strong> pl(lo <strong>IN  VARCHAR</strong>) <strong>IS</strong>
  <strong>BEGIN</strong>
    <strong>IF</strong> (debug_on) <strong>THEN</strong>
      <strong>DBMS_OUTPUT</strong>.<strong>PUT_LINE</strong>(lo);
    <strong>END IF</strong>;
  <strong>END</strong> pl;

  <em>-- This loads the records that started, ended, were contained in, or</em>
  <em>-- contained the specified start and end date. Split records will pull</em>
  <em>-- only the pieces we need.</em>
  <strong>PROCEDURE</strong> load_records
    (date_start <strong>IN      DATE</strong>,
     date_end   <strong>IN      DATE</strong>,
     value_list <strong>IN OUT</strong>  data_value_tab) <strong>IS</strong>

    <strong>CURSOR</strong> get_values_cur
      (start_date_in  <strong>DATE</strong>,
       end_date_in    <strong>DATE</strong>) <strong>IS</strong>
      <strong>SELECT</strong> dv.type_code, <strong>TRUNC</strong>(dv.start_date) start_date,
             <strong>TRUNC</strong>(dv.end_date) end_date, dv.amount
        <strong>FROM</strong> data_values dv
       <strong>WHERE TRUNC</strong>(dv.start_date) <strong>BETWEEN</strong> start_date_in
                                      <strong>AND</strong> end_date_in
          <strong>OR</strong> start_date_in <strong>BETWEEN TRUNC</strong>(dv.start_date)
                               <strong>AND</strong> (dv.end_date)
          <strong>OR TRUNC</strong>(dv.end_date) <strong>BETWEEN</strong> start_date_in
                                    <strong>AND</strong> end_date_in
          <strong>OR</strong> end_date_in <strong>BETWEEN TRUNC</strong>(dv.start_date)
                             <strong>AND TRUNC</strong>(dv.end_date);

    value_idx   <strong>BINARY_INTEGER</strong> := 0;
  <strong>BEGIN</strong>
    <em>-- Initialise the value list.</em>
    value_list.<strong>DELETE</strong>;

    <strong>FOR</strong> gvlc <strong>IN</strong> get_values_cur(date_start, date_end)
    <strong>LOOP</strong>
      value_idx := value_idx + 1;
      value_list(value_idx) := gvlc;
      pl('#         : ' || value_idx);
      pl('type_code : ' || gvlc.type_code);
      pl('dates     : ' || gvlc.start_date ||
            ' &#8722; ' || gvlc.end_date);
      pl('amount    : ' || gvlc.amount);
    <strong>END LOOP</strong>;
  <strong>END</strong> load_records;

  <strong>PROCEDURE</strong> split_records
    (start_date <strong>IN     DATE</strong>,
     end_date   <strong>IN     DATE</strong>,
     value_list <strong>IN</strong>     data_value_tab,
     day_list   <strong>IN OUT</strong> day_tab,
     item_list  <strong>IN OUT</strong> item_tab) <strong>IS</strong>

    value_idx       <strong>BINARY_INTEGER</strong>;
    item_idx        <strong>BINARY_INTEGER</strong> := 0;

    prev_idx        <strong>BINARY_INTEGER</strong>;
    link_idx        <strong>BINARY_INTEGER</strong>;

    rec_days        <strong>PLS_INTEGER</strong>;
    rec_days_amt    <strong>NUMBER</strong>;
    first_jul_day   <strong>BINARY_INTEGER</strong>;
    last_jul_day    <strong>BINARY_INTEGER</strong>;
    test_date       <strong>DATE</strong>;

  <strong>BEGIN</strong>
    <em>-- Initialise values</em>
    day_list.<strong>DELETE</strong>;
    item_list.<strong>DELETE</strong>;

    pl('# of values: ' || value_list.<strong>COUNT</strong>);
    value_idx := value_list.<strong>FIRST</strong>;

    <strong>WHILE</strong> (value_idx <strong>IS NOT NULL</strong>)
    <strong>LOOP</strong>
      pl('Processing Value Record: ' || value_idx);

      <em>-- Get the first day and last day in Julian terms.</em>
      first_jul_day := <strong>TO_NUMBER</strong>(<strong>TO_CHAR</strong>(value_list(value_idx).start_date,
        'J'));
      last_jul_day := <strong>TO_NUMBER</strong>(<strong>TO_CHAR</strong>(value_list(value_idx).end_date,
        'J'));

      <em>-- Figure out the amount per day.</em>
      rec_days_amt := value_list(value_idx).amount /
        (last_jul_day &#8722; first_jul_day + 1);

      pl('Value Record ' || value_list(value_idx).type_code ||
         ' [' || first_jul_day || ' &#8722; ' || last_jul_day ||
         ': ' || rec_days_amt || ' per day]');

      <strong>FOR</strong> jul_idx <strong>IN</strong> first_jul_day .. last_jul_day
      <strong>LOOP</strong>
        pl('Julian: ' || jul_idx);
        test_date := <strong>TO_DATE</strong>(<strong>TO_CHAR</strong>(jul_idx), 'J');

        <em>-- Make sure that we're within the boundaries.</em>
        <strong>IF</strong> (    (test_date &gt;= start_date)
            <strong>AND</strong> (test_date &lt;= end_date)) <strong>THEN</strong>
          pl('In Date Boundaries');

          <em>-- If we are, start applying the amount per day.</em>
          <strong>IF</strong> (day_list.<strong>EXISTS</strong>(jul_idx)) <strong>THEN</strong>
            <em>-- We've found a list already extant at the</em>
            <em>-- current date. Reuse it.</em>
            pl('Day exists.');
            item_idx := day_list(jul_idx).item_head;
            prev_idx := <strong>NULL</strong>;
            link_idx := <strong>NULL</strong>;

            <em>-- Look for our type_code.</em>
            <strong>WHILE</strong> (item_idx <strong>IS NOT NULL</strong>)
            <strong>LOOP</strong>
              <strong>IF</strong> (item_list(item_idx).type_code =
                  value_list(value_idx).type_code) <strong>THEN</strong>
                <em>-- Found a matching record.</em>
                link_idx := item_idx;
                item_idx := <strong>NULL</strong>;
                pl('Matching record found at ' || item_idx);
              <strong>ELSE</strong>
                prev_idx := item_idx;
                item_idx := item_list(prev_idx).next_item;
              <strong>END IF</strong>;
            <strong>END LOOP</strong>;

            <em>-- No such type_code, add a new record.</em>
            <strong>IF</strong> (link_idx <strong>IS NULL</strong>) <strong>THEN</strong>
              item_idx := <strong>NVL</strong>(item_list. <strong>LAST</strong>, 0) + 1;
              item_list(item_idx).type_code :=
                value_list(value_idx).type_code;
              item_list(item_idx).amount := rec_days_amt;
              item_list(item_idx).prev_item := prev_idx;
              item_list(item_idx).next_item := <strong>NULL</strong>;
              item_list(prev_idx).next_item := item_idx;
              pl('New record added.');
            <strong>ELSE</strong> <em>-- We have a match: increase it by the daily amount.</em>
              item_list(link_idx).amount :=
                item_list(link_idx).amount + rec_days_amt;
              pl('Existing record increased.');
            <strong>END IF</strong>;
          <strong>ELSE</strong> <em>-- No charges yet at this date.</em>
            item_idx := <strong>NVL</strong>(item_list. <strong>LAST</strong>, 0) + 1;
            day_list(jul_idx).day_date := test_date;
            day_list(jul_idx).item_head := item_idx;
            item_list(item_idx).type_code :=
              value_list(value_idx).type_code;
            item_list(item_idx).amount := rec_days_amt;
            item_list(item_idx).prev_item := <strong>NULL</strong>;
            item_list(item_idx).next_item := <strong>NULL</strong>;
            pl('New date and record added.');
          <strong>END IF</strong>;
        <strong>END IF</strong>;
      <strong>END LOOP</strong>;

      value_idx := value_list.<strong>NEXT</strong>(value_idx);
    <strong>END LOOP</strong>;
    pl('# of days : ' || day_list.<strong>COUNT</strong>);
    pl('# of items: ' || item_list.<strong>COUNT</strong>);
  <strong>END</strong> split_records;

  <strong>PROCEDURE</strong> save_records
    (day_list   <strong>IN</strong> day_tab,
     item_list  <strong>IN</strong> item_tab) <strong>IS</strong>

    day_idx     <strong>BINARY_INTEGER</strong>;
    item_idx    <strong>BINARY_INTEGER</strong>;

  <strong>BEGIN</strong>
    pl('# of days : ' || day_list.<strong>COUNT</strong>);
    pl('# of items: ' || item_list.<strong>COUNT</strong>);
    day_idx := day_list.<strong>FIRST</strong>;

    <strong>WHILE</strong> (day_idx <strong>IS NOT NULL</strong>)
    <strong>LOOP</strong>
      pl('Processing day [' || day_idx || ', ' ||
         <strong>TO_CHAR</strong>(<strong>TO_DATE</strong>(day_idx, 'J'), 'YYYY-MM-DD') ||
         '].');
      item_idx := day_list(day_idx).item_head;
      <strong>WHILE</strong> (item_idx <strong>IS NOT NULL</strong>)
      <strong>LOOP</strong>
        pl('Item [' || item_idx || ']: [' ||
           item_list(item_idx).type_code || ': ' ||
           item_list(item_idx).amount || ']');

        <strong>INSERT</strong>
          <strong>INTO</strong> data_output(data_date, type_code, amount)
        <strong>VALUES</strong> (day_list(day_idx).day_date,
                item_list(item_idx).type_code,
                item_list(item_idx).amount);

        item_idx := item_list(item_idx).next_item;
      <strong>END LOOP</strong>;

      day_idx := day_list.<strong>NEXT</strong>(day_idx);
    <strong>END LOOP</strong>;
  <strong>END</strong> save_records;

  <strong>PROCEDURE</strong> process_data
    (start_date <strong>IN  DATE DEFAULT SYSDATE</strong>,
     end_date   <strong>IN  DATE DEFAULT SYSDATE</strong>,
     debug      <strong>IN  BOOLEAN DEFAULT FALSE</strong>) <strong>IS</strong>

    v_list  data_value_tab;
    d_list  day_tab;
    i_list  item_tab;

  <strong>BEGIN</strong>
    debug_on := debug;
    pl('Start : ' || start_date);
    pl('Stop  : ' || end_date);
    load_records(start_date, end_date, v_list);
    split_records(start_date, end_date, v_list, d_list, i_list);
    save_records(d_list, i_list);
  <strong>END</strong> process_data;
<strong>END</strong> data_split;</pre>
<h3 id="toc-listing-3-schema-data_split_tables-sql">Listing 3: Schema (data_split_tables.sql)</h3>
<pre class="code"><em>-- Licensed under the Mozilla Public Licence 1.1</em>
<strong>CREATE TABLE</strong> data_values
  (type_code  <strong>CHAR</strong>(3) <strong>CONSTRAINT</strong> nn_data_values_tc <strong>NOT NULL</strong>,
   start_date <strong>DATE    DEFAULT SYSDATE CONSTRAINT</strong> nn_data_values_sd <strong>NOT NULL</strong>,
   end_date   <strong>DATE    DEFAULT SYSDATE CONSTRAINT</strong> nn_data_values_ed <strong>NOT NULL</strong>,
   amount     <strong>NUMBER  DEFAULT</strong> 0 <strong>CONSTRAINT</strong> nn_data_values_am <strong>NOT NULL</strong>,
   <strong>PRIMARY KEY</strong> pk_data_values (type_code, start_date, end_date));

<strong>CREATE TABLE</strong> data_output
  (data_date  <strong>DATE    DEFAULT SYSDATE CONSTRAINT</strong> nn_data_output_dd <strong>NOT NULL</strong>,
   type_code  <strong>CHAR</strong>(3) <strong>CONSTRAINT</strong> nn_data_output_do <strong>NOT NULL</strong>,
   amount     <strong>NUMBER  DEFAULT</strong> 0 <strong>CONSTRAINT</strong> nn_data_output_am <strong>NOT NULL</strong>,
   <strong>PRIMARY KEY</strong> pk_data_output (data_date, type_code));

<strong>ALTER SESSION SET NLS_DATE_FORMAT</strong> = 'yyyymmdd';

<strong>INSERT</strong>
  <strong>INTO</strong> data_values(type_code, start_date, end_date, amount)
<strong>VALUES</strong> ('ABC', '20010601', '20010601', 1);

<strong>INSERT</strong>
  <strong>INTO</strong> data_values(type_code, start_date, end_date, amount)
<strong>VALUES</strong> ('DEF', '20010601', '20010605', 15);

<strong>INSERT</strong>
  <strong>INTO</strong> data_values(type_code, start_date, end_date, amount)
<strong>VALUES</strong> ('ABC', '20010601', '20010603', 3);

<strong>INSERT</strong>
  <strong>INTO</strong> data_values(type_code, start_date, end_date, amount)
<strong>VALUES</strong> ('GHI', '20010602', '20010603', 10);

<strong>COMMIT</strong>;</pre>
<h3 id="toc-listing-4-data-test_data_split-sql">Listing 4: Data (test_data_split.sql)</h3>
<pre class="code"><em>-- Licensed under the Mozilla Public Licence 1.1</em>
<strong>BEGIN</strong>
  <strong>DELETE</strong>
    <strong>FROM</strong> data_output;

  data_split.process_data(<strong>TO_DATE</strong>('20010601', 'yyyymmdd'), <strong>TO_DATE</strong>('20010605', 'yyyymmdd'), <strong>TRUE</strong>);
  data_split.process_data(<strong>TO_DATE</strong>('20010601', 'yyyymmdd'), <strong>TO_DATE</strong>('20010603', 'yyyymmdd'));

  <strong>COMMIT</strong>;
<strong>EXCEPTION</strong>
  <strong>WHEN OTHERS THEN</strong>
    <strong>DBMS_OUTPUT</strong>.<strong>PUT_LINE</strong>('CODE: ' || <strong>SQLCODE</strong>);
    <strong>DBMS_OUTPUT</strong>.<strong>PUT_LINE</strong>('MSG : ' || <strong>SQLERRM</strong>);
<strong>END</strong>;

<strong>SELECT</strong> *
  <strong>FROM</strong> data_output
 <strong>ORDER BY</strong> type_code;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2002/11/10/complex-data-structures-in-plsql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Extremely Brief Introduction to PL/SQL</title>
		<link>http://www.halostatue.ca/2002/11/10/an-extremely-brief-introduction-to-plsql/</link>
		<comments>http://www.halostatue.ca/2002/11/10/an-extremely-brief-introduction-to-plsql/#comments</comments>
		<pubDate>Sun, 10 Nov 2002 22:09:56 +0000</pubDate>
		<dc:creator>austin</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://localhost/halostatue/2002/11/10/an-extremely-brief-introduction-to-plsql/</guid>
		<description><![CDATA[PL/SQL is Oracle&#8217;s &#8220;procedural language extensions to SQL.&#8221; It is embedded into Oracle server products and client development tools like Oracle Forms or Developer/2000. It is modeled on Ada, although anyone with any familiarity with Pascal will find it easy to understand. It offers most of the features one would expect in a modern procedural [...]]]></description>
			<content:encoded><![CDATA[<p>PL/SQL is Oracle&#8217;s &#8220;procedural language extensions to SQL.&#8221; It is embedded into Oracle server products and client development tools like Oracle Forms or Developer/2000. It is modeled on Ada, although anyone with any familiarity with Pascal will find it easy to understand. It offers most of the features one would expect in a modern procedural language: modularity, loops, conditionals, exceptions, native and user-definable data types (including collection types), and native handling of SQL queries and cursors. The PL/SQL engine is responsible for memory management with no option for user defined memory management; there are no pointers or references of any sort.PL/SQL is block-oriented (all code is organized between BEGIN and END statements) and offers both anonymous blocks and named blocks, which are procedures (may not return a value) and functions (must return a value). Parameters to procedures or functions are passed by value, not by reference (PL/SQL 8 offers a NOCOPY keyword allowing pass by reference parameters). Although PL/SQL isn&#8217;t an object-oriented language, it encourages encapsulation through packages. A package is written in two pieces: the package definition that defines the prototypes of the public modules and public data object definitions, and the package body that defines the implementation of the package, including private modules, variable types, and variables.</p>
<p>PL/SQL supports exception handling in named and anonymous blocks, and allows the programmer to define exceptions and associate these with error numbers. Several of the common Oracle errors are given names, and exceptions can be defined within packages (if they are defined in the public portion of the package, then they can be referenced just as a package procedure would be referenced).</p>
<p>PL/SQL supports all of the Oracle built-in types, plus a few for PL/SQL only (BOOLEAN, PLS_INTEGER, BINARY_INTEGER, others). Complex data types can be created as records or, in PL/SQL 8, database object types. Records can be created from references to tables or as an explicit declaration. Collections can be created from native data types, database object types, or records, but may not contain (directly or indirectly) other collections. Two of the collection types (varying arrays and nested tables) are based on Oracle8 object facilities and provide the best flexibility when defined as objects in the schema, as they can provide additional capabilities with CAST … AS statements. The remaining collection type, index-by tables, offers a sparse collection, where the entries do not need to be contiguous and allow for smart indexes. (Entries that have not been set in index-by tables do not exist and have no value, not even NULL, meaning that &#8220;random&#8221; index selection should test that the value EXISTS before attempting to get a value.)</p>
<p>The performance of PL/SQL is very good on certain sets of tasks, sometimes rivalling compiled C and C++. PL/SQL performs very well on tasks that involve data manipulation, and does not perform as well as tasks that involve significant calculations. Even with these limitations, PL/SQL&#8217;s flexibility, ease of use, and portability can make it an ideal choice for wide ranges of business logic and other functionality within Oracle products.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.halostatue.ca/2002/11/10/an-extremely-brief-introduction-to-plsql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 4.750 seconds -->

