<?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>tadhg.com &#187; coding</title>
	<atom:link href="http://tadhg.com/wp/tag/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://tadhg.com/wp</link>
	<description>Wherein some things Tadhg are discussed</description>
	<lastBuildDate>Fri, 03 Sep 2010 06:52:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Metaweb Acquired by Google</title>
		<link>http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/</link>
		<comments>http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/#comments</comments>
		<pubDate>Sat, 17 Jul 2010 06:57:46 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[organization]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[semantic-web]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=3100</guid>
		<description><![CDATA[The official announcements are out, and my former employer Metaweb no longer exists. I’m happy that the ideas, and most of the people, have found a home, but it feels strange that the company is no longer a distinct entity. In many ways it makes a lot of sense for Google to end up owning [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://tadhg.com/wp/2010/07/13/consumers-lament/" title="Consumer’s Lament" >official</a> <a href="http://blog.freebase.com/2010/07/16/metaweb-joins-google/" title="Metaweb Joins Google" >announcements</a> are out, and my former employer Metaweb no longer exists. I’m happy that the ideas, and most of the people, have found a home, but it feels strange that the company is no longer a distinct entity. In many ways it makes a lot of sense for Google to end up owning them, and I hope the former-Metaweb-now-Google employees prosper.<br />
<span id="more-3100"></span><br />
Many of them are good friends of mine, and that in itself is significant. I was there for under two years; the proportion of people that I get on well with or admire (or both) there was very high. For the most part they did an excellent job of hiring, and of keeping the company culture coherent and inspiring.</p>
<p>My time there was important professionally as well as rewarding personally. It’s where I first really dug into Python, and through learning Python and working there I feel as if I embarked on a process that has seen me gain quite a few levels in the Software Engineer class. The exposure there to extremely skilled and accomplished people certainly helped me a great deal.</p>
<p>Those aren’t the only reasons I wish them all well. I still have the classic geek’s desire for a more rationally structured world, and the classic geek’s optimism that thinking about and organizing things in better ways can help bring that rational structure closer. Those combine to make me want to see realized the three major possibilities (in my view) that the Metaweb project presents:</p>
<ul>
<li>A canonical namespace/“topic DNS” for, well, everything, so that words can easily be annotated (and analyzed, and manipulated) with pointers that make their actual meaning clear.
</li>
<li>A public repository of schemas for more or less everything, so that individual groups or organizations could simply use and build upon those, rather than separately creating their own—standardization in that arena would vastly improve the user experience for innumerable things online (especially if you’re <a href="http://googleblog.blogspot.com/2010/07/deeper-understanding-with-metaweb.html" title="Deeper Understanding with Metaweb" >as picky as I am</a>) and, not inconsequentially from my perspective, also eliminate all the work that programmers do reinventing the wheel with independently-developed schemas for common things.
</li>
<li>A public repository of all the data for all the things covered by the first two points. This is what most people probably think the key point of Metaweb/Freebase is, and while it’s certainly an amazing and lofty goal, it’s not more important than the first two, both of which could be truly revolutionary if done on a large enough scale (and adopted by sufficient numbers).
</li>
</ul>
<p>So, too all those moving to Google: best of luck, and I hope you succeed at those three goals!</p>
<p>To all those who have contributed, in ways large or small, to the project formerly known as Metaweb: well done, you’ve helped make something of potentially great importance, and I have no doubt that at some point the ideas you’ve helped develop will be extremely influential, and possibly ubiquitous. To even get this far towards such an outcome is no small achievement.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/database/" rel="tag">database</a>, <a href="http://tadhg.com/wp/tag/organization/" rel="tag">organization</a>, <a href="http://tadhg.com/wp/tag/personal/" rel="tag">personal</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a>, <a href="http://tadhg.com/wp/tag/semantic-web/" rel="tag">semantic-web</a>, <a href="http://tadhg.com/wp/tag/work/" rel="tag">work</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2008/04/29/literary-awards-in-freebase/">Literary Awards in Freebase</a> <span class="related-post-date timestamp">Tue 29 Apr 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/03/10/data-fever/">Data Fever</a> <span class="related-post-date timestamp">Mon 10 Mar 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/03/06/freebasin/">Freebasin'</a> <span class="related-post-date timestamp">Thu 06 Mar 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/12/31/crossfit-and-coding-and-meat/">CrossFit and Coding (and Meat)</a> <span class="related-post-date timestamp">Thu 31 Dec 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/28/better-rest-wordpress-pipeline/">Better reST–WordPress Pipeline</a> <span class="related-post-date timestamp">Tue 28 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/14/blog-workflow-with-restructuredtext/">Blog Workflow with reStructuredText</a> <span class="related-post-date timestamp">Tue 14 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/02/24/that-pesky-apostrophe/">That Pesky Apostrophe</a> <span class="related-post-date timestamp">Sun 24 Feb 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/01/20/some-project-status/">Some Project Status</a> <span class="related-post-date timestamp">Sun 20 Jan 2008</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit Testing as Game</title>
		<link>http://tadhg.com/wp/2010/07/15/unit-testing-as-game/</link>
		<comments>http://tadhg.com/wp/2010/07/15/unit-testing-as-game/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 06:23:43 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[flow]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[psychology]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=3097</guid>
		<description><![CDATA[One of the great things about unit testing is that you can get into a game-like mode where you make incremental but measurable progress—“flow”, basically—but what if it’s just not similar enough to a game for you?
Install Unit Testing Achievements, a Python package that works with nose, unittest, and Django. Somewhat crazy, definitely hilarious. Some [...]]]></description>
			<content:encoded><![CDATA[<p>One of the great things about unit testing is that you can get into a game-like mode where you make incremental but measurable progress—<a href="http://tadhg.com/wp/2006/03/11/consciousness-versus-entropy/" title="Consciousness Versus Entropy" >“flow”, basically</a>—but what if it’s just not similar enough to a game for you?</p>
<p>Install <a href="http://exogen.github.com/nose-achievements/" title="Unit Testing Achievements" >Unit Testing Achievements</a>, a Python package that works with nose, unittest, and Django. Somewhat crazy, definitely hilarious. Some of the achievements themselves are excellent, such as <strong>My God, It’s Full of Dots</strong>: The suite has at least 2,001 passing tests.</p>
<p>Sadly not yet working is another one I like, <strong>Heisenbug</strong>: Make a passing suite fail without changing anything.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/flow/" rel="tag">flow</a>, <a href="http://tadhg.com/wp/tag/humor/" rel="tag">humor</a>, <a href="http://tadhg.com/wp/tag/psychology/" rel="tag">psychology</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/06/11/the-platform-of-the-maine-republican-party/">The Platform of the Maine Republican Party</a> <span class="related-post-date timestamp">Fri 11 Jun 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/16/how-to-solve-it-and-project-euler/"><cite>How to Solve It</cite> and Project Euler</a> <span class="related-post-date timestamp">Fri 16 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/">Python Flatten/Concantenate Comparisons</a> <span class="related-post-date timestamp">Fri 09 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/">A Little More Functional Programming</a> <span class="related-post-date timestamp">Thu 25 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/">Minor Foray into Functional Programming</a> <span class="related-post-date timestamp">Tue 23 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/07/15/unit-testing-as-game/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>8-Bit Cities</title>
		<link>http://tadhg.com/wp/2010/07/12/8-bit-cities/</link>
		<comments>http://tadhg.com/wp/2010/07/12/8-bit-cities/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 04:35:14 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[culture]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=3090</guid>
		<description><![CDATA[As a geek of my generation, I cannot help but find an eight-bit map of San Francisco (there are maps of other cities too) a wonderful thing. It became even cooler when I found out it was programmed in Python.
Tags: coding, culture, techRelated PostsiPad First Impressions: Consumption Machine Sun 23 May 2010Your Online Life Might [...]]]></description>
			<content:encoded><![CDATA[<p>As a geek of my generation, I cannot help but find <a href="http://8bitcity.com/map?San%20Francisco" title="8-bit San Francisco" >an eight-bit map of San Francisco</a> (there are maps of other cities too) a wonderful thing. It became even cooler when I found out it was programmed in Python.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/culture/" rel="tag">culture</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/05/23/ipad-first-impressions-consumption-machine/">iPad First Impressions: Consumption Machine</a> <span class="related-post-date timestamp">Sun 23 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/24/your-online-life-might-be-an-open-book/">Your Online Life Might be an Open Book</a> <span class="related-post-date timestamp">Mon 24 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/30/profiling-political-leanings-by-browsing-history/">Profiling Political Leanings by Browsing History</a> <span class="related-post-date timestamp">Fri 30 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/02/clearing-growl-notifications/">Clearing Growl Notifications</a> <span class="related-post-date timestamp">Fri 02 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/10/wordpress-2-9-upgrade/">WordPress 2.9 Upgrade</a> <span class="related-post-date timestamp">Sun 10 Jan 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/07/12/8-bit-cities/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iPad First Impressions: Consumption Machine</title>
		<link>http://tadhg.com/wp/2010/05/23/ipad-first-impressions-consumption-machine/</link>
		<comments>http://tadhg.com/wp/2010/05/23/ipad-first-impressions-consumption-machine/#comments</comments>
		<pubDate>Mon, 24 May 2010 01:52:52 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[consciousness]]></category>
		<category><![CDATA[culture]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2960</guid>
		<description><![CDATA[I got an iPad for work on Friday, and have been playing around with it. I would not have bought one for myself, and have grave misgivings about the device, primarily due to its highly proprietary, locked-down, walled-garden approach.
That being said, I think it’s an extremely slick, well-designed device, and may represent the first steps [...]]]></description>
			<content:encoded><![CDATA[<p>I got an iPad for work on Friday, and have been playing around with it. I would not have bought one for myself, and have grave misgivings about the device, primarily due to its highly proprietary, locked-down, walled-garden approach.</p>
<p>That being said, I think it’s an extremely slick, well-designed device, and may represent the first steps towards a new phase in accessing computer and/or internet artifacts.<br />
<span id="more-2960"></span><br />
Before I get to that, I want to note that I hated having to synch it to iTunes before I could use it. For a “next-generation” device, one that supposedly breaks with older computing paradigms, that seemed rather pathetic. Also, I can’t stand iTunes, and the iPad setup was the only time I’d started it in the years I’ve had my Macbook Pro.</p>
<p>Once that was out of the way, however, it was all slick and smooth thereafter. Using the device: easy. Installing applications: easy. Browsing the web: easy.</p>
<p>The interface is, as promised, extremely intuitive. It works as you expect it to work. It’s also just fun to use, somehow.</p>
<p>So what’s the problem? Well, all of the criticisms about its closed model remain true. That it’s not easy to tinker with, that applications have to be approved by Apple, that getting data on and off it has to be managed by iTunes or some other application—these are all really bad things, in my opinion. That ground has been covered before, and if you’re interested you can read <a href="http://www.boingboing.net/2010/04/02/why-i-wont-buy-an-ipad-and-think-you-shouldnt-either.html" title="Why I won’t buy an iPad (and think you shouldn’t, either)" >Cory Doctorow’s take</a>, which I largely agree with.</p>
<p>What struck me even more than those issues, however, is just how geared towards consumption the iPad is. You add functionality via one mechanism: the App Store. While you can get some things for free there, the name makes clear that it’s about buying things. You can get content through the iTunes store. Many of the other apps, like the amazon.com application (or the Kindle application), are focused on making it easy to buy things.</p>
<p>Beyond that, the activities the device is suited for are consumption activities. Reading, browsing, buying, and watching videos are all really easy. I haven’t tried games on it yet, but I suspect that while games on it will be fun, they won’t (yet, at least) be as deep as games on dedicated platforms or on fully general-purpose computers. It does, however, support “casual games” quite well.</p>
<p>Up until this point, all general-purpose computing devices have been geared towards productivity of some kind. Even if they ended up being used as gaming boxes or as entertainment and netsurfing devices, they were designed for production of some kind, usually writing, programming, or management. This is not the case with the iPad. Regardless of whether or not you could actually edit video, or create music, or write efficiently, on it, its primary purpose is consumption. As such, I think it represents a significant break in the history of computing and the internet as the first mass-market, general-purpose device that is geared towards consuming rather than both consuming and producing.</p>
<p>This raises a question, one that is critical to assessing the validity of many of the criticisms of it (such as Doctorow’s): have computers been combined production/consumption machines up until now merely due to technological limitations, or is that combination an essential part of what a computer is? I think that what Jobs has done, deliberately and effectively, is tried to separate those two parts and get rid of the irritating bits that support production so that consumption can be made accessible and easy to more and more people.</p>
<p>Furthermore, Apple recognized that what made this attempted break with computing history possible was the touch interface. Crucially, the touch interface removes a layer of abstraction. Now there’s no cursor to move around with a mouse, and no commands to invoke via unknown (or clumsily announced) keystrokes. No abstraction, and hence almost no need for training. In many ways, the iPad is a device aimed squarely at <a href="http://tadhg.com/wp/2010/02/11/internet-illiteracy/" title="Internet Illiteracy" >the people who can’t tell the difference between an article about Facebook’s login page and Facebook’s login page itself</a>.</p>
<p>This is in many ways an inevitable step. URLs aren’t the best-designed things in the world (having the hierarchy go specific-to-general for domains and general-to-specific for resources on a domain, for example, is clearly screwy), and turning sites (accessible by URLs) into applications (accessible like other applications, by an easy launch mechanism) is probably inevitable too. But there’s clearly a loss with this, as abstraction in computing generally means power. That is, being able to manipulate resources with abstractions gives the user power, and abstracting things out before they reach the user takes power away from the user while making the smaller set of tasks they’re still able to do easier.</p>
<p>Many people will be in favor of this tradeoff; I’m not one of them, although I’d feel a lot better about it if it were a transient state that one could get past on a device (which I hope will be the case with the post-iPad tablets that emerge) rather than the state the device desires to keep its users in (which is the iPad’s approach).</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/consciousness/" rel="tag">consciousness</a>, <a href="http://tadhg.com/wp/tag/culture/" rel="tag">culture</a>, <a href="http://tadhg.com/wp/tag/internet/" rel="tag">internet</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a>, <a href="http://tadhg.com/wp/tag/usability/" rel="tag">usability</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/12/8-bit-cities/">8-Bit Cities</a> <span class="related-post-date timestamp">Mon 12 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/24/your-online-life-might-be-an-open-book/">Your Online Life Might be an Open Book</a> <span class="related-post-date timestamp">Mon 24 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/11/internet-illiteracy/">Internet Illiteracy</a> <span class="related-post-date timestamp">Thu 11 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2006/11/23/power-to-the-users/">Power to the Users</a> <span class="related-post-date timestamp">Thu 23 Nov 2006</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/30/profiling-political-leanings-by-browsing-history/">Profiling Political Leanings by Browsing History</a> <span class="related-post-date timestamp">Fri 30 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/02/clearing-growl-notifications/">Clearing Growl Notifications</a> <span class="related-post-date timestamp">Fri 02 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/05/23/ipad-first-impressions-consumption-machine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>sabbatical.close()</title>
		<link>http://tadhg.com/wp/2010/05/16/sabbatical-close/</link>
		<comments>http://tadhg.com/wp/2010/05/16/sabbatical-close/#comments</comments>
		<pubDate>Mon, 17 May 2010 06:36:56 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[CrossFit]]></category>
		<category><![CDATA[diet]]></category>
		<category><![CDATA[document formats]]></category>
		<category><![CDATA[exercise]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[goals]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[reStructuredText]]></category>
		<category><![CDATA[roleplaying]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[sports]]></category>
		<category><![CDATA[T]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[tennis]]></category>
		<category><![CDATA[text editing]]></category>
		<category><![CDATA[version-control]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2942</guid>
		<description><![CDATA[After a highly enjoyable, productive, and extended period, it’s time for me to return to the world of paid work.
I’m quite happy with the things I’ve done during my time off. Many of them are important only to me, but then, it’s been my time off.

Here are some of the things I’ve done since leaving [...]]]></description>
			<content:encoded><![CDATA[<p>After a highly enjoyable, productive, and extended period, it’s time for me to return to the world of paid work.</p>
<p>I’m quite happy with the things I’ve done during my time off. Many of them are important only to me, but then, it’s been my time off.<br />
<span id="more-2942"></span><br />
Here are some of the things I’ve done since leaving Metaweb that I consider significant:</p>
<ul>
<li><strong>CrossFit</strong>. I’m approaching the one year mark, and it’s hard to overstate the importance of that for me. This is the first time in my life I’ve managed to keep an exercise routine of any kind going for that long. Not coincidentally, I’m also in the best shape of my life. I now feel that some kind of regular, intense, exercise has a similar place in my life to my morning pages—that is, something I I regard as mandatory and more or less permanent.
</li>
<li><strong>Diet</strong>. Not just <a href="http://tadhg.com/wp/2009/07/20/considering-carnivorism/" title="Considering Carnivorism" >switching back to eating meat</a>, but also radically cutting down on sugar and processed foods. This also has a lot to do with my being in good shape.
</li>
<li><strong>Document format</strong>. Until this year, I hadn’t found a text-based document format I liked, but I have now finally settled on <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>. One of the effects of this is that I shifted to doing all of my writing in a text editor rather than doing some of it in word processors. Another effect is that all of my writing is now much more amenable to programmatic manipulation.
</li>
<li><strong>Programming my own environment</strong>. Following from the previous item, I spent quite a bit of time working on solutions to various small niggles in my workflows, so that far less of my time is consumed by setup for writing. Some examples of this include scripts to insert the template for blog posts into my editor, scripts to publish to my blog directly from my editor, scripts to do word counting precisely as I wish it to be done, and many other small utilities that remove minor annoyances that I previously encountered almost every day. In many respects this kind of thing is precisely what programming and computers are for: to make it easier to create, and to lessen the gap between a thought and expression of that thought.
</li>
<li><strong>Digital organization</strong>. This includes <a href="http://tadhg.com/wp/2009/05/04/version-control-recovery/" title="Version Control Recovery" >recovering my subversion repository</a>, restoring my blog to proper working order, and various other steps that have made my digital domain much more manageable. This is bound up with the previous item too.
</li>
<li><strong>Switching to Vim</strong>. This was probably a long time coming, but nevertheless required a fair amount of work, not least in porting all my scripts for jEdit over to it. I’ve been extremely happy with Vim. I think that to most people this might sound trivial; how many people would regard switching word processors as an “achievement”? But a text editor is different from a word processor, and switching to Vim isn’t like switching between non-modal text editors. This, combined with moving all my writing to text editors and thus to Vim, is a profound change for me, and one that I’m very happy I took the time to get through.
</li>
<li><strong>WordPress plugins</strong>. <a href="http://tadhg.com/wp/wordpress-plugins/" title="WordPress Plugins" >I wrote some of these</a> to improve my blog after I got it working again.
</li>
<li><strong>PyWordCount</strong>. My word counting script/Vim plugin is done, but I have to finish the documentation for it and make it public. It’s significant to me because it’ll be my first self-contained public Python project, and also because it’s an outgrowth of the document format switch, the Vim switch, and the focus on programming my own environment to a much greater degree.
</li>
<li><strong>Q’Rith</strong>. I ran my first roleplaying sessions in 15 years, and am currently running my first roleplaying campaign in 15 years, in a world that I’ve created and am quite happy with so far.
</li>
<li><strong>Tennis</strong>. I started playing it again, and don’t know why I ever stopped.
</li>
</ul>
<p>Those are the main highlights. Many of them are internal, or are things that only I notice, but I think the effect they’ve had on me is actually quite major, and in positive ways.</p>
<p>As for what’s next, I’ll write about that tomorrow.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/crossfit/" rel="tag">CrossFit</a>, <a href="http://tadhg.com/wp/tag/diet/" rel="tag">diet</a>, <a href="http://tadhg.com/wp/tag/document-formats/" rel="tag">document formats</a>, <a href="http://tadhg.com/wp/tag/exercise/" rel="tag">exercise</a>, <a href="http://tadhg.com/wp/tag/food/" rel="tag">food</a>, <a href="http://tadhg.com/wp/tag/games/" rel="tag">games</a>, <a href="http://tadhg.com/wp/tag/goals/" rel="tag">goals</a>, <a href="http://tadhg.com/wp/tag/personal/" rel="tag">personal</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a>, <a href="http://tadhg.com/wp/tag/restructuredtext/" rel="tag">reStructuredText</a>, <a href="http://tadhg.com/wp/tag/roleplaying/" rel="tag">roleplaying</a>, <a href="http://tadhg.com/wp/tag/software/" rel="tag">software</a>, <a href="http://tadhg.com/wp/tag/sports/" rel="tag">sports</a>, <a href="http://tadhg.com/wp/tag/t/" rel="tag">T</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a>, <a href="http://tadhg.com/wp/tag/tennis/" rel="tag">tennis</a>, <a href="http://tadhg.com/wp/tag/text-editing/" rel="tag">text editing</a>, <a href="http://tadhg.com/wp/tag/version-control/" rel="tag">version-control</a>, <a href="http://tadhg.com/wp/tag/vim/" rel="tag">Vim</a>, <a href="http://tadhg.com/wp/tag/wordpress/" rel="tag">WordPress</a>, <a href="http://tadhg.com/wp/tag/writing/" rel="tag">writing</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/03/30/2010-goals-first-quarter-review/">2010 Goals: First Quarter Review</a> <span class="related-post-date timestamp">Tue 30 Mar 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/01/2010-goals/">2010 Goals</a> <span class="related-post-date timestamp">Fri 01 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/12/31/crossfit-and-coding-and-meat/">CrossFit and Coding (and Meat)</a> <span class="related-post-date timestamp">Thu 31 Dec 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/28/better-rest-wordpress-pipeline/">Better reST–WordPress Pipeline</a> <span class="related-post-date timestamp">Tue 28 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/14/blog-workflow-with-restructuredtext/">Blog Workflow with reStructuredText</a> <span class="related-post-date timestamp">Tue 14 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/05/16/sabbatical-close/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rather Better Than a Cover Letter</title>
		<link>http://tadhg.com/wp/2010/05/13/rather-better-than-a-cover-letter/</link>
		<comments>http://tadhg.com/wp/2010/05/13/rather-better-than-a-cover-letter/#comments</comments>
		<pubDate>Fri, 14 May 2010 01:55:12 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[advertising]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2931</guid>
		<description><![CDATA[It might sound like a cheesy stunt, but I have a hard time coming up with a more fitting way to land a job at an advertising agency.
Tags: advertising, coding, workRelated PostsGiles Bowkett on Finding New Programming Jobs Tue 23 Mar 2010Metaweb Acquired by Google Fri 16 Jul 2010Literary Awards in Freebase Tue 29 Apr [...]]]></description>
			<content:encoded><![CDATA[<p>It might sound like a cheesy stunt, but I have a hard time coming up with a <a href="http://www.guardian.co.uk/media/pda/2010/may/13/google-jobs-brownstein" title="Get your dream job - through Google Ads" >more fitting way to land a job at an advertising agency</a>.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/advertising/" rel="tag">advertising</a>, <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/work/" rel="tag">work</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/03/23/giles-bowkett-on-finding-new-programming-jobs/">Giles Bowkett on Finding New Programming Jobs</a> <span class="related-post-date timestamp">Tue 23 Mar 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/04/29/literary-awards-in-freebase/">Literary Awards in Freebase</a> <span class="related-post-date timestamp">Tue 29 Apr 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/03/10/data-fever/">Data Fever</a> <span class="related-post-date timestamp">Mon 10 Mar 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2008/03/06/freebasin/">Freebasin'</a> <span class="related-post-date timestamp">Thu 06 Mar 2008</span></li><li class="related-post"><a href="http://tadhg.com/wp/2007/02/11/enjoyable-work/">Enjoyable Work</a> <span class="related-post-date timestamp">Sun 11 Feb 2007</span></li><li class="related-post"><a href="http://tadhg.com/wp/2006/02/10/nimblefish-field-expansion-bookmarklets/">Nimblefish field expansion bookmarklets</a> <span class="related-post-date timestamp">Fri 10 Feb 2006</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/12/8-bit-cities/">8-Bit Cities</a> <span class="related-post-date timestamp">Mon 12 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/23/ipad-first-impressions-consumption-machine/">iPad First Impressions: Consumption Machine</a> <span class="related-post-date timestamp">Sun 23 May 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/05/13/rather-better-than-a-cover-letter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Improving a Python Word Counting Function</title>
		<link>http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/</link>
		<comments>http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 20:33:36 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[text editing]]></category>
		<category><![CDATA[Vim]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2892</guid>
		<description><![CDATA[This post could be summarized as “regular expressions are a lot faster than naive for loops”.
I’ve been working on improving the script I use for live wordcount in Vim, partly for performance and partly so that I can package it up as a plugin and share it with other people. Along the way I’ve improved [...]]]></description>
			<content:encoded><![CDATA[<p>This post could be summarized as “regular expressions are a lot faster than naive for loops”.</p>
<p>I’ve been working on improving the script I use for live wordcount in Vim, partly for performance and partly so that I can package it up as a plugin and share it with other people. Along the way I’ve improved the speed of the script rather significantly, and will go through the key part of that change here.<br />
<span id="more-2892"></span><br />
The core part of the script, unsurprisingly, is the <tt class="docutils literal"><span class="pre">count_words()</span></tt> function. As is common, it treats groups of letters surrounded by spaces as “words”. New lines also mark the end of a word. So do a variety of other characters, such as em dashes—in fact, one of the motivations for writing my own wordcount was because I wanted em dashes to be recognized as word separators.</p>
<p>In the following code, <tt class="docutils literal"><span class="pre">self.WORD_SEPS</span></tt> and <tt class="docutils literal"><span class="pre">self.LINE_SEPS</span></tt> are lists containing characters that separate words and lines. <tt class="docutils literal"><span class="pre">self.REPEATER_SEPS</span></tt> contains characters like “-”, which in my opinion does not separate words when used singly (e.g. “twenty-three” is one word) but does when used consecutively; “&#8211;” is a simple way to write an em dash when you’re restricted to ASCII. <tt class="docutils literal"><span class="pre">self.IGNORE</span></tt> is a list of characters that cannot form words on their own but aren’t necessarily separators, either.</p>
<p>The code is quite naive in its approach. It goes through the text letter by letter, checks the letter to see whether or not it’s in one of those lists, adjusts the count accordingly, and also stores <tt class="docutils literal"><span class="pre">previous_char</span></tt> in order to be able to handle the repeater separators.</p>
<pre class="python literal-block">
def count_words(self, text):
    words, lines = 0, 1
    word, previous_char = 0, None
    lineword_separators = self.LINE_SEPS + self.WORD_SEPS
    repeater_test = lambda c, pc: bool(
        c in self.REPEATER_SEPS and pc in self.REPEATER_SEPS)
    separator_test = lambda c, pc: bool(
        char in lineword_separators or repeater_test(c, pc))
    for char in text:
        if separator_test(char, previous_char):
            word = 0
            if char in (self.LINE_SEPS):
                lines = lines + 1
        elif char in (self.IGNORE):
            pass
        else:
            #it’s part of a word.
            if not word:
                words = words + 1
                word = 1
        previous_char = char

    return (words, lines)
</pre>
<p>With that code as the central function, the script takes about three seconds to process a text file that’s approximately 400K/68,000 words.</p>
<p>The new version eliminates the need for a separate list of repeater separators, is fewer lines of code, and is faster:</p>
<pre class="python literal-block">
def count_words(self, text):

    def ors(l): return r&quot;|&quot;.join([re.escape(c) for c in l])
    def retext(text, chars, sub):
        return re.compile(ors(chars)).sub(sub, text)

    lines = text and len(re.compile(ors(self.LINE_SEPS)).split(text)) or 0

    text = retext(text, self.WORD_SEPS + self.LINE_SEPS, u&quot; &quot;)
    text = retext(text.strip(), self.IGNORE, u&quot;&quot;)
    words = text and len(re.compile(r&quot;[ ]+&quot;).split(text)) or 0

    return (words, lines)
</pre>
<p>The basic approach here is different. Rather than going through the text and evaluating it character by character, instead it replaces all of the characters in the separator lists with spaces, removes all the characters in the ignore list, uses <tt class="docutils literal"><span class="pre">split()</span></tt> to get a list of all the words in the text, and then counts the length of that list.</p>
<p>The most awkward part of it is having to construct the regular expressions out of the lists of characters, which is what the <tt class="docutils literal"><span class="pre">ors()</span></tt> function does. I could have replaced the lists with regular expressions, but I want it to be easy for users to alter the lists to suit their own preferences, and so left them as plain lists.</p>
<p>(Note that I’m restricted to Python 2.3 here since this needs to run in MacVim; hence the old-style <tt class="docutils literal"><span class="pre">and</span></tt> and <tt class="docutils literal"><span class="pre">or</span></tt> instead of new-style ternary expressions.)</p>
<p>Using that code instead of the previous version, and operating on the same 400K/68,000-word file, the script takes about 0.12 seconds—a 25-fold speed increase. Since this is a “live” wordcount, one that has to recount the entire file whenever you do something other than typing or adding a single new line, that’s an important difference, and it makes it much more usable when working with large files.</p>
<p>I had no illusions that my original version was anything close to optimal when I first wrote it, but I didn’t realize that the speed gains from doing it better would be so significant. Python’s regular expression handling is done by a C module, and I suspect that C module is quite highly optimized indeed. So, if speed is important, let highly-optimized C do the work, instead of doing it in your own code.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a>, <a href="http://tadhg.com/wp/tag/software/" rel="tag">software</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a>, <a href="http://tadhg.com/wp/tag/text-editing/" rel="tag">text editing</a>, <a href="http://tadhg.com/wp/tag/vim/" rel="tag">Vim</a>, <a href="http://tadhg.com/wp/tag/writing/" rel="tag">writing</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/19/better-word-count-in-jedit/">Better Word Count in jEdit</a> <span class="related-post-date timestamp">Sun 19 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/28/some-futurist-speculation-on-screen-interfaces/">Some Futurist Speculation on Screen Interfaces</a> <span class="related-post-date timestamp">Fri 28 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/08/02/python-script-for-subversion-status/">Python Script for Subversion Status</a> <span class="related-post-date timestamp">Sun 02 Aug 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/28/better-rest-wordpress-pipeline/">Better reST–WordPress Pipeline</a> <span class="related-post-date timestamp">Tue 28 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/14/blog-workflow-with-restructuredtext/">Blog Workflow with reStructuredText</a> <span class="related-post-date timestamp">Tue 14 Jul 2009</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to Solve It and Project Euler</title>
		<link>http://tadhg.com/wp/2010/04/16/how-to-solve-it-and-project-euler/</link>
		<comments>http://tadhg.com/wp/2010/04/16/how-to-solve-it-and-project-euler/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 03:35:41 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[psychology]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2856</guid>
		<description><![CDATA[Some tips on problem solving.
Some problems.
Tags: coding, math, psychologyRelated PostsUnit Testing as Game Thu 15 Jul 2010Public Projects, Finishing Things, and bitbucket Tue 06 Apr 2010Courtney Stoker, Patriarchy, and Geek Misogyny Mon 23 Aug 2010Nurture, not Nature Sun 22 Aug 2010Controlling Discourse in the Internet Era Fri 06 Aug 2010Three Routines Mon 02 Aug 2010Lifehacker [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/How_to_Solve_It" title="How to Solve It" >Some tips on problem solving</a>.</p>
<p><a href="http://projecteuler.net/" title="Project Euler" >Some problems</a>.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/math/" rel="tag">math</a>, <a href="http://tadhg.com/wp/tag/psychology/" rel="tag">psychology</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/08/23/courtney-stoker-patriarchy-and-geek-misogyny/">Courtney Stoker, Patriarchy, and Geek Misogyny</a> <span class="related-post-date timestamp">Mon 23 Aug 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/08/22/nurture-not-nature/">Nurture, not Nature</a> <span class="related-post-date timestamp">Sun 22 Aug 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/08/06/controlling-discourse-in-the-internet-era/">Controlling Discourse in the Internet Era</a> <span class="related-post-date timestamp">Fri 06 Aug 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/08/02/three-routines/">Three Routines</a> <span class="related-post-date timestamp">Mon 02 Aug 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/20/lifehacker-meditation-guide/">Lifehacker Meditation Guide</a> <span class="related-post-date timestamp">Tue 20 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/12/8-bit-cities/">8-Bit Cities</a> <span class="related-post-date timestamp">Mon 12 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/08/tal-ben-shahar-on-practical-happiness/">Tal Ben-Shahar on Practical Happiness</a> <span class="related-post-date timestamp">Thu 08 Jul 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/16/how-to-solve-it-and-project-euler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Flatten/Concantenate Comparisons</title>
		<link>http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/</link>
		<comments>http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 07:31:32 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2839</guid>
		<description><![CDATA[I’m going to compare seven different ways in Python to make one list out of several lists containing different numbers of elements, something that strikes me as a common but not necessarily everyday operation.
The philosophy of Python is that generally there should be one obvious and reasonable way to do things. I really like this [...]]]></description>
			<content:encoded><![CDATA[<p>I’m going to compare seven different ways in Python to make one list out of several lists containing different numbers of elements, something that strikes me as a common but not necessarily everyday operation.</p>
<p>The philosophy of Python is that generally there should be one obvious and reasonable way to do things. I really like this philosophy—except when the Python way isn’t the way I prefer, of course.<br />
<span id="more-2839"></span><br />
I seem to instinctively like functional programming approaches, or at least an approach of breaking things down into small functions, each of which takes up a small amount of space in terms of code and which does just one thing. More and more I find myself thinking that if I can express succinctly (in English) what a block of code should do<a class="footnote-reference" href="#id2" id="id1">[1]</a>, the block shouldn’t be more than a couple of lines. I think this drive pushes me away from the Pythonic way of doing things.</p>
<p>So we have a list of lists. We want to make the list of lists into one list. <tt class="docutils literal"><span class="pre">[[1],</span> <span class="pre">[2,</span> <span class="pre">3]]</span></tt> should become <tt class="docutils literal"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></tt>. While trying to find the “right” way to do this trivial task, I became a little obsessed, hence this post and its seven approaches.</p>
<p>The first one is the one I suspect Python’s <a class="reference external" href="http://en.wikipedia.org/wiki/Benevolent_Dictator_For_Life">Benevolent Dictator For Life</a> would want me (and everyone else) to use:</p>
<pre class="python literal-block">
def flatten_for_loop(l):
    fl = []
    for i in l:
        for j in i:
            fl.append(j)
    return fl
</pre>
<p>It does the job, certainly. But at six lines, it just bugs me. My instinct tells me that “concatenate the lists” shouldn’t take that many lines. It’s possible that my instinct is simply off, but it’s pretty insistent.</p>
<p>This was my next idea:</p>
<pre class="python literal-block">
from operator import add
def flatten_reduce_add(l):
    return reduce(add, l)
</pre>
<p>Yes, the <a class="reference external" href="http://www.artima.com/forums/flat.jsp?forum=106&amp;thread=98196&amp;msRange=15">much-maligned</a> <tt class="docutils literal"><span class="pre">reduce</span></tt>. This does seem like a completely natural fit for it, however. I like this solution, but I don’t like having to import <tt class="docutils literal"><span class="pre">add</span></tt>, and I don’t like using <tt class="docutils literal"><span class="pre">reduce</span></tt> when in future it’ll need to be imported as well.</p>
<pre class="python literal-block">
def flatten_lc(l):
    return [i for j in l for i in j]
</pre>
<p>While I love list comprehensions, this one just doesn’t sit well. Even though I know what it does, I have trouble parsing it for some reason—and that’s really a sign that I shouldn’t use it, since someone who doesn’t know what it does would have a significantly harder time.</p>
<p>Before discovering better ways, I went on to create my own function to do it:</p>
<pre class="python literal-block">
def listadd(l, new=[]): return listadd(l, new + l.pop(0)) if l else new
def flatten_custfunc(l, new=[]):
    return listadd(l[:])
</pre>
<p>This modifies the list, necessitating the creation of a copy, and overall it’s pretty inefficient; I didn’t like it much, which is why I kept looking.</p>
<pre class="python literal-block">
def flatten_sum(l):
    return sum(l, [])
</pre>
<p>Possibly my favorite. The problem is that since I didn’t know that you could use sum on non-numbers—by giving it a value to start off with, which it normally defaults to 0—I suspect a lot of other people wouldn’t know it either, so it might cause confusion. I’m on the fence on this one—after all, the name gives it away, and so its intent should be quite clear. But there are cases where a reader might think that it was going to get the sum of all the numbers in the lists.</p>
<pre class="python literal-block">
from itertools import chain
def flatten_chain(l):
    return [i for i in chain(*l)]
</pre>
<p>Another favorite. This one seems quite clear to me (in part because the name helps), but again it requires an import.</p>
<pre class="python literal-block">
def flatten_map_extend(l):
    new = []
    map(new.extend, l)
    return new
</pre>
<p>Better than the original for-loop version, but it rubs me the wrong way—probably because I’ve seen solutions like the ones laid out above and their concision is exerting a dark influence.</p>
<p>Naturally, the next thing to do was to check the performance of the various options.</p>
<p>So I ran each a million times against a number of different inputs. The first input was a list of tuples and dicts:</p>
<pre class="python literal-block">
[
    [(1, {’type’: ’type1’, ’name’: ’name1’})],
    [(2, {’type’: ’type2’, ’name’: ’name2’})],
    [(3, {’type’: ’type3’, ’name’: ’name3’})],
    [(4, {’type’: ’type4’, ’name’: ’name4’})],
    [(9, {’type’: ’type9’, ’name’: ’name9’}), (10, {’type’: ’type9’, ’name’: ’name9’}), (11, {’type’: ’type9’, ’name’: ’name9’}), (12, {’type’: ’type9’, ’name’: ’name9’})],
    [(13, {’type’: ’type9’, ’name’: ’name9’})],
    [(23, {’type’: ’type9’, ’name’: ’name9’})]
]
</pre>
<p>And these are the times it took for each function to run 1000000 times with that input:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody valign="top">
<tr>
<td>flatten_map_extend</p>
</td>
<td>9.0762510299682617</p>
</td>
</tr>
<tr>
<td>flatten_lc</p>
</td>
<td>9.6673529148101807</p>
</td>
</tr>
<tr>
<td>flatten_reduce_add</p>
</td>
<td>9.8464798927307129</p>
</td>
</tr>
<tr>
<td>flatten_sum</p>
</td>
<td>10.240524053573608</p>
</td>
</tr>
<tr>
<td>flatten_chain</p>
</td>
<td>10.286052942276001</p>
</td>
</tr>
<tr>
<td>flatten_for_loop</p>
</td>
<td>11.377233028411865</p>
</td>
</tr>
<tr>
<td colspan="2">flatten_custfunc   16.330123901367188</p>
</td>
</tr>
</tbody>
</table>
<p>Next were lists of numbers:</p>
<pre class="python literal-block">
[
    [0],
    [1],
    [2],
    range(3,100),
    range(100,200),
    range(200,300),
    range(300,400),
    range(400,500),
    range(500,600),
    range(600,700),
    range(700,800),
    range(800,900),
    range(900,1000),
]
</pre>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody valign="top">
<tr>
<td>flatten_map_extend</p>
</td>
<td>34.196415901184082</p>
</td>
</tr>
<tr>
<td>flatten_sum</p>
</td>
<td>61.231782913208008</p>
</td>
</tr>
<tr>
<td>flatten_reduce_add</p>
</td>
<td>65.624041080474854</p>
</td>
</tr>
<tr>
<td>flatten_custfunc</p>
</td>
<td>75.283849000930786</p>
</td>
</tr>
<tr>
<td>flatten_lc</p>
</td>
<td>96.376346826553345</p>
</td>
</tr>
<tr>
<td>flatten_chain</p>
</td>
<td>126.78751182556152</p>
</td>
</tr>
<tr>
<td colspan="2">flatten_for_loop   213.21602821350098</p>
</td>
</tr>
</tbody>
</table>
<p>Finally, lists of strings:</p>
<pre class="python literal-block">
[
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
    [&quot;abcde&quot;] * 10,
]
</pre>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody valign="top">
<tr>
<td>flatten_map_extend</p>
</td>
<td>11.517388820648193</p>
</td>
</tr>
<tr>
<td>flatten_reduce_add</p>
</td>
<td>15.214270114898682</p>
</td>
</tr>
<tr>
<td>flatten_sum</p>
</td>
<td>15.836833000183105</p>
</td>
</tr>
<tr>
<td>flatten_lc</p>
</td>
<td>20.376528024673462</p>
</td>
</tr>
<tr>
<td>flatten_chain</p>
</td>
<td>22.739732027053833</p>
</td>
</tr>
<tr>
<td>flatten_custfunc</p>
</td>
<td>23.072113990783691</p>
</td>
</tr>
<tr>
<td colspan="2">flatten_for_loop   33.499195098876953</p>
</td>
</tr>
</tbody>
</table>
<p>I’m running these tests on a 2.5 GHz Intel Core 2 Duo machine, 4GB RAM, OS X, Python 2.6.</p>
<p>I don’t know how informative they were, but using <tt class="docutils literal"><span class="pre">map</span></tt> and <tt class="docutils literal"><span class="pre">list.extend</span></tt> seems like the most performant option. Which is unfortunate from my point of view, since I don’t like the way that looks, but since I should remember to turn it into a function whenever I need it, I should be able to deal with that.</p>
<p>It must be said that neither performance nor code readability (for programmers other than myself) matter in the project I was working on when I decided to explore this question, but I do want to know the right way to do it; it appears that I found a reasonable answer, although I’m definitely going to be tempted to use <tt class="docutils literal"><span class="pre">sum</span></tt> instead some of the time&#8230;</p>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup>
<col class="label" />
<col /></colgroup>
<tbody valign="top">
<tr>
<td class="label"><a class="fn-backref" href="#id1">[1]</a></td>
<td>Of course, I mean a succinct, specific, and complete explanation, rather than e.g. “it should solve my problem”, as going down that track would lead one to think that all programs should be one line long. They shouldn’t. But the line between concision and obscurity is subjective, and I’m trying to fine-tune my subjective take on that particular question of style.</p>
</td>
</tr>
</tbody>
</table>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/">A Little More Functional Programming</a> <span class="related-post-date timestamp">Thu 25 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/">Minor Foray into Functional Programming</a> <span class="related-post-date timestamp">Tue 23 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Public Projects, Finishing Things, and bitbucket</title>
		<link>http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/</link>
		<comments>http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 19:46:14 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[psychology]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2830</guid>
		<description><![CDATA[I’ve been writing Python fairly steadily for the past couple of years, and a significant amount of that has been for my own projects; Python is what I tend to use to scratch workflow-related itches. That’s great, but many of these projects reach a point short of “finished” when I stop working on them.

This is [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been writing Python fairly steadily for the past couple of years, and a significant amount of that has been for my own projects; Python is what I tend to use to scratch workflow-related itches. That’s great, but many of these projects reach a point short of “finished” when I stop working on them.<br />
<span id="more-2830"></span><br />
This is because I generally stop when they’re good enough for me to use. Which is fine, except that they hang around mentally, because I don’t feel that they’re fully done. So I’m going to make an effort to formally finish them by making them public, and pushing them to <a class="reference external" href="http://bitbucket.org/">bitbucket.org</a>. Making them public by posting them on my blog is fine, but feels much more like just pasting code into a blog post—which is what it is. Making them available to others in a convenient way is a better approach, and also forces me to get them to the point where I can call them done and feel good about it.</p>
<p>I selected my <a class="reference external" href="http://tadhg.com/wp/2009/08/02/python-script-for-subversion-status/">sorted Subversion status</a> script for this, because it was fairly small but might conceivably be useful to others (I found the concept useful enough to write it, after all). I cleaned up it, which made it faster and better, and wrote a quick README for it, and <a href="http://bitbucket.org/tadhg/subversion-sorted-status/" title="tadhg / Subversion sorted status / overview — bitbucket.org" >put it on bitbucket</a>.</p>
<p>I hope to do the same with other almost-finished scripts I have lying around.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/psychology/" rel="tag">psychology</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/16/how-to-solve-it-and-project-euler/"><cite>How to Solve It</cite> and Project Euler</a> <span class="related-post-date timestamp">Fri 16 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/">Python Flatten/Concantenate Comparisons</a> <span class="related-post-date timestamp">Fri 09 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/">A Little More Functional Programming</a> <span class="related-post-date timestamp">Thu 25 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/">Minor Foray into Functional Programming</a> <span class="related-post-date timestamp">Tue 23 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refactoring, Geeky Enjoyment, and Readability</title>
		<link>http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/</link>
		<comments>http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 20:16:55 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2820</guid>
		<description><![CDATA[Refactoring is rewriting source code while preserving the functionality of that code. I’m currently refactoring my Python script for Subversion status, because I want to experiment with sharing code on bitbucket and it seemed like a reasonable first project to put up there.
Some people hate refactoring, but I often enjoy it. I get a kick [...]]]></description>
			<content:encoded><![CDATA[<p><a class="reference external" href="http://en.wikipedia.org/wiki/Code_refactoring">Refactoring</a> is rewriting source code while preserving the functionality of that code. I’m currently refactoring my <a class="reference external" href="http://tadhg.com/wp/2009/08/02/python-script-for-subversion-status/">Python script for Subversion status</a>, because I want to experiment with sharing code on <a class="reference external" href="http://bitbucket.org/">bitbucket</a> and it seemed like a reasonable first project to put up there.</p>
<p>Some people hate refactoring, but I often enjoy it. I get a kick out of figuring out how to make code “better”, although that’s often a subjective judgment. In this case, when I opened up the script to have a look at it, I immediately saw a function that I knew I wanted to refactor. I’m amused by the enjoyment I derived from making the fairly simple change.<br />
<span id="more-2820"></span><br />
The function gets the length of the longest filename in a list<a class="footnote-reference" href="#id2" id="id1">[1]</a>, returning <tt class="docutils literal"><span class="pre">0</span></tt> if for some reason there aren’t any filenames in that list. This was the original version:</p>
<pre class="python literal-block">
def get_filename_width(self, files):
    width = 0
    lines = files.split(&quot;\n&quot;)
    for line in lines:
        if len(line) &gt; width:
            width = len(line)
    return width
</pre>
<p>It expects the <tt class="docutils literal"><span class="pre">files</span></tt> variable to be a multiline string. So it assigns a value to <tt class="docutils literal"><span class="pre">width</span></tt>, then splits the string into individual lines, and goes through each line, testing its length against the value of <tt class="docutils literal"><span class="pre">width</span></tt> and making <tt class="docutils literal"><span class="pre">width</span></tt> into that value if it’s greater. After going through all the lines, it returns <tt class="docutils literal"><span class="pre">width</span></tt>.</p>
<p>It’s fine as a first pass, but looking at it now, it just seems clunky and too long. I rewrote it into this:</p>
<pre class="python literal-block">
def get_filename_width(self, files):
    return max([len(line) for line in files.split(u&quot;\n&quot;)]) if files else 0
</pre>
<p>Six lines into one. But is this too opaque?</p>
<p>If I’m the intended reader, clearly not, as I’m quite familiar with reading list comprehensions, and I also consider the <a class="reference external" href="http://www.python.org/dev/peps/pep-0308/">Python 2.5+ ternary expression</a> to be entirely legible.</p>
<p>If someone else is the reader? The ease with which they can break the line into chunks is the main issue, as first they have to see that the line returns the result of <tt class="docutils literal"><span class="pre">max()</span></tt> if <tt class="docutils literal"><span class="pre">files</span></tt> has some value and <tt class="docutils literal"><span class="pre">0</span></tt> otherwise. The next bit is seeing that <tt class="docutils literal"><span class="pre">max()</span></tt> operates on a list comprehension, and finally they have to see that the list comprehension creates a list of the lengths of the lines in <tt class="docutils literal"><span class="pre">files</span></tt>.</p>
<p>I can see the argument that the six-line version is clearer, but the fact that it’s six lines as opposed to one needs to be taken into account as well—more lines mean more cognitive overhead for the reader, something that is often underestimated in judging the readability of code.</p>
<p>I think that a reader familiar with Python would grasp the one-liner faster than the six-liner. The use of <tt class="docutils literal"><span class="pre">max</span></tt> is helpful here (whereas it might hinder a reader who doesn’t know it)—rather than having to discern what the <tt class="docutils literal"><span class="pre">for</span></tt> loop in the six-liner is doing, it’s clear that the one-liner is interested in getting the highest value. I personally think that the lack of variable assignment in the one-liner makes it easier as well, despite the familiarity that almost all readers would have with variables.</p>
<p>Clearly, this is a rather trivial example<a class="footnote-reference" href="#id4" id="id2">[2]</a>. But the issues are relevant to writing shared code, and “shared” often applies even to personal code if you’re ever going to revisit it. While I definitely want to get something working quickly, it’s important to balance that with writing readable software. Readability requires finding the line between elegance and impenetrability, between concision and obscurity—just like writing more generally.</p>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup>
<col class="label" />
<col /></colgroup>
<tbody valign="top">
<tr>
<td class="label"><a class="fn-backref" href="#id1">[1]</a></td>
<td>Yet it’s called <tt class="docutils literal"><span class="pre">get_filename_width</span></tt>—because it’s concerned with the width (in columns) that the longest filename will take up in a terminal window. The purpose of the function in the larger context is related to the concept of width, while in the function itself it’s dealing with the length of individual filenames. You could argue for changing the name to <tt class="docutils literal"><span class="pre">get_filename_length</span></tt>, but I think the overall purpose of the function is more important to its name than what it’s doing internally.
</td>
</tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id4" rules="none">
<colgroup>
<col class="label" />
<col /></colgroup>
<tbody valign="top">
<tr>
<td class="label"><a class="fn-backref" href="#id2">[2]</a></td>
<td>It took me less than 3 minutes to write the new version of the function, whereas this post discussing it has taken rather a lot longer than that&#8230;</td>
</tr>
</tbody>
</table>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a>, <a href="http://tadhg.com/wp/tag/writing/" rel="tag">writing</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/19/better-word-count-in-jedit/">Better Word Count in jEdit</a> <span class="related-post-date timestamp">Sun 19 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/">Python Flatten/Concantenate Comparisons</a> <span class="related-post-date timestamp">Fri 09 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clearing Growl Notifications</title>
		<link>http://tadhg.com/wp/2010/04/02/clearing-growl-notifications/</link>
		<comments>http://tadhg.com/wp/2010/04/02/clearing-growl-notifications/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 22:43:22 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2814</guid>
		<description><![CDATA[I use a notification system for OS X called Growl, which provides a single channel for various applications to use when they have something to tell me. I mainly use it for IM and email. I’m fairly happy with it, but one issue that irked me was dealing with clearing a bunch of the notifications [...]]]></description>
			<content:encoded><![CDATA[<p>I use a notification system for OS X called <a class="reference external" href="http://growl.info/">Growl</a>, which provides a single channel for various applications to use when they have something to tell me. I mainly use it for IM and email. I’m fairly happy with it, but one issue that irked me was dealing with clearing a bunch of the notifications off the screen.<br />
<span id="more-2814"></span><br />
You can set them to disappear on their own, but then you run the risk of missing them if you’re away from your keyboard, or if you just don’t happen to catch their content in time. So I set mine to all stay on the screen until they’re dismissed. In order to dismiss them, you either click to close each one individually, or you can restart Growl from the OS menu bar.</p>
<p>To do the latter, you more or less have to use the mouse, and that eventually began to annoy me. I looked around, and found that there was a commandline controller called <tt class="docutils literal"><span class="pre">growlctl</span></tt>, but that it was no longer included in Growl releases. It can be found in the Extras section of the Growl 0.7.6 release, though, which they still have available for download.</p>
<p>I downloaded that, installed it (which really just means moving it to somewhere on your path), and verified that it does indeed still work. I then created a rather simple script:</p>
<pre class="literal-block">
/usr/local/bin/growlctl restart
</pre>
<p>And put it in my homedir, calling it <tt class="docutils literal"><span class="pre">gr.sh</span></tt>. <a class="reference external" href="http://en.wikipedia.org/wiki/Quicksilver_(software)">Quicksilver</a> knows that it’s there, so now clearing the notifications requires, at most, the following keystrokes: <tt class="docutils literal"><span class="pre">&lt;Ctrl-Space&gt;gr&lt;Enter&gt;</span></tt>. Itch scratched.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/os-x/" rel="tag">OS X</a>, <a href="http://tadhg.com/wp/tag/personal/" rel="tag">personal</a>, <a href="http://tadhg.com/wp/tag/software/" rel="tag">software</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/28/better-rest-wordpress-pipeline/">Better reST–WordPress Pipeline</a> <span class="related-post-date timestamp">Tue 28 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/14/blog-workflow-with-restructuredtext/">Blog Workflow with reStructuredText</a> <span class="related-post-date timestamp">Tue 14 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/11/26/open-source-thanks/">Open Source Thanks</a> <span class="related-post-date timestamp">Thu 26 Nov 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/08/02/python-script-for-subversion-status/">Python Script for Subversion Status</a> <span class="related-post-date timestamp">Sun 02 Aug 2009</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/04/02/clearing-growl-notifications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2010 Goals: First Quarter Review</title>
		<link>http://tadhg.com/wp/2010/03/30/2010-goals-first-quarter-review/</link>
		<comments>http://tadhg.com/wp/2010/03/30/2010-goals-first-quarter-review/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 19:12:33 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[CrossFit]]></category>
		<category><![CDATA[exercise]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[goals]]></category>
		<category><![CDATA[MTG]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[roleplaying]]></category>
		<category><![CDATA[web-development]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2808</guid>
		<description><![CDATA[Yes, clearly my progress (or lack thereof) needs quarterly reports. And here’s the first one for this year.

I laid out the full list at the start of the year. I’ve accomplished some of them:

Celebrate my birthday. This still seems like a strange goal to have—but putting it on here helped me get it done, and [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, clearly my progress (or lack thereof) needs quarterly reports. And here’s the first one for this year.<br />
<span id="more-2808"></span><br />
I laid out the <a href="http://tadhg.com/wp/2010/01/01/2010-goals/" title="2010 Goals" >full list</a> at the start of the year. I’ve accomplished some of them:</p>
<ul>
<li>Celebrate my birthday. This still seems like a strange goal to have—but putting it on here helped me get it done, and I had a great time and don’t get why I didn’t do this for years. I’ll do it again next year!
</li>
<li>Participate in the CrossFit Sectionals. <a href="http://tadhg.com/wp/2010/03/28/crossfit-games-2010-norcal-sectionals-how-i-did/" title="CrossFit Games 2010 NorCal Sectionals: How I Did" >Done</a>!
</li>
<li>Ten dead-hang pullups. Done; currently my best is 11, and I’m now aiming for 20 before going back to kipping.
</li>
</ul>
<p>I’ve made some progress on these:</p>
<ul>
<li>Revive sfmagic.org. “Some progress” here means I’ve tried to get the code running again and have run into incompatibilities between Pylons versions. So, slightly closer, but not a lot of movement.
</li>
<li>Run a roleplaying campaign. I’ve started it, and two sessions in it’s going well.
</li>
<li>I’m presumably closer to my other fitness-related goals of a 300-pound deadlift, a sub-23:00 5K, and <a class="reference external" href="http://www.crossfit.com/mt-archive2/001129.html">“Murph”</a> in under 50:00.
</li>
<li>It’s hard to judge progress on an amorphous goal like “building a sense of community”, but I think there’s been some.
</li>
</ul>
<p>I’ve made no progress on these:</p>
<ul>
<li>Write at least one draft of the fantasy novel. I feel fine about this, and haven’t really tried to work on it. I know that at some point the desire to do so will resurface, and the key to getting it done is focusing on it when that happens.
</li>
<li>Finish <a class="reference external" href="http://tadhg.com/afbh/"><cite>The Annotated Fantasy Bedtime Hour</cite></a>. Still something I just need to get down to doing&#8230;
</li>
</ul>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/community/" rel="tag">community</a>, <a href="http://tadhg.com/wp/tag/crossfit/" rel="tag">CrossFit</a>, <a href="http://tadhg.com/wp/tag/exercise/" rel="tag">exercise</a>, <a href="http://tadhg.com/wp/tag/games/" rel="tag">games</a>, <a href="http://tadhg.com/wp/tag/goals/" rel="tag">goals</a>, <a href="http://tadhg.com/wp/tag/mtg/" rel="tag">MTG</a>, <a href="http://tadhg.com/wp/tag/personal/" rel="tag">personal</a>, <a href="http://tadhg.com/wp/tag/roleplaying/" rel="tag">roleplaying</a>, <a href="http://tadhg.com/wp/tag/web-development/" rel="tag">web-development</a>, <a href="http://tadhg.com/wp/tag/writing/" rel="tag">writing</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/01/01/2010-goals/">2010 Goals</a> <span class="related-post-date timestamp">Fri 01 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/08/02/three-routines/">Three Routines</a> <span class="related-post-date timestamp">Mon 02 Aug 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/01/anaqrest/">Anaq’rest</a> <span class="related-post-date timestamp">Thu 01 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/03/21/an-introduction-to-roleplaying-games/">An Introduction to Roleplaying Games</a> <span class="related-post-date timestamp">Sun 21 Mar 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/12/31/crossfit-and-coding-and-meat/">CrossFit and Coding (and Meat)</a> <span class="related-post-date timestamp">Thu 31 Dec 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/12/29/2009-goals-review/">2009 Goals Review</a> <span class="related-post-date timestamp">Tue 29 Dec 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/30/2009-goals-status/">2009 Goals Status</a> <span class="related-post-date timestamp">Thu 30 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/01/01/2009-goals/">2009 Goals</a> <span class="related-post-date timestamp">Thu 01 Jan 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2007/05/11/sfmagicorg-database-structure/">sfmagic.org Database Structure</a> <span class="related-post-date timestamp">Fri 11 May 2007</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/03/30/2010-goals-first-quarter-review/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Giles Bowkett on Finding New Programming Jobs</title>
		<link>http://tadhg.com/wp/2010/03/23/giles-bowkett-on-finding-new-programming-jobs/</link>
		<comments>http://tadhg.com/wp/2010/03/23/giles-bowkett-on-finding-new-programming-jobs/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 23:52:45 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[advertising]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[work]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2786</guid>
		<description><![CDATA[It’s too long, it’s full of self-promotion, and really it’s an ad for a video he’s selling, but it’s entertaining and contains some good advice: “Programmers: What to do if You Get Fired”.
This might be the best line:

If you’re looking for a better job, writing an amazing resume is a good place to start. I [...]]]></description>
			<content:encoded><![CDATA[<p>It’s too long, it’s full of self-promotion, and really it’s an ad for a video he’s selling, but it’s entertaining and contains some good advice: <a class="reference external" href="http://gilesbowkett.blogspot.com/2010/03/programmers-what-to-do-if-you-get-fired.html">“Programmers: What to do if You Get Fired”</a>.</p>
<p>This might be the best line:</p>
<blockquote><p>
If you’re looking for a better job, writing an amazing resume is a good place to start. I don’t mean just a <em>better</em> resume; I mean <span class="bolditalic">a resume that makes people stop asking if they should hire you and start asking if they can afford you.</span> </p>
<div class="block-cite">—Giles Bowkett. <a href="http://gilesbowkett.blogspot.com/2010/03/programmers-what-to-do-if-you-get-fired.html">“Programmers: What to do if You Get Fired”</a>. <a href="http://gilesbowkett.blogspot.com/"><em>Giles Bowkett’s blog</em></a>, 8 Mar 2010.</div>
</blockquote>
<p>Annoyingly, I find myself tempted to buy that video after reading his post&#8230;</p>
<p>So far, his <a class="reference external" href="http://www.infoq.com/presentations/archaeopteryx-bowkett">2008 presentation at RubyFringe seems pretty entertaining too.</a> Maybe you should watch it after you’ve updated your résumé.</p>
<p>Update: at the end of that presentation, he says “build something because you believe it should exist”, which I agree with 100%.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/advertising/" rel="tag">advertising</a>, <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/work/" rel="tag">work</a>, <a href="http://tadhg.com/wp/tag/writing/" rel="tag">writing</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/05/13/rather-better-than-a-cover-letter/">Rather Better Than a Cover Letter</a> <span class="related-post-date timestamp">Thu 13 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/03/30/2010-goals-first-quarter-review/">2010 Goals: First Quarter Review</a> <span class="related-post-date timestamp">Tue 30 Mar 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/01/2010-goals/">2010 Goals</a> <span class="related-post-date timestamp">Fri 01 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/03/23/giles-bowkett-on-finding-new-programming-jobs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Little More Functional Programming</title>
		<link>http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/</link>
		<comments>http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 07:55:51 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2712</guid>
		<description><![CDATA[After reading Dhananjay Nene’s comment on my post about a functional style approach to the “find longest repeater” problem, I decided to follow the line from that comment and divide the program into functions for finding the longest contiguous block and then for comparing the blocks. Naturally, I wanted to do this without using any [...]]]></description>
			<content:encoded><![CDATA[<p>After reading <a class="reference external" href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/#comment-19788">Dhananjay Nene’s comment</a> on my <a class="reference external" href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/">post about a functional style approach to the “find longest repeater” problem</a>, I decided to follow the line from that comment and divide the program into functions for finding the longest contiguous block and then for comparing the blocks. Naturally, I wanted to do this without using any variables&#8230;<br />
<span id="more-2712"></span><br />
It wasn’t too hard to write a variable-free function to return a list of blocks of letters from a string, e.g. <tt class="docutils literal"><span class="pre">continuous_blocks(&quot;anna&quot;)</span></tt> produces <tt class="docutils literal"><span class="pre">[&quot;a&quot;,</span> <span class="pre">&quot;nn&quot;,</span> <span class="pre">&quot;a&quot;]</span></tt>:</p>
<pre class="python literal-block">
def contiguous_blocks(string):
    def listbuilder(blocks, char, rest):
        if not rest:
            return add_to_blocks(char, blocks)
        return listbuilder(add_to_blocks(char, blocks), rest[0], rest[1:])

    def add_to_blocks(char, blocks):
        if blocks and char in blocks[-1]:
            return blocks[:-1] + [&quot;&quot;.join([blocks[-1], char])]
        return blocks+[char]

    return listbuilder([], string[0], string[1:])
</pre>
<p>And then <tt class="docutils literal"><span class="pre">findlongestrepeater</span></tt> becomes:</p>
<pre class="python literal-block">
def findlongestrepeater(string):
    def compare_blocks(previous, current):
        return current if len(current)&gt;len(previous) else previous

    return reduce(compare_blocks, contiguous_blocks(string))
</pre>
<p>Note that this approach provides a clear use for <tt class="docutils literal"><span class="pre">reduce</span></tt>, which is <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=98196" title="The fate of reduce() in Python 3000" >on the outs in Python these days</a>.</p>
<p>A crucial difference between <a class="reference external" href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/#comment-19788">Dhananjay Nene’s version</a> and mine, however, is that mine returns a list and not a generator. So I decided to write a variable-free generator version&#8230; and just couldn’t do it. I don’t know what it was, but I kept getting hung up on trying to track the previous, current, and next characters, and to do that without variables while trying to skip at the right times in the for loop just seemed impossible. While writing this blog post, however, I figured it out. I had intended to put it up as a puzzle for other people, so I guess I’ll put my solution at the end. If you plan to try it, don’t scroll beyond the warning below.</p>
<p>There’s an easier way, too, which is simply to do this:</p>
<pre class="python literal-block">
def contiguous_blocks(string):
    from itertools import groupby
    for k,g in groupby(string):
        yield u&quot;&quot;.join(list(g))
</pre>
<p>I found that last night after being unable to bend my mind in the right way, because I was sure that this problem couldn’t be so rare that itertools wouldn’t have something to handle it.</p>
<p>However, I felt like that was cheating&#8230; so I kept trying to build my own variable-free generator.</p>
<p>Because of the fact that <tt class="docutils literal"><span class="pre">reduce</span></tt> isn’t going to be in Python 3, I decided I’d write a version of it that would work as its replacement for this problem. It didn’t seem too hard to come up with this:</p>
<pre class="python literal-block">
def reducereplacement(func, generator):
    def runfunc(product, gen):
        try:
            return runfunc(func(product, gen.next()), gen)
        except StopIteration:
            return product

    return runfunc([], generator)
</pre>
<p>This only works with generators and not with lists, unlike the real <tt class="docutils literal"><span class="pre">reduce</span></tt>. There’s no reason to use this, either, given that <tt class="docutils literal"><span class="pre">reduce</span></tt> is in Python 2 and will be in the <tt class="docutils literal"><span class="pre">functools</span></tt> module for Python 3; I just wanted to try it as an experiment.</p>
<p>So, to restate the puzzle problem:</p>
<p>Write a version of <tt class="docutils literal"><span class="pre">contiguous_blocks</span></tt> that is functionally equivalent to the version above using <tt class="docutils literal"><span class="pre">itertools.groupby</span></tt>, without using the assignment operator anyhere, or anything from a module. This is a puzzle I found impossible last night but reasonably easy today. Like a lot of puzzles, looking at it in a slightly different way can make all the difference—advice which is often maddeningly useless while you’re trying to solve something.</p>
<p>The function, plus the version of <tt class="docutils literal"><span class="pre">findlongestrepeater</span></tt> I have above, should pass the following tests:</p>
<pre class="python literal-block">
def test_contiguous_blocks():
    testgen = contiguous_blocks(&quot;googlee&quot;)
    assert testgen.next() == &quot;g&quot;
    assert testgen.next() == &quot;oo&quot;
    assert testgen.next() == &quot;g&quot;
    assert testgen.next() == &quot;l&quot;
    assert testgen.next() == &quot;ee&quot;
    assert [c for c in contiguous_blocks(&quot;google&quot;)] == [&quot;g&quot;, &quot;oo&quot;, &quot;g&quot;, &quot;l&quot;, &quot;e&quot;]
    assert [c for c in contiguous_blocks(&quot;googlee&quot;)] == [
        &quot;g&quot;, &quot;oo&quot;, &quot;g&quot;, &quot;l&quot;, &quot;ee&quot;]

def test_findlongestrepeater():
    assert findlongestrepeater(&quot;google&quot;) == &quot;oo&quot;
    assert findlongestrepeater(&quot;gooooogle&quot;) == &quot;ooooo&quot;
    assert findlongestrepeater(&quot;eeffi&quot;) == &quot;ee&quot;
    assert findlongestrepeater(&quot;abcdef&quot;) == &quot;a&quot;
    assert findlongestrepeater(&quot;eeffeeeffeeeee&quot;) == &quot;eeeee&quot;
</pre>
<h4>WARNING, SOLUTION</h4>
<p>Don’t read past here if you want to solve it yourself, obviously.</p>
<hr class="docutils" />
The key insight that helped me get it (which seems utterly obvious now, of course) is that you’re not limited to the current and next (and/or previous) characters. I’d been approaching it with logic like this:</p>
<ul>
<li>Check the character to see if it’s different from the next character.
<ul>
<li>If it is, return it.
</li>
<li>If it isn’t, pass.
</li>
</ul>
</li>
<li>But also (somehow) store it so that you know what the current sequence of repeated characters is, and when you next return something, return that sequence instead of just the current character.
</li>
</ul>
<p>I couldn’t figure out how to make that work, and it may be impossible to get Python to do that without using variables (although maybe I just missed the trick).</p>
<p>However, that wasn’t the right way to look at it. With access to the index of the current character, you can get not only the next character, but also string up to that point. That was the realization: the logic should be as follows:</p>
<ul>
<li>Check the character to see if it’s different from the next character.
<ul>
<li>If it isn’t, pass.
</li>
<li>If it is, return all the characters in the string up to that point that are the same as the character.
</li>
</ul>
</li>
</ul>
<p>As I said, that seems awfully obvious now&#8230;</p>
<p>This is the solution I came up with:</p>
<pre class="python literal-block">
def contiguous_blocks(string):
    def inarow(row, string):
        if not string or row[0] != string[0]:
            return row
        return inarow(u&quot;&quot;.join([row, string[0]]), string[1:])

    for i,c in enumerate(string):
        if i &gt;= (len(string) -1) or c != string[i+1]:
            yield inarow(c, string[:i][::-1])
</pre>
<p>So, if the character is different from the next one, or you’ve run out of string, yield the result of passing the character and the (reversed) string up to that point to <tt class="docutils literal"><span class="pre">inarow</span></tt>. Otherwise, if the character is the same as the next character—do nothing.</p>
<p><tt class="docutils literal"><span class="pre">inarow</span></tt> doesn’t have to track anything but the characters until a different character shows up or you run out of string, so it returns what it has at that point if either of those happen, otherwise it calls itself with a new row of characters (the current one tacked onto the end) and the rest of the string.</p>
<p>The combination of <tt class="docutils literal"><span class="pre">find_longest_repeater</span></tt> and <tt class="docutils literal"><span class="pre">contiguous_blocks</span></tt> seems like a fairly elegant solution. Not only does it come in at two lines shorter than my version from Tuesday, but it also has the benefit of being more neatly divided in logical terms. (Which is something I wouldn’t have seen without the suggestion that the determination of contiguous blocks could be a discrete function.)</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/">Python Flatten/Concantenate Comparisons</a> <span class="related-post-date timestamp">Fri 09 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/">Minor Foray into Functional Programming</a> <span class="related-post-date timestamp">Tue 23 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Minor Foray into Functional Programming</title>
		<link>http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/</link>
		<comments>http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 23:56:05 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2709</guid>
		<description><![CDATA[Last night a friend asked me what functional programming was, and as part of my answer I decided to rewrite a trivial program in the functional style to see what it was like. I did this in Python without using the functional module.

The program finds the longest sequence of repeated characters in a string; if [...]]]></description>
			<content:encoded><![CDATA[<p>Last night a friend asked me what <a class="reference external" href="http://en.wikipedia.org/wiki/Functional_programming">functional programming</a> was, and as part of my answer I decided to rewrite a trivial program in the functional style to see what it was like. I did this in Python without using the <tt class="docutils literal"><span class="pre">functional</span></tt> module.<br />
<span id="more-2709"></span><br />
The program finds the longest sequence of repeated characters in a string; if there’s a tie, it returns the first sequence of that length. My (<a class="reference external" href="http://en.wikipedia.org/wiki/Imperative_programming">imperative</a>) version was six lines of Python:</p>
<pre class="python literal-block">
def findlongestrepeater(string):
    longest, curr = &quot;&quot;, &quot;&quot;
    for c in string:
        curr = &quot;&quot;.join([curr, c]) if c in curr else c
        longest = curr if len(curr) &gt; len(longest) else longest
    return longest
</pre>
<p>There are doubtless better ways to do it, but this is relatively succinct and clear. I can’t say the same about the functional version I came up with.</p>
<p>With my attempt at this example, “functional programming” basically meant “not using the assignment operator”.</p>
<p>I couldn’t see any way to do it without recursion, and it came out looking like a recursive decision tree:</p>
<pre class="python literal-block">
def findlongestrepeater(string):
    def flr(lr, curseq, s):
        return lr if len(s) == 0 else character_match(lr, curseq, s)

    def character_match(lr, curseq, s):
        if s[0] == curseq[0]:
            return sequence_length(lr, u&quot;&quot;.join([s[0],curseq]), s)
        else:
            return flr(lr, s[0], s[1:])

    def sequence_length(lr, newseq, s):
        if len(newseq) &gt; len(lr):
            return flr(newseq, newseq, s[1:])
        else:
            return flr(lr, newseq, s[1:])

    return flr(string[0], string[0], string[1:])
</pre>
<p><tt class="docutils literal"><span class="pre">flr</span></tt> takes arguments of the longest repeating sequence found so far, the current sequence, and the rest of the string. We kick it off by passing it the first character as the first two arguments, and then the rest of the string after the first character.</p>
<p>If the rest of string has a length of zero, we’ve reached the end of the string and <tt class="docutils literal"><span class="pre">flr</span></tt> returns the longest repeating sequence it was passed.</p>
<p>Otherwise, it calls <tt class="docutils literal"><span class="pre">character_match</span></tt>, which checks whether or not the current sequence matches the first character in the string. If not, it goes back to <tt class="docutils literal"><span class="pre">flr</span></tt> passing in the next character and the rest of the string; if so, it goes on to <tt class="docutils literal"><span class="pre">sequence_length</span></tt> passing in the longest repeater, the new sequence (which is the first character in the string plus the current sequence), and the string. <tt class="docutils literal"><span class="pre">sequence_length</span></tt> will then call <tt class="docutils literal"><span class="pre">flr</span></tt> with either the new sequence as the longest repeater, or the current longest repeater as the longest repeater.</p>
<p>It was pretty hard for me to approach the problem this way. It took me about forty minutes to get a working version, and another fifteen to clean it up (the first version was big jumble of conditionals). It’s also much harder to troubleshoot than the imperative version, at least for me. Recursion isn’t that hard to handle, but I really wanted to use variables just to make things clearer—for example, in <tt class="docutils literal"><span class="pre">character_match</span></tt>, I really want to replace <tt class="docutils literal"><span class="pre">u&quot;&quot;.join([s[0],curseq])</span></tt> with <tt class="docutils literal"><span class="pre">newseq</span> <span class="pre">=</span> <span class="pre">u&quot;&quot;.join([s[0],curseq])</span></tt> and then call <tt class="docutils literal"><span class="pre">sequence_length</span></tt> with <tt class="docutils literal"><span class="pre">newseq</span></tt> as the second argument, purely to make what’s going on more explicit.</p>
<p>It was definitely an interesting experiment, and in future I might try some exercises where I have to take functions and rewrite them without using assignment. I’m sure there are cases where this makes sense; I’m also sure that the above script would be a lot easier to deal with in a proper functional language (or perhaps using the <tt class="docutils literal"><span class="pre">functional</span></tt> module).</p>
<p>After doing that last night, this morning I came across an <a href="http://blog.dhananjaynene.com/2010/02/functional-programming-with-python-part-1/" title="Functional Programming with Python – Part 1" >introduction to functional programming with Python</a>.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/07/16/metaweb-acquired-by-google/">Metaweb Acquired by Google</a> <span class="related-post-date timestamp">Fri 16 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/07/15/unit-testing-as-game/">Unit Testing as Game</a> <span class="related-post-date timestamp">Thu 15 Jul 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/09/python-flattenconcantenate-comparisons/">Python Flatten/Concantenate Comparisons</a> <span class="related-post-date timestamp">Fri 09 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/06/public-projects-finishing-things-and-bitbucket/">Public Projects, Finishing Things, and bitbucket</a> <span class="related-post-date timestamp">Tue 06 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/05/refactoring-geeky-enjoyment-and-readability/">Refactoring, Geeky Enjoyment, and Readability</a> <span class="related-post-date timestamp">Mon 05 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/25/a-little-more-functional-programming/">A Little More Functional Programming</a> <span class="related-post-date timestamp">Thu 25 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/">Some Vim Script Implementation, Testing, and Hackery</a> <span class="related-post-date timestamp">Tue 16 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/02/23/minor-foray-into-functional-programming/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Some Vim Script Implementation, Testing, and Hackery</title>
		<link>http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/</link>
		<comments>http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 07:50:47 +0000</pubDate>
		<dc:creator>Tadhg</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[Jython]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[text editing]]></category>
		<category><![CDATA[Vim]]></category>

		<guid isPermaLink="false">http://tadhg.com/wp/?p=2690</guid>
		<description><![CDATA[As a result of my porting over jEdit (Jython) macros to Vim, I now have a fair amount of (Python) Vim scripts, and have learned some things about how to set up those scripts. I&#8217;ll go through some of that below, and hopefully other people writing Python scripts for Vim will find it useful.

In jEdit, [...]]]></description>
			<content:encoded><![CDATA[<p>As a result of my porting over <a class="reference external" href="http://jedit.org/">jEdit</a> (Jython) macros to <a class="reference external" href="http://www.vim.org/">Vim</a>, I now have a fair amount of (Python) Vim scripts, and have learned some things about how to set up those scripts. I&#8217;ll go through some of that below, and hopefully other people writing Python scripts for Vim will find it useful.<br />
<span id="more-2690"></span><br />
In jEdit, you invoke macros either by selecting them from a menu (clearly unacceptable) or by opening the <a class="reference external" href="http://www.jedit.org/users-guide/action-bar.html">Action Bar</a> (Ctrl-Enter, for me) and then typing the name of the macro, where “name” means the non-extension part of the filename. I put my macro files went in a subdirectory of the macros directory, and there were namespace issues—all macro names had to be unique, and also couldn&#8217;t match any internal jEdit actions. Furthermore, you couldn&#8217;t pass arguments to them. Despite those issues, it was a powerful and quick piece of functionality, and I wanted to make Vim at least match it.</p>
<p>You can put Python directly into Vim script files, but I wanted to do that as minimally as possible. I added a Vim script that would (essentially) include a Python file, and then I had that Python file import from other Python files as necessary. The Python file includes a class, <tt class="docutils literal"><span class="pre">TBase</span></tt>, that contains the functions I want to run; as much code as possible is kept out of those functions and is in other files—files which ideally are individually testable.</p>
<p>To get to those functions from within Vim, I did this:</p>
<pre class="literal-block">
if filereadable($HOME.&quot;/.vim/plugin/tadhg/tadhg.py&quot;)
    pyfile $HOME/.vim/plugin/tadhg/tadhg.py
endif

&quot; Create the commands pointing the Python in tadhg.py:
if !exists(&quot;:T&quot;)
  command! -range -nargs=+ T python tadhgbase = TBase('rs=&lt;line1&gt; rf=&lt;line2&gt;'); tadhgbase('&lt;args&gt;')
endif

nmap &lt;D-CR&gt; :T
</pre>
<p>That code goes in a Vim script that goes in <tt class="docutils literal"><span class="pre">~/.vim/plugins/tadhg/</span></tt>; it&#8217;s loaded when Vim is. This means that the code in <tt class="docutils literal"><span class="pre">tadhg.py</span></tt> is evaluated at Vim start, so the <tt class="docutils literal"><span class="pre">TBase</span></tt> class is available. Furthermore the user Ex mode command “T” creates a new instance of <tt class="docutils literal"><span class="pre">TBase</span></tt> and then calls it with whatever the user enters after “T”. Finally, Command-Enter is mapped to enter Ex mode and type “T ”, which is quite close indeed to the jEdit functionality I had, but without the disadvantages. I have much more control over the namespace, and I can pass arguments.</p>
<p>When the T command is invoked, a new <tt class="docutils literal"><span class="pre">TBase</span></tt> instance is created and it gets passed the range start and range end line numbers from Vim, which is pretty important for some of the functions. Then the new instance is called, with the argument of whatever was typed after “T ”.</p>
<p>This is the code for handling that latter aspect:</p>
<pre class="python literal-block">
def __call__(self, argstring):
    &quot;&quot;&quot;
    The first arg is the command; the rest are arguments to that command.
    &quot;&quot;&quot;
    args = argstring.split(u&quot; &quot;)

    #Need to extract the keyword args out of args
    kwargs = dict([(arg.split(&quot;=&quot;)[0], arg.split(&quot;=&quot;)[1]) for arg in s.split(&quot; &quot;) if &quot;=&quot; in arg])
    args = [arg for arg in s.split(&quot; &quot;) if &quot;=&quot; not in arg]

    if args and args[0] in self.__class__.__dict__.keys():
        import types
        f = self.__class__.__dict__[args[0]]
        if type(f) == types.FunctionType:
            if args[1:]:
                f(self, *args[1:])
            else:
                f(self)
    else:
        print &quot;no command by that name&quot;
</pre>
<p>In other words, if the first (non-keyword) argument matches the name of a function in the class, run it and pass the rest of the (non-keyword) arguments to it. If I ever need keyword arguments as well, I&#8217;ll add the ability to pass them along too.</p>
<p>In order to actually manipulate Vim from these scripts, you have to use <tt class="docutils literal"><span class="pre">import</span> <span class="pre">vim</span></tt>. When I started writing this, I wasn&#8217;t sure how I&#8217;d test that, and I tried to keep the meat of the code in other files, e.g.:</p>
<pre class="python literal-block">
def mpc(self):
    &quot;&quot;&quot;
    Count the words, then insert them into the document's word count line.
    &quot;&quot;&quot;
    from write_wordcount import WriteWordcount
    wwc = WriteWordcount(tadhgbase)
    wwc.vim_main(vim)
</pre>
<p>(Note that I use <tt class="docutils literal"><span class="pre">import</span> <span class="pre">sys;</span> <span class="pre">sys.path.append(myscriptdir)</span></tt> at the top of the file to make these imports work.)</p>
<p>One of the advantages of this construction is that <tt class="docutils literal"><span class="pre">WriteWordCount</span></tt> can theoretically be used as a standalone script, on any file, and also that its <tt class="docutils literal"><span class="pre">vim_main</span></tt> method takes <tt class="docutils literal"><span class="pre">vim</span></tt> as an argument. For testing purposes, I had to created a <tt class="docutils literal"><span class="pre">MockVim</span></tt> class, which currently looks like this:</p>
<pre class="python literal-block">
class MockVimBuffer(object):

    def __init__(self):
        self.lines = []

    def __contains__(self, item):
        return item in self.lines

    def __iter__(self):
        return self.lines.__iter__()

    def __getitem__(self, index):
        return self.lines.__getitem__(index)

    def __setitem__(self, index, value):
        return self.lines.__setitem__(index, value)

class MockVimCurrent(object):

    def __init__(self):
        self.__dict__[&quot;buffer&quot;] = MockVimBuffer()

    def __setattr__(self, attr, value):
        if attr == &quot;buffer&quot;:
            self.__dict__[&quot;buffer&quot;].lines = value
        else:
            self.__dict__[attr] = value

class MockVim(object):

    def __init__(self):
        self.current = MockVimCurrent()
        self.commands = []

    def eval(self, command):
        command_list = {
            &quot;&amp;ft&quot;: lambda: self.rawmodes,
            &quot;exists('b:TotalWordCount')&quot;: lambda: False,
            &quot;tvar&quot;: lambda: self.tvar,

        }
        return command_list.get(command, lambda: &quot;&quot;)()

    def command(self, command):
        self.commands.append(command)
</pre>
<p>The <tt class="docutils literal"><span class="pre">eval</span></tt> method in <tt class="docutils literal"><span class="pre">MockVim</span></tt> simply returns whatever was appropriate for various tests I was running; I should change it to return <tt class="docutils literal"><span class="pre">self.command_list.get(command,</span> <span class="pre">lambda:</span> <span class="pre">&quot;&quot;)()</span></tt> instead, and make <tt class="docutils literal"><span class="pre">command_list</span></tt> an instance variable so that the various tests can manipulate it as needed instead of having to put specific commands in the base code.</p>
<p>Because the methods in <tt class="docutils literal"><span class="pre">TBase</span></tt> pass <tt class="docutils literal"><span class="pre">vim</span></tt> along to the instances or methods of the modules they import, testing those modules is relatively simple: in the test, you create a new <tt class="docutils literal"><span class="pre">MockVim</span></tt> object, call it <tt class="docutils literal"><span class="pre">vim</span></tt>, and then pass it along instead.</p>
<p>So everything is great (and testable). Unless, that is, you (meaning me) lapse from full test-driven development discipline and bits and pieces of functionality creep into <tt class="docutils literal"><span class="pre">TBase</span></tt>. Because <tt class="docutils literal"><span class="pre">TBase</span></tt> has that <tt class="docutils literal"><span class="pre">import</span> <span class="pre">vim</span></tt> line at the top of it and running it when you&#8217;re not actually in Vim produces an <tt class="docutils literal"><span class="pre">ImportError</span></tt>.</p>
<p>The right way to deal with this is to refactor <tt class="docutils literal"><span class="pre">TBase</span></tt> to take <tt class="docutils literal"><span class="pre">vim</span></tt> as one of its initialization arguments, and then have it set that as an instance variable, and then pass that in its methods, while also altering the line in the parent Vim script to:</p>
<pre class="literal-block">
command! -range -nargs=+ T python import vim; tadhgbase = TBase(vim, 'rs=&lt;line1&gt; rf=&lt;line2&gt;'); tadhgbase('&lt;args&gt;')
</pre>
<p>That way <tt class="docutils literal"><span class="pre">TBase</span></tt> is much easier to test, since the fake <tt class="docutils literal"><span class="pre">vim</span></tt> can be passed in at test time. However, for a bunch of reasons I didn&#8217;t want to do that just yet, partly because it means some reasonably heavy refactoring of pieces of code that I use every day—without tests, because the whole issue here is that <tt class="docutils literal"><span class="pre">TBase</span></tt> isn&#8217;t testable. So I wanted a way to make it testable while altering as little of its existing code (which I know currently works, after all) as possible. This took me a while to figure out, and is rather hacky—but it works.</p>
<p>First, in the test file, do this:</p>
<pre class="python literal-block">
from mockvim import MockVim
#Hack a mock Vim into the global namespace so that we can actually test:
import __builtin__
mv = MockVim()
__builtin__.mv = mv
from tadhg import TBase
</pre>
<p>Then alter the <tt class="docutils literal"><span class="pre">import</span> <span class="pre">vim</span></tt> line above the <tt class="docutils literal"><span class="pre">TBase</span></tt> class to instead read:</p>
<pre class="python literal-block">
try:
    import vim
except ImportError:
    import __builtin__
    vim = __builtin__.mv
</pre>
<p>What this really does is hack a giant global variable, <tt class="docutils literal"><span class="pre">vim</span></tt>, into all of the Python that&#8217;s run after those lines in the test file. Normally doing this seems like a rather bad idea, but it&#8217;s also rather necessary to handle the less-than-ideal situation I&#8217;m dealing with. Once I have the test harness using this hackery running properly, I&#8217;ll feel a lot better about switching over to a better architecture.</p>
<p>Tags: <a href="http://tadhg.com/wp/tag/coding/" rel="tag">coding</a>, <a href="http://tadhg.com/wp/tag/jython/" rel="tag">Jython</a>, <a href="http://tadhg.com/wp/tag/python/" rel="tag">python</a>, <a href="http://tadhg.com/wp/tag/software/" rel="tag">software</a>, <a href="http://tadhg.com/wp/tag/tech/" rel="tag">tech</a>, <a href="http://tadhg.com/wp/tag/text-editing/" rel="tag">text editing</a>, <a href="http://tadhg.com/wp/tag/vim/" rel="tag">Vim</a></p><h4 class='related-posts-header'>Related Posts</h4><ul class="related-posts-list"><li class="related-post"><a href="http://tadhg.com/wp/2010/02/14/first-post-with-vim/">First Post With Vim</a> <span class="related-post-date timestamp">Sun 14 Feb 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/01/17/better-word-count-in-vim/">Better Word Count in Vim</a> <span class="related-post-date timestamp">Sun 17 Jan 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/16/sabbatical-close/">sabbatical.close()</a> <span class="related-post-date timestamp">Sun 16 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/04/29/improving-a-python-word-counting-function/">Improving a Python Word Counting Function</a> <span class="related-post-date timestamp">Thu 29 Apr 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/19/better-word-count-in-jedit/">Better Word Count in jEdit</a> <span class="related-post-date timestamp">Sun 19 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2010/05/28/some-futurist-speculation-on-screen-interfaces/">Some Futurist Speculation on Screen Interfaces</a> <span class="related-post-date timestamp">Fri 28 May 2010</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/09/24/rtf_word_restructuredtext-toolchain/">RTF/Word–reStructuredText Toolchain</a> <span class="related-post-date timestamp">Thu 24 Sep 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/08/02/python-script-for-subversion-status/">Python Script for Subversion Status</a> <span class="related-post-date timestamp">Sun 02 Aug 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/28/better-rest-wordpress-pipeline/">Better reST–WordPress Pipeline</a> <span class="related-post-date timestamp">Tue 28 Jul 2009</span></li><li class="related-post"><a href="http://tadhg.com/wp/2009/07/17/jedit-macros-in-python/">jEdit Macros in Python</a> <span class="related-post-date timestamp">Fri 17 Jul 2009</span></li></ul>]]></content:encoded>
			<wfw:commentRss>http://tadhg.com/wp/2010/02/16/some-vim-script-implementation-testing-and-hackery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
