<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Thinking Digitally</title>
	
	<link>http://thinkingdigitally.com</link>
	<description>programming for the fun of it</description>
	<lastBuildDate>Sun, 28 Apr 2013 16:13:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/thinkingdigitally" /><feedburner:info uri="thinkingdigitally" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>thinkingdigitally</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Book Review: The Book of Ruby</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/J2tZO5TkA2c/</link>
		<comments>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 02:01:37 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[book review]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/?p=223</guid>
		<description><![CDATA[Last month No Starch Press released their second Ruby book ever, The Book of Ruby by Huw Collingbourne. Their first was Ruby by Example, released four years ago in 2007! The Book of Ruby is an introductory book to the Ruby programming language. The book covers all of the standard programming language basics: strings, classes, [...]]]></description>
				<content:encoded><![CDATA[<p>Last month No Starch Press released their second Ruby book ever, <a href="http://nostarch.com/boruby.htm">The Book of Ruby</a> by Huw Collingbourne. Their first was Ruby by Example, released four years ago in 2007! The Book of Ruby is an introductory book to the Ruby programming language.</p>

<p>The book covers all of the standard programming language basics: strings, classes, arrays, loops, etc. Additionally there are three chapters on more advanced subjects in Ruby: Marshal, Threads, and Dynamic Programming. Ruby on Rails is also quickly introduced in a chapter at the end of the book.</p>

<p>Each chapter includes a Digging Deeper section at the end that goes into more detail, warns about corner cases, or introduces an advanced usage. As someone who already knows Ruby these were the most interesting to read. They are placed inside of their own section to let someone who is just trying to learn Ruby know that they can safely be skipped.</p>

<p>No Starch Press is the publisher behind several fun programming books like <a href="http://nostarch.com/lisp.htm">Land of Lisp</a>, <a href="http://nostarch.com/lyah.htm">Learn You a Haskell for Great Good</a>, and the iconic <a href="http://nostarch.com/catalog/manga">Manga guides</a>. When I picked up The Book of Ruby I wasn&#8217;t expecting to encounter the second coming of <a href="http://mislav.uniqpath.com/poignant-guide/">Why&#8217;s (Poignant) Guide to Ruby</a>, but that&#8217;s what I was hoping for. Unfortunately, The Book of Ruby does not share any characteristics with that fun intro to programming Ruby and instead reads like an average technical book&#8230; dryly. On the positive side, I did find the author&#8217;s writing to be clear and easy to follow.</p>

<p>The book contains many examples but they are as contrived as possible. I understand that examples should be as simple as possible so that the reader can easily follow along but there is also a need to make the examples do interesting things to make the book more engaging.</p>

<p>Further, Collingbourne does not make an attempt to explain how Ruby is actually used &#8220;in the wild&#8221;. This is something that another Ruby author, Russ Olsen, does really well. Ruby has a lot of features so it is important to understand how Ruby programmers actually use Ruby. For instance, even though class variables are available, Ruby programmers try to never use them. This is something I would have liked to know when learning Ruby. However, instead of sharing these tidbits of information from his many years of Ruby experience, Collingbourne stays neutral and presents all of the information without including his opinions.</p>

<p>The one opinion that Collingbourne did share, is that he does not believe code style conventions are very important. This is something I can respect, and actually envy. In my own programming, I consider the time I spend to reformat my code to make it &#8220;look pretty&#8221; to be a waste. However, I still do it because it drives me crazy not to. If I could flip a switch inside my brain that would cause me to not care about code style anymore I absolutely would.</p>

<p>Overall, I feel like if this had been the first Ruby book I had picked up I would not have fallen in love with Ruby like I did. I am disappointed with No Starch Press for not upholding their unique style. The Book of Ruby does not differentiate itself enough to recommend over the other Ruby titles that are out there.</p>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/J2tZO5TkA2c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/book-review-the-book-of-ruby/</feedburner:origLink></item>
		<item>
		<title>Upgrading to RTorrent 0.8.5</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/PMvuquIvW7o/</link>
		<comments>http://thinkingdigitally.com/archive/upgrading-to-rtorrent-0-8-5/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 07:15:10 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Unix]]></category>
		<category><![CDATA[bittorrent]]></category>
		<category><![CDATA[dtach]]></category>
		<category><![CDATA[libtorrent]]></category>
		<category><![CDATA[rtorrent]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/?p=208</guid>
		<description><![CDATA[Recently I went through the process of upgrading rtorrent-0.8.2 and libtorrent-0.12.2 on my Ubuntu 9.04 box to the latest versions, rtorrent-0.8.5 and libtorrent-0.12.5. Unfortunately what should be a simple process was rather complicated because the developer has not yet updated the project&#8217;s website to reflect all of the changes that have been made to the [...]]]></description>
				<content:encoded><![CDATA[<p>Recently I went through the process of upgrading rtorrent-0.8.2 and libtorrent-0.12.2 on my Ubuntu 9.04 box to the latest versions, rtorrent-0.8.5 and libtorrent-0.12.5. Unfortunately what should be a simple process was rather complicated because the developer has not yet updated the <a href="http://libtorrent.rakshasa.no/">project&#8217;s website</a> to reflect all of the changes that have been made to the configuration options in version 0.8.4 (which was released nearly a year ago!). After dozens of Google searches I was able track down the information I needed. In addition, I have added notes on hiccups I ran into when compiling RTorrent from source and getting RTorrent to work with dtach.</p>

<p><span id="more-208"></span></p>

<h3>Compiling</h3>

<p>To compile LibTorrent I needed to install the <code>libsigc++-2.0-dev</code> package. To compile RTorrent I needed to install <code>libcurl4-openssl-dev</code>. Both can be installed via apt-get:</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;">sudo apt-get install libsigc++-2.0-dev libcurl4-openssl-dev</pre></td></tr></table></div>


<h3>Updating .rtorrent.rc</h3>

<h4>The New Ratio Syntax</h4>

<p>This actually has been documented to some extent on the <a href="http://libtorrent.rakshasa.no/wiki/RTorrentRatioHandling">RTorrentRatioHandling</a> wiki page. Unfortunately &#8220;The basics&#8221; make little sense to me. Here is what I did:</p>

<p>Remove my old schedule command to stop torrents when they reach a certain ratio:</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;">schedule = ratio,60,60,&quot;stop_on_ratio=100&quot;</pre></td></tr></table></div>


<p>And replace it with:</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;"># Enable the default ratio group.
ratio.enable=
&nbsp;
# Change the limits
ratio.min.set=100
#ratio.max.set=300
#ratio.upload.set=20M</pre></td></tr></table></div>


<p>My desired behavior is for RTorrent to close a torrent when its ratio reaches 1.0 which is why I am only setting ratio.min.set.</p>

<p>I am extremely curious why the developer decided to make the configuration command to enable ratios <code>ratio.enable=</code>. The equals sign on the end of the line makes the option feel very incomplete and does not make sense.</p>

<h4>Deprecated on_&#42; commands</h4>

<p>All of the on_* commands are now deprecated.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> This includes on_start, on_stop, on_finished, and on_erase. I use an on_finished command to move finished torrents to a separate directory which had to be changed.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;"># deprecated on_finished command
# on_finished = move_complete,&quot;d.set_directory=~/torrents/finished/ ;execute=mv,-u,$d.get_base_path=,~/torrents/finished/&quot;
&nbsp;
# Equivalent on_finished for rtorrent &gt; 0.8.4
system.method.set_key = event.download.finished,move_complete,&quot;d.set_directory=~/torrents/finished/ ;execute=mv,-u,$d.get_base_path=,~/torrents/finished/&quot;</pre></td></tr></table></div>


<h3>DTach</h3>

<p>On a whim I decided to switch to running RTorrent with <a href="http://dtach.sourceforge.net/">dtach</a> instead of inside GNU Screen. My hope is that dtach will perform a little better. Unfortunately when I opened RTorrent with dtach my arrow keys changed my download threshold instead of navigating the list of torrents. A fix that I found is to specify <code>TERM=linux</code> when launching dtach.<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">env</span> <span style="color: #007800;">TERM</span>=linux dtach <span style="color: #660033;">-c</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>rtorrent.dtach rtorrent</pre></td></tr></table></div>


<p>Once again I find it why this works to be a mystery but no explanation was given.</p>

<h3>Rant</h3>

<p>I have a lot of respect for the creator of RTorrent/LibTorrent. He has created an excellent Bittorrent client and backend that I have been happily been using for a couple years. However, I think it is very poor form that he released new updates that change the configuration interface without properly documenting the upgrade path on the website. This was frustrating enough that I tried to update the LibTorrent trac but public accounts are not allowed, blocking my attempt to help.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p><a href="http://rakshasa.no/pipermail/libtorrent-devel/2009-June/002176.html">Deprecated on_&#42; commands</a>&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p><a href="http://libtorrent.rakshasa.no/ticket/192">DTach TERM=linux fix</a>&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/PMvuquIvW7o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/upgrading-to-rtorrent-0-8-5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/upgrading-to-rtorrent-0-8-5/</feedburner:origLink></item>
		<item>
		<title>Rails Rumble ’09: Grocery Tracker</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/dduB9f2EX_Y/</link>
		<comments>http://thinkingdigitally.com/archive/grocery-tracker/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 09:34:11 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[grocery tracker]]></category>
		<category><![CDATA[rails rumble]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/?p=185</guid>
		<description><![CDATA[Update: The Grocery Tracker website is no longer online. This year I once again participated in the RailsRumble competition with the goal to build a Rails app in 48 hours. My amazing teammates Arya Asemanfar, Gary Tsang, and Alex Le and I worked together tirelessly to build an application for tracking grocery purchases. The result [...]]]></description>
				<content:encoded><![CDATA[<p><strong>Update</strong>: The Grocery Tracker website is no longer online.</p>

<p>This year I once again participated in the <a href="http://r09.railsrumble.com/">RailsRumble</a> competition with the goal to build a Rails app in 48 hours. My amazing teammates <a href="http://twitter.com/aryaasemanfar">Arya Asemanfar</a>, <a href="http://twitter.com/garru">Gary Tsang</a>, and <a href="http://twitter.com/alexcharlie">Alex Le</a> and I worked together tirelessly to build an application for tracking grocery purchases. The result is <a href="http://grocerytracker.r09.railsrumble.com/">Grocery Tracker</a>.</p>

<h2>Grocery Tracker</h2>

<div style="text-align:center; padding:10px 0;">
  <a href="http://grocerytracker.r09.railsrumble.com/"><img src="http://thinkingdigitally.com/wp-content/uploads/2009/08/grocery-tracker-splash.png" alt="grocery tracker landing page screenshot"></a>
</div>

<p>The objective of Grocery Tracker is to make it really easy to visualize how much you are spending on groceries and how your buying habits are changing. For me, it is interesting to see what percent of my grocery purchases are going towards &#8220;Snacks &amp; Candy&#8221; as well as my historical spending in that category. Grocery Tracker allows me to quickly answer questions like &#8220;Am I spending less on snacks now than I was 3 months ago?&#8221;.</p>

<p><span id="more-185"></span></p>

<h4>Start Tracking!</h4>

<p>To signup, click &#8220;Get Started&#8221; on the homepage. Fill out the (poorly styled) registration form to create an account and you will be automatically logged in.
<img src="http://thinkingdigitally.com/wp-content/uploads/2009/08/sandwich-list.png" class="inline-right" alt="sandwich grocery list"></p>

<p>When you login for the first time we create two sample grocery lists for you. The first one has all the ingredients to make a wicked sandwich and the second one is blank. Click on the blank list and play around with entering new items to the list.</p>

<p>After you have entered some data click the &#8220;Reports&#8221; tab at the top to view graphs of your purchases. The first graph on the reports dashboard is a graph of total spending over time and the smaller graphs beneath display a breakdown of spending by category. The default view is to view a breakdown by day. You may find it more useful to break down your purchases by week, month, and eventually year. To do so, click the respective links in the top right of the page.</p>

<div style="text-align:center">
<img src="http://thinkingdigitally.com/wp-content/uploads/2009/08/deli-graph.png"  alt="graph of deli category">
</div>

<h4>iPhone Integration</h4>

<p>Grocery Tracker has a minimal iPhone interface for viewing your grocery lists from your phone. This is ideal for reviewing your grocery lists when shopping at the grocery store. We hope to build out the iPhone functionality more in the future.</p>

<h4>Alpha, Beta, Gamma?</h4>

<p>Keep in mind when using Grocery Tracker that it was developed entirely in 48 hours. Once the deadline passed we were no longer allowed to make changes. There are a few known bugs in the software that we want desperately to fix but are barred from doing so by the rules of the competition. In particular, logging in and out of the application is really rough and you should anticipate strange behavior to crop up.</p>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/dduB9f2EX_Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/grocery-tracker/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/grocery-tracker/</feedburner:origLink></item>
		<item>
		<title>Capturing Output from PUTS in Ruby</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/6UT0jm5tlwQ/</link>
		<comments>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 08:36:13 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[mocha]]></category>
		<category><![CDATA[puts]]></category>
		<category><![CDATA[redirect output]]></category>
		<category><![CDATA[simplesem]]></category>
		<category><![CDATA[zentest]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/</guid>
		<description><![CDATA[When writing unit tests for my simplesem interpreter, one test in particular was problematic. In simplesem, the set write instruction prints output to the screen. // place Hello World! on the 'write' buffer set write, &#34;Hello World!&#34; Internally, the interpreter is just passing the second parameter, &#8220;Hello World!&#8221;, to the puts method in Ruby. This [...]]]></description>
				<content:encoded><![CDATA[<p>When writing unit tests for my <a href="http://thinkingdigitally.com/archive/a-simplesem-interpreter/">simplesem interpreter</a>, one test in particular was problematic. In simplesem, the <code>set write</code> instruction prints output to the screen.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;">// place Hello World! on the 'write' buffer
set write, &quot;Hello World!&quot;</pre></td></tr></table></div>


<p>Internally, the interpreter is just passing the second parameter, &#8220;Hello World!&#8221;, to the <code>puts</code> method in Ruby. This makes it difficult to use traditional test/unit assertions to check that the simplesem instruction is working.</p>

<p>I eventually found two solutions for this. The first, suggested by <a href="http://flouri.sh/">David Stevenson</a> at Pivotal Labs, is to use <a href="http://github.com/floehopper/mocha/">mocha</a> to check that <code>puts</code> was called on the object.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/unit'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mocha'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
    parser.<span style="color:#9900CC;">expects</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#CC0066; font-weight:bold;">puts</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Hello World!&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>


<p>This solution is fine for most situations; Mocha will throw an exception if <code>puts</code> is not called. However in my case, it was unsuitable because <code>puts</code> was not being called on the SimpleSemParser object but instead on a <a href="http://treetop.rubyforge.org/">Treetop</a> syntax node that I did not easily have access to within the unit test.</p>

<p>I knew that if I could capture the output from the <code>puts</code> method into a variable I would be able write the test using a standard <code>assert_equal</code>. After some googling I discovered that this functionality is built into the <a href="http://www.zenspider.com/ZSS/Products/ZenTest/index.html">ZenTest</a> gem. After rewriting the test looked like this.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test/zentest_assertions'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    out, err = util_capture <span style="color:#9966CC; font-weight:bold;">do</span> 
      parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
      parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    assert_equal <span style="color:#996600;">&quot;Hello World!<span style="color:#000099;">\n</span>&quot;</span>, out.<span style="color:#CC0066; font-weight:bold;">string</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>


<p>This works great. However, should we decided that we do not want to use an external gem, with a little effort we can bypass ZenTest and implement <code>util_capture</code> ourselves.</p>

<p><span id="more-165"></span></p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'stringio'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#CC00FF; font-weight:bold;">Kernel</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> capture_stdout
    out = <span style="color:#CC00FF; font-weight:bold;">StringIO</span>.<span style="color:#9900CC;">new</span>
    <span style="color:#ff6633; font-weight:bold;">$stdout</span> = out
    <span style="color:#9966CC; font-weight:bold;">yield</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> out
  <span style="color:#9966CC; font-weight:bold;">ensure</span>
    <span style="color:#ff6633; font-weight:bold;">$stdout</span> = STDOUT
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>


<p>Done! We extended the Kernel module with a method called <code>capture_stdout</code><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. <code>capture_stdout</code> works by redirecting <code>$stdout</code> to an instance of <a href="http://www.ruby-doc.org/core/classes/StringIO.html">StringIO</a>. StringIO has all of the <a href="http://www.ruby-doc.org/core/classes/IO.html">IO</a> methods, but acts on a string instead of a file. After changing <code>$stdout</code> we yield to let the caller generate output. Once the yield is finished, we return the StringIO instance and add an ensure to guarantee that <code>$stdout</code> is reset to its default value. Adding <code>capture_stdout</code> to the Kernel module has the effect of giving <code>capture_stdout</code> a global scope so that it can be used anywhere.</p>

<p>With the exception that we that we renamed the method to <code>capture_stdout</code>, and are not returning <code>$stderr</code>, the unit test has not changed from the ZenTest version.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SimpleSemParserTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">Test::Unit::TestCase</span></span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> test_set_stmt_write
    out = capture_stdout <span style="color:#9966CC; font-weight:bold;">do</span> 
      parser = SimpleSemParser.<span style="color:#9900CC;">new</span>
      parser.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'set write, &quot;Hello World!&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">execute</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    assert_equal <span style="color:#996600;">&quot;Hello World!<span style="color:#000099;">\n</span>&quot;</span>, out.<span style="color:#CC0066; font-weight:bold;">string</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>


<p>We end with a clean, very readable way to test Ruby methods that generate output without using any libraries.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>I prefer this name over &#8220;util_capture&#8221;.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/6UT0jm5tlwQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/</feedburner:origLink></item>
		<item>
		<title>Automate Updating Your Git Repositories</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/M-TTKCKO7wU/</link>
		<comments>http://thinkingdigitally.com/archive/automate-updating-your-git-repositories/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 22:21:20 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Scripts]]></category>
		<category><![CDATA[automate]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[textmate]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/automate-updating-your-git-repositories/</guid>
		<description><![CDATA[I have a half dozen TextMate bundles that I am grabbing the latest versions from GitHub instead of from the main TextMate subversion repository. For a long time I have been updating each of the bundles&#8217; Git repositories by cd&#8217;ing into each directory and running git pull. Doing this over and over became silly and [...]]]></description>
				<content:encoded><![CDATA[<p>I have a half dozen TextMate bundles that I am grabbing the latest versions from GitHub instead of from the main TextMate subversion repository. For a long time I have been updating each of the bundles&#8217; Git repositories by cd&#8217;ing into each directory and running <code>git pull</code>. Doing this over and over became silly and I was annoyed from doing all that typing.</p>

<p>Today, I finally wrote a basic bash script that automates updating each of the repositories. Sometimes it is surprising how simple an automated solution turns out to be.</p>

<script src="http://gist.github.com/75456.js"></script>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/M-TTKCKO7wU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/automate-updating-your-git-repositories/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/automate-updating-your-git-repositories/</feedburner:origLink></item>
		<item>
		<title>A SIMPLESEM Interpreter</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/VCsaf6542qI/</link>
		<comments>http://thinkingdigitally.com/archive/a-simplesem-interpreter/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 09:35:24 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[cs141]]></category>
		<category><![CDATA[simplesem]]></category>
		<category><![CDATA[treetop]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/a-simplesem-interpreter/</guid>
		<description><![CDATA[In my Programming Languages course, taught by Shannon Tauro we have been using a fake assembly language of sorts called SIMPLESEM to gain experience translating the semantics of a high level programming language, to a simple processor. Since SIMPLESEM is a made up language that was created just for our textbook, there was no way [...]]]></description>
				<content:encoded><![CDATA[<p>In my <a href="https://eee.uci.edu/09w/16250/">Programming Languages course</a>, taught by <a href="http://www.ics.uci.edu/~stauro/">Shannon Tauro</a> we have been using a fake assembly language of sorts called SIMPLESEM to gain experience translating the semantics of a high level programming language, to a simple processor.</p>

<p>Since SIMPLESEM is a made up language that was created just for our textbook, there was no way for me to execute the SIMPLESEM programs that I was writing for the homework assignments. This was annoying because SIMPLESEM is a low level language which makes it hard to notice mistakes. Of course, it is very easy to make a mistake any time you are programming but it is even harder to catch those mistakes if you are working at close to assembly level.</p>

<p>As a fun exercise I implemented an <a href="http://github.com/robolson/simplesem">interpreter for SIMPLESEM</a> using Ruby and published it as a RubyGem. Fortunately, I choose to use Nathan Sobo&#8217;s <a href="http://treetop.rubyforge.org/">Treetop</a> gem to aide in the development. Using Treetop, I wrote a parsing expression grammar to parse SIMPLESEM commands. This resulted in my SIMPLESEM interpreter being a lot more flexible than I had originally anticipated. After I familiarized myself with the basics of writing Treetop grammars I found it very easy to make changes to my grammar definitions to add language features one by one.</p>

<p><span id="more-158"></span>
Installing the SIMPLESEM interpreter should be easy if you are on Linux or OS X, and possible if you are on Windows. The program is packaged as a rubygem. *nix folks should have rubygems packaged with their system. Windows users should visit the  <a href="http://www.rubygems.org/read/chapter/3">RubyGems</a> page to get running. Once you are setup with RubyGems, install the simplesem gem from Gemcutter:</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;">$ sudo gem install simplesem --source http://gemcutter.org</pre></td></tr></table></div>


<p>The gem installs a command called <code>simplesem</code>. To test it out download this <a href="http://github.com/robolson/simplesem/blob?path[]=sample_programs&amp;path[]=hello-world.txt&amp;raw=true">sample SIMPLESEM program</a> that prints &#8220;hello world!&#8221; five times. Run it by passing the name of the file as an argument to the command.</p>


<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;">$ simplesem hello-world.txt
hello world!
hello world!
hello world!
hello world!
hello world!</pre></td></tr></table></div>


<p>You can view other sample SIMPLESEM programs <a href="http://github.com/robolson/simplesem/tree/master/sample_programs">here</a>. To learn more about SIMPLESEM or the interpreter check out the <a href="http://github.com/robolson/simplesem/blob/master/README.textile">README</a>.</p>

<div class="resource-list"><dl>

<dt><a href="http://github.com/robolson/simplesem">
<img src="/images/icons/application_x-ruby.png" alt="SIMPLESEM Interpreter on GitHub" />
SIMPLESEM Interpreter</a></dt>
<dd>Source code available on GitHub.</dd>

</dl></div>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/VCsaf6542qI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/a-simplesem-interpreter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/a-simplesem-interpreter/</feedburner:origLink></item>
		<item>
		<title>Since When Did A Nice Case Cost $300?</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/I8crI9AHS7A/</link>
		<comments>http://thinkingdigitally.com/archive/since-when-did-a-nice-case-cost-300/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 00:52:34 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Macbook]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/since-when-did-a-nice-case-cost-300/</guid>
		<description><![CDATA[This jumped out at me while browsing the Apple Store today. The two 13&#8243; Macbooks are practically identical on the inside. The new aluminum version&#8217;s hard drive is 40GB larger and it contains the newer DDR3 memory. However they have the same video card and the same CPU. These changes may seem of consequence, but [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://thinkingdigitally.com/wp-content/uploads/2009/01/macbook-comparison-orig.png"><img src="http://thinkingdigitally.com/wp-content/uploads/2009/01/macbook-comparison.png" style="border:none" width="490" height="236" alt="feature comparison new aluminum macbook with old white macbook" /></a></p>

<p>This jumped out at me while browsing the Apple Store today. The two 13&#8243; Macbooks are practically identical on the inside. The new aluminum version&#8217;s hard drive is 40GB larger and it contains the newer DDR3 memory. However they have the same video card and the same CPU. These changes may seem of consequence, but with the falling price of memory components Apple is likely paying the same price or less for the DDR3 memory and 160GB hard drive than they were for the corresponding parts in the white Macbook a year ago. Making the internal enhancements essentially a free upgrade for Apple.</p>

<p>All that remains is the case. Which means buyers are paying $300 for the upgrade from plastic to aluminum. That unibody case is nice but that is outrageous! It is easy to see where Apple&#8217;s high profit margins are. And I thought it was bad when they put a $150 premium on the black macbook casing two years ago.</p>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/I8crI9AHS7A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/since-when-did-a-nice-case-cost-300/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/since-when-did-a-nice-case-cost-300/</feedburner:origLink></item>
		<item>
		<title>The Case For Replacing Java With Python In Education</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/qZbT3noYEnA/</link>
		<comments>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 21:56:26 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[School]]></category>
		<category><![CDATA[computer science]]></category>
		<category><![CDATA[CS Education]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/</guid>
		<description><![CDATA[Around 2003 all of the colleges and high schools in the United States switched from teaching Computer Science courses in C++ to teaching them in Java. The intention was to make it easier for students to pick up programming. Schools were finding that many students were struggling to cope with low level tasks in C++ [...]]]></description>
				<content:encoded><![CDATA[<p>Around 2003 all of the colleges and high schools in the United States switched from teaching Computer Science courses in C++ to teaching them in Java. The intention was to make it easier for students to pick up programming. Schools were finding that many students were struggling to cope with low level tasks in C++ like manual memory management and pointer references. Instead of learning algorithms, data structures and object oriented programming, students were stuck for hours trying to track down incorrect pointer references.</p>

<p>About four years after the education system made the switch to Java from C++, the whole software industry started complaining about the degrading quality of the Computer Science graduates in the US; which is a <a href="http://thinkingdigitally.com/archive/what-if-i-went-to-a-java-school-joel/">topic I explored recently</a>. Ultimately, schools have made the switch away from C++, and they are unlikely to go back, nor do I think they should. Instead, what I want to discuss is why did we have to replace C++ with <em>Java</em>? I can see that at the time, it may have seemed the obvious choice, but looking around the language landscape now there are several choices that I think are better suited for the task. Namely, Python.</p>

<h3>Java > Python How???</h3>

<p>First, I want to really think about what advantage does learning programming with Java have over using a modern scripting language like Python? Python equally hides the things that make programming in C++ laborious and has many of the nice features that the JVM provides like garbage collection, unicode strings, and threads. The difference is Java is miserable for web programming (Java EE) and equally overly complex for building GUIs (Swing). As a scripting language, Python is far easier to pick and learn.</p>

<h3>What CS students would lose from switching from Java to Python</h3>

<ul>
<li><strong>Static Typing</strong> &#8211; The difference between an Integer and a Float is harder to understand when you do not have to declare variable types.</li>
<li><strong>Compilation</strong> &#8211; In my opinion this is not a big deal. They are still going to learn how to debug runtime errors which is where the substance is. Advanced IDEs like Eclipse are making dealing with compiler errors almost a thing of the past in Java. Additionally, the upper division compilers class will still be there to teach them the ins and outs of compilers.</li>
<li><strong>Performance</strong> &#8211; This is a moot point. I only put it down because it is what most people think of first but very rarely do the projects assigned in a classroom require serious computation. I would also wager that even the ones that do can be solved in a satisfactory manor with Python. If anything it will force students to be more creative about their solutions instead of just relying on brute force.</li>
</ul>

<h3>What CS students will gain from switching from Java to Python</h3>

<ul>
<li><strong>Dynamic Typing</strong> &#8211; There are tradeoffs to both approaches but as nearly everyone who programs dynamically typed language for a while finds out that the type safety provided by static typing is unnecessary and more often gets in your way than it helps you (ex. Casting).</li>
<li><strong>Interpretation</strong> &#8211; Becoming familiar with interpretation is just as important as compilation. Interpretation opens several doors for you when programming and is becoming more common. In addition it gives you helpful tools like an interactive console.</li>
</ul>

<p>Overall, there is no big loss in Computer Science concepts when moving from Java to Python like there was when we moved away from C++.  You trade static typing for dynamic typing and compilation for interpretation but everything else is just about the same and you gain Python&#8217;s simplicity.</p>

<p>One of the real problems with Java is that many students do not like to use it when programming for fun. Since the majority of students only become competent in Java, they only code they write is for their homework assignments. These are type A CS students. There is a second, type B, group of CS students. Type B students pick up another language like PHP, Python, Ruby, Clojure, etc. and are ones who spend time coding and creating cool things outside of their schoolwork. These students find programming on the side to be the most enriching and also the most educational. Employers often cite type B students, the self starters, as the ones they are most interested in hiring. If the only programming a student does while attending school is for their class projects, it is more than likely that they will continue this practice once leaving school, only writing code for their job. By making the switch away from Java in education, more type B CS students would emerge from American universities; enormously benefiting the software industry.</p>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/qZbT3noYEnA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/the-case-for-replacing-java-with-python-in-education/</feedburner:origLink></item>
		<item>
		<title>New Year’s Resolutions for 2009</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/ZvUNBBGZoj0/</link>
		<comments>http://thinkingdigitally.com/archive/new-years-resolutions-for-2009/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 02:44:10 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[new year's resolutions]]></category>
		<category><![CDATA[self-improvement]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/new-years-resolutions-for-2009/</guid>
		<description><![CDATA[I realize that it is about a week late to be posting New Year&#8217;s Resolutions but I figure better late than never. My resolutions for 2009: Take on fewer projects. I have a tendency of getting involved in just about everything. Too often I eagerly say &#8220;Yes&#8221; to a for-fun project, contract, or job without [...]]]></description>
				<content:encoded><![CDATA[<p>I realize that it is about a week late to be posting New Year&#8217;s Resolutions but I figure better late than never.</p>

<p>My resolutions for 2009:</p>

<ol>
<li><p><strong>Take on fewer projects.</strong> I have a tendency of getting involved in just about everything. Too often I eagerly say &#8220;Yes&#8221; to a for-fun project, contract, or job without really thinking about whether I have the necessary amount of time to devote to the project to make it a success. For a few months I need to instantiate a &#8220;project-freeze&#8221; until I can bring some closure to the myriad of things currently clogging up my to-do list.</p></li>
<li><p><strong>Look at where I am spending my time and decide what is truly important. Stop spending my time on the things I think are important but really aren&#8217;t.</strong> I just finished reading the book <a href="http://www.amazon.com/Predictably-Irrational-Hidden-Forces-Decisions/dp/006135323X?tag=zotrails-20">Predictably Irrational by Dan Ariely</a>. The eighth chapter is titled &#8220;Keeping Doors Open: Why Options Distract Us from Our Main Objective&#8221;. In the chapter Ariely explains how people have this irrational behavior to keep as many options available to them as we can. Even though this behavior diverts our energy and commitment away from the doors that should be left open and that we are better off when we close as many doors as we can and focus on the ones that are the most valuable. For most people, including myself, deciding which doors are the most beneficial is a not easy because, as Ariely states, some doors are tied to my dreams or contain the promise of leading to a better career. Therefore I need to be rigid in closing doors if I really want to focus on what is important.</p></li>
<li><p><strong>Get better at finishing what I start.</strong> Since I have been starting too many projects in the last year and getting involved with too many things, I have fallen into a really bad spell of not finishing many of the various projects that I start. By spreading myself too thin I have become ineffective as a programmer. But I believe that if I am able to stick to my first two resolutions, then finishing the things I start will follow.</p></li>
<li><p><strong>Exercise with Wii Fit on a regular basis for the entire year.</strong> I am not overweight or out of shape so when I say that I need to exercise it is not to lose weight. Instead I want to see how my body will improve if I do exercise regularly. And I say exercise with Wii Fit because that is the only method of exercise that is convenient enough (I don&#8217;t have to leave my apartment) for me to do it for a prolonged period.</p></li>
</ol>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/ZvUNBBGZoj0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/new-years-resolutions-for-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/new-years-resolutions-for-2009/</feedburner:origLink></item>
		<item>
		<title>Measuring the Efficiency of Email</title>
		<link>http://feedproxy.google.com/~r/thinkingdigitally/~3/LCiXEjdhzmw/</link>
		<comments>http://thinkingdigitally.com/archive/measuring-the-efficiency-of-email/#comments</comments>
		<pubDate>Fri, 26 Dec 2008 08:11:54 +0000</pubDate>
		<dc:creator>Rob Olson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[RescueTime]]></category>

		<guid isPermaLink="false">http://thinkingdigitally.com/archive/measuring-the-efficiency-of-email/</guid>
		<description><![CDATA[Since July I have been using an application called RescueTime to track my computer usage habits. It records how much time I spend using each application and visiting websites. This information is useful for me to monitor how much time I am blowing on Twitter and how much of my 8+ hour work day (when [...]]]></description>
				<content:encoded><![CDATA[<div style="text-align:center"><img src="http://thinkingdigitally.com/wp-content/uploads/2008/12/death-by-email.gif" style="margin-bottom:10px" alt="Death by Email"></div>

<p>Since July I have been using an application called <a href="http://www.rescuetime.com">RescueTime</a> to track my computer usage habits. It records how much time I spend using each application and visiting websites. This information is useful for me to monitor how much time I am blowing on Twitter and how much of my 8+ hour work day (when I was working) I was actually spending on programming.</p>

<p>One of the features of RescueTime is that it lets me set efficiency values between -2 and +2 for my Apps. So for example, I marked TextMate as being +2 efficiency, Adium and Skype as -1 efficiency, and Facebook as -2 efficiency. Then RescueTime aggregates all of my usage data, and generates an overall Efficiency Score based on the efficiency values I assigned. If my overall efficiency score is above 0 than I have been productive, if it is below 0 than I have been generally unproductive.</p>

<p>So far I have assigned all of my &#8220;most used&#8221; applications and websites and efficiency value&#8230;except for my email client, <a href="http://mailplaneapp.com/">MailPlane</a>. When it comes to rating the efficiency of my time spent writing and reading emails I am conflicted. While email is necessary to getting many things done, it is a lot of time not spent working towards my main objective which is programming.</p>

<p>Writing emails is what particularly kills me as it consumes far more time than reading emails does. Writing good emails that provide actual value is difficult and I can easily spend 20 minutes writing and rewording an important email. If the amount of email I dealt with was low this would obviously be less of an issue but I estimate that I send an average of 40 emails every week, half of them being during the weekend.</p>

<p>I know that this amount of email writing is nothing compared to what many people deal with but for a college student who writes code on the side, writing 40 emails every week is a significant time sink. According to RescueTime, I have spent 110 hours using my email client since RescueTime started monitoring on July 21st. Making it my most popular application (Adium is second, followed by TextMate).</p>

<p><img src="http://thinkingdigitally.com/wp-content/uploads/2008/12/email-a-necessary-evil.png" class="inline-left" alt="Email, A Necessary Evil">
So the problem I am left with is, how do I rate the efficiency of a necessary evil? I can not stop writing email because then I would not be fulfilling my other responsibilities, like my role as ACM President at UCI. If I give MailPlane an efficiency rating of +1 than time spent writing emails is going to boost my overall efficiency score so that even if I&#8217;m not writing any code RescueTime is still going to tell me I have been efficiently using my time. If I rate it negatively and give MailPlane a rating of -1 than I am never going to be able to dig myself out from negative territory on the overall efficiency scale. I already have Adium, VLC, and Facebook bringing me down enough as it is.</p>

<p>In the end, I feel that 0 is the most appropriate efficiency rating for a necessary evil. Thus it does not hurt you to be doing it but it does not help you either. I think a good solution would be for RescueTime to add a goal type where I can specify that on any given day, my goal is to use TextMate for longer than I use MailPlane. RescueTime deals in tags and categories so really it would be to use things tagged &#8220;dev&#8221; for longer than things in the &#8220;Comm (Email)&#8221; category but it is the same principle. That way I can challenge myself to spend more time writing code than emailing without having all my other activities interfere.</p>
<img src="http://feeds.feedburner.com/~r/thinkingdigitally/~4/LCiXEjdhzmw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thinkingdigitally.com/archive/measuring-the-efficiency-of-email/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://thinkingdigitally.com/archive/measuring-the-efficiency-of-email/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.381 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-06-12 10:02:41 --><!-- Compression = gzip -->
