<?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>Artful Code &#187; Tips</title>
	<atom:link href="http://www.artfulcode.net/categories/tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.artfulcode.net</link>
	<description>Resources and tips for dynamic, interactive languages.</description>
	<lastBuildDate>Fri, 09 Sep 2011 02:15:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>My thoughts on Blackberry OS 6</title>
		<link>http://www.artfulcode.net/articles/my-thoughts-on-blackberry-os-6/</link>
		<comments>http://www.artfulcode.net/articles/my-thoughts-on-blackberry-os-6/#comments</comments>
		<pubDate>Mon, 16 May 2011 01:32:12 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Soap box]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[blackberry]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=840</guid>
		<description><![CDATA[I have been using Blackberry OS 6 on my Bold 9650 (pre-installed) for a few weeks. I love some of the new functionality, especially search and the new context menus. Search works very similarly to Spotlight on OSX. The new context menus do a good job of splitting common contextual options out of the BB menu. I also like the quicker boot time.]]></description>
			<content:encoded><![CDATA[<p>I have been using Blackberry OS 6 on my Bold 9650 (pre-installed) for a few weeks. I love some of the new functionality, especially search and the new context menus. Search works very similarly to Spotlight on OSX. The new context menus do a good job of splitting common contextual options out of the BB menu. I also like the quicker boot time.<span id="more-840"></span></p>
<p>It feels pretty top heavy, though. I think they tried to bolt the QNX UI on top of BB OS, but without the power and efficiency underneath the hood to make it perform adequately on my handset. The 9650 seems high end for OS 5 but low end for OS 6. Some of the rendering, smooth scrolling, and transparency effects really bog down the system, at least on the 9650’s hardware.</p>
<p>The only other real problem I have with it is that it is missing a feature I really like from OS 5 &#8211; the ability to send a picture via MMS directly from the browser.</p>
<p>For a while, I used an OS 5 theme which eliminated many of the more expensive UI elements, like app tabs, but at some point I lost the ability to use themes, even after a clean install.</p>
<p>So for now, I’m back to OS 5, and my phone is much snappier again. Oh well. Better to be a big fish in a little pond, I suppose.</p>
<p>&nbsp;</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F&amp;title=My+thoughts+on+Blackberry+OS+6" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F&amp;title=My+thoughts+on+Blackberry+OS+6" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=My+thoughts+on+Blackberry+OS+6&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F&amp;title=My+thoughts+on+Blackberry+OS+6" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F&amp;title=My+thoughts+on+Blackberry+OS+6" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F&amp;title=My+thoughts+on+Blackberry+OS+6" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+My+thoughts+on+Blackberry+OS+6+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fmy-thoughts-on-blackberry-os-6%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/my-thoughts-on-blackberry-os-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blackberry Bridge and the Playbook</title>
		<link>http://www.artfulcode.net/articles/blackberry-bridge-and-the-playbook/</link>
		<comments>http://www.artfulcode.net/articles/blackberry-bridge-and-the-playbook/#comments</comments>
		<pubDate>Mon, 02 May 2011 23:44:32 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Soap box]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[blackberry]]></category>
		<category><![CDATA[playbook]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[rim]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=832</guid>
		<description><![CDATA[After silently drooling over the usefulness of my wife's iPad for the last few months, I finally gave in to temptation and decided to get a tablet. Of course, being a Blackberry man, I was ecstatic about the release of the Playbook. The Playbook OS is QNX, and ultra fast, light-weight, real time unix that I have been a fan of since college. I always felt that it would have been a wonderful system for Apple to have built OSX on, but it seems that Blackberry at least gets to beat Apple to the punch on something, anyway.]]></description>
			<content:encoded><![CDATA[<p>After silently drooling over the usefulness of my wife&#8217;s iPad for the last few months, I finally gave in to temptation and decided to get a tablet. Of course, being a Blackberry man, I was ecstatic about the release of the Playbook. The Playbook OS is QNX, and ultra fast, light-weight, real time unix that I have been a fan of since college. I always felt that it would have been a wonderful system for Apple to have built OSX on, but it seems that Blackberry at least gets to beat Apple to the punch on something, anyway. <span id="more-832"></span></p>
<p>The Playbook has suffered from a rash of poor reviews, largely due to the lack of apps and RIM&#8217;s decision to release without  the native PIM suite ready. These things obviously detract from the experience, especially the absence of email and messaging software.</p>
<p>I try to take the long view, though. This is a brand new tablet platform, and software environment will eventually get a complete host of apps, some useful, some not, just as is the case with the Apple app store as well as the Android marketplace. For the moment, though, it is mostly filled with what appear to be very mediocre experiments with the platform. Very few are worth the money at the moment.</p>
<p>The system is very slick, though. The navigation becomes very natural with very little effort, and the browser is lightening fast. The bridge functionality is excellent, although it will frustrate the unenlightened (read: non-Blackberry users) that it requires a Blackberry hand set to use.</p>
<p>Bridge is extremely cool. It gets overlooked as a stop-gap until RIM releases the official, native PIM, but it gives Blackberry users something important that a more typical suite might easily overlook. Messages are pushed to a Blackberry, rather than synchronized, as is the case with IMAP. Bridge maintains control over those messages on the hand held, rather than the tablet. That&#8217;s the right way, because a phone is going to stay with you much more than a tablet (new toy syndrome notwithstanding).</p>
<p>Bridge gives me an extra piece of awesome, too. The Bridge Browser, while not running at native speed, provides a decent web experience without tethering charges. That not only saves me money, but it keeps me feeling young by letting me pretend that I am sticking it to the man, and you just can&#8217;t put a price on that.</p>
<p>Therefore, I really hope that bridge is not condemned once RIM releases their PIM suite. I really want to see them add to it and give it the polish that RIM is so good at. I hope it continues as a special extra for BB users, and becomes fully integrated, which is one of the major areas of polish were RIM lords it over the competition</p>
<p>On another note, I also very humbly ask that whoever is in charge of the keyboard make it behave exactly as it does on my Blackberry. I am tired of having to type apostrophes and capitalize with a separate button, thank you very much.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F&amp;title=Blackberry+Bridge+and+the+Playbook" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F&amp;title=Blackberry+Bridge+and+the+Playbook" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Blackberry+Bridge+and+the+Playbook&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F&amp;title=Blackberry+Bridge+and+the+Playbook" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F&amp;title=Blackberry+Bridge+and+the+Playbook" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F&amp;title=Blackberry+Bridge+and+the+Playbook" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Blackberry+Bridge+and+the+Playbook+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fblackberry-bridge-and-the-playbook%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/blackberry-bridge-and-the-playbook/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>From TextMate to Vim</title>
		<link>http://www.artfulcode.net/articles/from-textmate-to-vim/</link>
		<comments>http://www.artfulcode.net/articles/from-textmate-to-vim/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 15:13:06 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[textmate]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=756</guid>
		<description><![CDATA[TextMate is an excellent editor, but it is beginning to show its age. It has a few squeaky wheels that have yet to be oiled, and it looks as though the author may be getting bogged down in the minutiae of his next release. With the next version apparently due sometime after the colonization of Mars, it seemed an auspicious time to try out another editor.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.macromates.com">TextMate</a> is an excellent editor, but it is beginning to show its age. It has a few squeaky wheels that have yet to be oiled, and it looks as though the author may be getting bogged down in the minutiae of his next release. With the <a href="http://blog.macromates.com/2009/working-on-it/">next version</a> apparently due sometime after the colonization of Mars, it seemed an auspicious time to try out another editor.<span id="more-756"></span></p>
<h3>What I like about TextMate</h3>
<p>Let me repeat that I like TextMate. I have happily used it for years. It has some wonderful features. It is reasonably fast and its indentation is great. It has a great selection of plugins for a wide variety of languages and is easy to extend with new language modules. It has a decent macro system based on regular expressions that, while not nearly as powerful as scripted editors, provides 80% of what most users need.</p>
<h3>Problems with TextMate</h3>
<p>TextMate, for all its sterling qualities &#8211; and there are many &#8211; has a few problems that, while not deal-breakers in themselves, together provide a less-than-satisfactory experience.</p>
<h4>Split-windows</h4>
<p>This is a rather stark issue, and is a feature that has been promised in the next release. Nevertheless, its absence often means either filling my screen with open TextMate windows or firing up emacs when I need to look at many files at once &#8211; or many parts of the same file at once. C, in particular, tends toward long functions, and is especially painful to write in TextMate.</p>
<h4>Large files</h4>
<p>TextMate handles many open files well, but a single large file will hang the entire application. I can accept a large file taking a long time to load, but please! Load the file in the background, so that I can keep working. Even opening a large file in a second window blocks the entire application. Find and replace also choke on larger documents, sometimes taking minutes to complete.</p>
<h4>Key-bindings</h4>
<p>TextMate&#8217;s key-bindings can be puzzling. Many common commands (especially in Python), such as converting between spaces and tabs in a document, don&#8217;t have bindings and are several levels deep in the menu. Other commands of dubious utility are given simple bindings, such as &#8220;Execute line/selection inserting result&#8221; (control-R.) Many have extremely difficult combinations, such as control-alt-command-D to toggle to project drawer, or control-option-shift-P to toggle text mode (and then &#8211; because several bundles use this same key-binding, god knows why &#8211; you are given a drop-down to choose which command you wanted.)</p>
<h3>Choosing a new editor</h3>
<p>I was initiated into the cult of emacs in college and have used it for several years. I&#8217;ve played with BBEdit (which I think is horribly cluttered and completely lost in the pre-OSX world), NetBeans, and Eclipse (which is, amazingly, slower and clunkier than NetBeans.) I love emacs&#8217; extensibility and its indentation is second to none. It suffers from the key-binding issue as well, though. Becoming efficient in emacs is a journey, not a destination. I find myself spending more time navigating its arcane and bureaucratic configuration system than actually writing code in it.</p>
<p>NetBeans in some ways seems very polished, and the new Python module is very good (I have <a href="http://www.artfulcode.net/articles/python-in-netbeans/">written about this</a> before.) Refactoring across files is extremely useful. It has good debugger integration. Unfortunately, tight integration with any particular language costs a great deal in load times and can lead to an unresponsive UI. And for god&#8217;s sake &#8211; why does it have to be such a chore to open a file outside of a project?</p>
<p>Panic&#8217;s Coda is pretty and has some neat features, but in the end, SubEthaEdit (its editor) has poor syntax support and its extension system feels very clunky. Editra is nice, but <em>slow</em> and buggy on OSX.</p>
<h3>Vim</h3>
<p>After a disappointing look around the net for better choices, I decided to give Vim another try. I had a passing familiarity with some of its basic functionality from my days as a system administrator, it is scriptable, and it has a large number of plugins for syntax support.</p>
<h4>Lack of distractions</h4>
<p>Overall, I am satisfied with Vim&#8217;s minimalism. Its indentation is pretty second rate, but I can live with it. Vim feels extremely comfortable. Over the years, Vim has gently washed away all of the &#8220;features&#8221; of an editor that actually get in the programmer&#8217;s way and come up with a system that drastically increases productivity and makes coding a more satisfying experience.</p>
<h4>Load speed</h4>
<p>While not the primary measure of an editor, load time is important. How many programmers (myself included) give up on Eclipse or NetBeans right away because it takes more than half a minute to start up? Load time is one of those things that, while really just an annoyance, can completely color the experience of using a program. Vim loads quickly. It is one less thing to get in the way of productivity.</p>
<h4>Efficiency</h4>
<p>Nothing beats Vim for efficiency. If you ever wonder why so many applications have modes that mimic Vim, it is because once you learn Vim&#8217;s bindings, there is nothing faster. Jumping around a file with precision is a breeze. Coming from emacs, I expected it to take a lot longer to become comfortable with Vim&#8217;s style and bindings, but it has a much milder learning curve than emacs. Search and replace is also fast and easy to use. I quickly found myself giving up <a href="http://code.google.com/p/macvim/">MacVim</a> in favor of the command line. Copy and paste &#8211; the biggest barrier to command-line editors for me &#8211; is fast and easy with Vim&#8217;s visual mode.</p>
<h4>Other features</h4>
<p>Vim 7 has auto-complete, although I rarely use it. I&#8217;m much more comfortable with an enormous stack of O&#8217;Reilly books. Vim&#8217;s code folding is also very nice. I generally turn code folding off because it slows most editors down so drastically, but it does not appear to affect Vim.</p>
<p>Two of Vim&#8217;s features really stand out for me: reformatting text and retabbing a document. I love being able to convert a file&#8217;s tabs to spaces just by typing <code>:retab</code>. It is much more efficient than having to go through two levels of menus in TextMate. And being able to reformat Python doc strings is very useful. It removes an annoyance that can make updating documentation a real chore.</p>
<h3>Conclusion</h3>
<p>Vim strikes the perfect balance for me. At first glance, it seems archaic, especially for those born after the mouse became standard. After a few days of using it, though, I find myself enabling Vim bindings mode in any application that has it, using the <a href="https://addons.mozilla.org/en-US/firefox/addon/4891">Vimperator plugin for Firefox</a>, and wishing that OSX&#8217;s terminal was more easily scriptable. If you haven&#8217;t used Vim, give it a chance. Coming from a graphic editor like TextMate, it is a much different experience and, arguably, a more satisfying one.</p>
<p>Here are some other folks&#8217; experiences with the transition in both directions:</p>
<ul>
<li><a href="http://weblog.jamisbuck.org/2008/10/10/coming-home-to-vim">Coming home to Vim</a></li>
<li><a href="http://cosine.org/2007/08/25/vim-textmate/">From Vim to TextMate</a></li>
</ul>
Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.
<p><strong>Edit [2009-08-03 15:50]:</strong> added links to similar stories</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F&amp;title=From+TextMate+to+Vim" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F&amp;title=From+TextMate+to+Vim" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=From+TextMate+to+Vim&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F&amp;title=From+TextMate+to+Vim" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F&amp;title=From+TextMate+to+Vim" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F&amp;title=From+TextMate+to+Vim" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+From+TextMate+to+Vim+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Ffrom-textmate-to-vim%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/from-textmate-to-vim/feed/</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>Compiling Pike 7.8 on OSX PPC</title>
		<link>http://www.artfulcode.net/articles/compiling-pike-78-on-osx-ppc/</link>
		<comments>http://www.artfulcode.net/articles/compiling-pike-78-on-osx-ppc/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 21:49:12 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[pike]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=540</guid>
		<description><![CDATA[Pike 7.8 did not compile out of the box on my Mac, so I figured I would write up what it took to get it working.]]></description>
			<content:encoded><![CDATA[<p>Pike 7.8 did not compile out of the box on my Mac, so I figured I would write up what it took to get it working.<span id="more-540"></span></p>
<p>The initial problem was getting it to find the MySQL headers and libraries installed by macports, which was easy enough to fix.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">LDCONFIG</span>=<span style="color: #ff0000;">&quot;-L/opt/local/mysql/lib&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> LDCONFIG
<span style="color: #007800;">CPPFLAGS</span>=<span style="color: #ff0000;">&quot;-I/opt/local/include/mysql5&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> CPPFLAGS</pre></div></div>

<p>It found the files it needed, but it still didn&#8217;t pass the test.  It complained about not finding various API functions in the MySQL library. It turns out that it was detecting my system as 64bit (when it is in fact 32).  For that, I had to run make with CONFIGUREARGS:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #007800;">CONFIGUREARGS</span>=<span style="color: #ff0000;">&quot;--with-abi=32&quot;</span></pre></div></div>

<p>&#8230;and that did it.  Thank god for the good folks in #pike on irc.freenode.net!</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F&amp;title=Compiling+Pike+7.8+on+OSX+PPC" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F&amp;title=Compiling+Pike+7.8+on+OSX+PPC" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Compiling+Pike+7.8+on+OSX+PPC&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F&amp;title=Compiling+Pike+7.8+on+OSX+PPC" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F&amp;title=Compiling+Pike+7.8+on+OSX+PPC" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F&amp;title=Compiling+Pike+7.8+on+OSX+PPC" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Compiling+Pike+7.8+on+OSX+PPC+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcompiling-pike-78-on-osx-ppc%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/compiling-pike-78-on-osx-ppc/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Profiling a Lisp application</title>
		<link>http://www.artfulcode.net/articles/profiling-lisp-application/</link>
		<comments>http://www.artfulcode.net/articles/profiling-lisp-application/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 21:28:38 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[slime]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/profiling-lisp-application/</guid>
		<description><![CDATA[Profiling is one of the most important steps in writing software. Once a package is written, profiling greatly helps to identify bottlenecks and inefficiencies by showing how an application spends its time. How to profile a lisp application is a common question among those new to lisp. Luckily, profiling lisp is simple with emacs and [...]]]></description>
			<content:encoded><![CDATA[<p>Profiling is one of the most important steps in writing software.  Once a package is written, profiling greatly helps to identify bottlenecks and inefficiencies by showing how an application spends its time.  How to profile a lisp application is a common question among those new to lisp.  Luckily, profiling lisp is simple with emacs and <a href="http://common-lisp.net/project/slime/">slime</a>.<span id="more-22"></span></p>
<p>There are several slime profiling functions, but the simplest is <code>slime-profile-package</code> (<code>M-x slime-profile-package</code>), which profiles all functions in a package.  You will be asked for the package name to profile.  All functions in the package will be profiled. <code>slime-profile-functions</code> gives you more control over which functions to profile.  The profiling of a single function can be controlled with <code>slime-toggle-profile-fdefinition</code>.</p>
<p>After entering the package name, you are asked whether to record the most common callers and whether to profile methods as well as typical functions.  To view the results, you use <code>slime-profile-report</code>, which displays a table of the most commonly called functions, time spent in each, amount of consing in each, calls, total time, etc.</p>
<p>Before the next run, be sure to use <code>M-x slime-profile-reset</code> to reset the profiling statistics so you get a fresh and accurate report.</p>
<h3>Optimizing functions</h3>
<p>Generally, you should attempt to write a more efficient algorithm before depending on compiler optimization declarations.  The slime profiler will tell you which functions are taking the majority of your application&#8217;s time, and making these more efficient will serve you better than tuning the manner in which a function is compiled.  However, once your function is written to your satisfaction, you may wish to further tune it by sacrificing speed for lower memory usage (or vice versa) or trading debug information for extra speed.</p>
<p>Lisp compilers accept a few optimization declarations that can earn you significant speed-ups.  The compiler generally optimizes code based on four variables: speed, safety, debug, and compilation-speed.  These can be set between 0 and 3 with a declaration:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> foo <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span>declare <span style="color: #66cc66;">&#40;</span>optimize <span style="color: #66cc66;">&#40;</span>speed <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>
                        <span style="color: #66cc66;">&#40;</span>safety <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
                        <span style="color: #66cc66;">&#40;</span>debug <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
                        <span style="color: #66cc66;">&#40;</span>compilation-speed <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#40;</span>format t <span style="color: #ff0000;">&quot;~&amp;amp;Hello world~%&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Generally, lowering the debug value of a function makes trouble-shooting your application extremely difficult.  For example, the name of the function may disappear from backtraces.  Therefore, lowering this value is usually only worthwhile once the program has been suitably tested and deployed.  Use the profiler to determine which portions of your code will provide the most benefit.</p>
<h4>Macros and optimization</h4>
<p>Macros are sometimes touted as a way to optimize code.  In a compiled lisp program, they can cause some calculations and expansions to be performed at compile time, saving run-time.  In situations where much of the information is known ahead of time, this can be an effective technique, although overuse can be dangerous.  For example, rewriting a function as a macro will make debugging more difficult, since the macro is expanded in the compiled code.  A problem in a macro may only be shown as a problem in the function that utilizes the macro.</p>
<p>Note that in interpreted lisps, especially those without any form of compilation (such as newLISP), macros provide no speed-up.  In fact, in newLISP, macros are just functions that do not evaluate their arguments.</p>
<h4>More info</h4>
<p><a href="http://common-lisp.net/project/slime/doc/html/Profiling.html#Profiling">slime profiling documentation</a></p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F&amp;title=Profiling+a+Lisp+application" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F&amp;title=Profiling+a+Lisp+application" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Profiling+a+Lisp+application&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F&amp;title=Profiling+a+Lisp+application" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F&amp;title=Profiling+a+Lisp+application" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F&amp;title=Profiling+a+Lisp+application" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Profiling+a+Lisp+application+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fprofiling-lisp-application%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/profiling-lisp-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimizing regular expressions</title>
		<link>http://www.artfulcode.net/articles/optimizing-regular-expressions/</link>
		<comments>http://www.artfulcode.net/articles/optimizing-regular-expressions/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 19:43:17 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[regexp]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/optimizing-regular-expressions/</guid>
		<description><![CDATA[We lispers generally look down our noses at regular expressions. Regular expressions are ugly. They are not expressive. However, they are a reality of programming. When used with care, they can express complex text patterns concisely. Writing software almost always means processing some form of user input. When the format of that input is pre-determined [...]]]></description>
			<content:encoded><![CDATA[<p>We lispers generally look down our noses at regular expressions.  Regular expressions are ugly.  They are not expressive.  However, they are a reality of programming.  When used with care, they can express complex text patterns concisely.<span id="more-27"></span></p>
<p>Writing software almost always means processing some form of user input.  When the format of that input is pre-determined and (mostly) guaranteed to be valid, regular expressions are just so much overhead.  But when the validity of user input can vary widely, such as with form validation, regular expressions are much more concise than writing a custom parser.</p>
<h4>Regular expressions are slower for simple matching</h4>
<p>A regular expression must be compiled.  Incautiously crafted patterns can take up quite a bit of memory or result in poorly performing matches.  Routines that make heavy use of regular expressions can quickly become a bottlneck.</p>
<p>If a match operation doesn&#8217;t need features of regular expressions, such as alternating patterns or backreferences, it is faster to use string matching.  It takes much less time to see if a string is terminated by a semi-colon in Python using <code>string.endswith(';')</code> than <code>re.compile(r';$').search(string)</code>, especially over many iterations.</p>
<p>The exception is when a pattern is matched often over lengthy iterations.  Once compiled, regular expression matching is O(log n).  Regular string matching is typically O(n).  However, it generally takes an extraordinarily large number of iterations before regular expressions become more efficient than string matching.</p>
<h4>Optimizing for speed</h4>
<p><a href="http://www.oreilly.com/catalog/regex3/">Entire books</a> have been written on this subject.  Here are a few tips.</p>
<p>Alternating patterns (such as <code>(abc|def)</code>) can be expensive.  Always try to put the pattern most likely to match first (<code>(John|Rumplestiltskin)</code>, rather than <code>(Rumplestiltskin|John)</code>).</p>
<p>Avoid nesting repeating patterns when possible.  They grow quickly in memory and increase the number of possible matches exponentially (thereby slowing a match down noticeably).</p>
<p>As the target string gets longer, matching slows drastically when using repeating patterns.  Follow indefinite patterns with quantifiers (<code>{min, max}</code>) or with a literal or atomic group.</p>
<p>When possible, use anchors (<code>^</code> and <code>$</code>) or lookahead/lookbehind to limit the scope of a pattern and make failures occur faster.</p>
<h4>Optimizing for memory usage</h4>
<p>Some types of expressions can grow to quite large sizes in memory.  A <a href="http://regexkit.sourceforge.net/Documentation/pcre/pcreperform.html">little reading</a> shows how apparently simple expressions can grow when compiled:</p>
<pre><code>(abc|def){2,4}
is compiled as if it were
(abc|def)(abc|def)((abc|def)(abc|def)?)?
</code></pre>
<p>Indefinite and large quantifiers (<code>*</code>, <code>+</code>, and <code>{min,max}</code>) are expanded.  Imagine if the example above were <code>(abc|def){2,1000}</code>, or if the pattern matched were more complex and contained internal quantifiers, such as <code>(abc+|def){2,1000}</code>.  A little care is needed to prevent such exponential expansion.</p>
<p>One solution is to use a subroutine.  Although slower, a subroutine calls back a previous match without the memory-eating expansion:</p>
<pre><code>(abc+|def)(?1){1,999}
</code></pre>
<p>The subroutine backreferences the first grouped match and repeats it.  However, subroutine matches are treated as atomic groups.  When an indefinite match fails, the engine will typically backtrack and see if a smaller substring of the target matches.</p>
<p>For example, <code>\w+0</code> matches one or more letters followed by a zero.  If it is matched against &#8220;abcdefg0&#8243;, it matches all of the letters and the zero.  If it is matched against &#8220;abcdefg1&#8243;, it will backtrack and attempt to match against substrings of the target (&#8220;abcdefg&#8221;, &#8220;abcdef&#8221;, &#8220;abcde&#8221;, &#8230;).</p>
<p>This may or may not be the desired behavior, but it will keep the pattern&#8217;s footprint down.</p>
<h4>Links</h4>
<ul>
<li> <a href="http://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast</a></li>
<li> <a href="http://regexkit.sourceforge.net/Documentation/pcre/pcreperform.html">RegexKit docs</a></li>
<li> <a href="http://blog.stevenlevithan.com/archives/faster-trim-javascript">Faster JavaScript Trim</a></li>
</ul>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F&amp;title=Optimizing+regular+expressions" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F&amp;title=Optimizing+regular+expressions" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Optimizing+regular+expressions&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F&amp;title=Optimizing+regular+expressions" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F&amp;title=Optimizing+regular+expressions" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F&amp;title=Optimizing+regular+expressions" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Optimizing+regular+expressions+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Foptimizing-regular-expressions%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/optimizing-regular-expressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Psyco and Django</title>
		<link>http://www.artfulcode.net/articles/psyco-and-django/</link>
		<comments>http://www.artfulcode.net/articles/psyco-and-django/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 22:25:06 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/psyco-and-django/</guid>
		<description><![CDATA[Psyco is a module that optimizes Python applications on the fly. Numerous resources online describe how to use psyco in a Django-powered application to speed it up. My experiences with this has been less than wonderful. I wrote a simple middleware class to import psyco as suggested here: # Be sure to only load on [...]]]></description>
			<content:encoded><![CDATA[<p>Psyco is a module that optimizes Python applications on the fly.  Numerous resources online describe how to use psyco in a Django-powered application to speed it up.<span id="more-34"></span></p>
<p>My experiences with this has been less than wonderful.  I wrote a simple middleware class to import psyco as suggested <a href="http://code.djangoproject.com/wiki/PsycoMiddleware">here</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Be sure to only load on the proper architecture</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">platform</span> <span style="color: #ff7700;font-weight:bold;">import</span> architecture
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> settings.<span style="color: black;">DEBUG</span> <span style="color: #ff7700;font-weight:bold;">and</span> architecture<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'32bit'</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> architecture<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'32bit'</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #ff7700;font-weight:bold;">import</span> psyco
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
            <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PsycoMiddleware<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> process_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Do not waste time trying to optimize the re module</span>
        psyco.<span style="color: black;">cannotcompile</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Limit memory usage</span>
        psyco.<span style="color: #dc143c;">profile</span><span style="color: black;">&#40;</span>memory=<span style="color: #ff4500;">2048</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span></pre></div></div>

<p>In development this appeared to work fine (we excluded the <code>if not settings.DEBUG</code> portion while testing).  Once we were up and running on the production server, however, mysterious exceptions began to surface.</p>
<p>In particular, we seemed to be &#8220;missing&#8221; on some page hits.  Specifically, we would get TemplateDoesNotExist exceptions when the templates did, in fact, exist.  We were never able to sort that out.  They immediately stopped when we commented out the psyco-related stuff.  We tried changing the memory usage, excluding more items from compilation (including the Django loader classes), all to no avail.</p>
<p>My recommendation is avoidance of psyco in a Django setting.  If someone has an idea what might have caused this, I&#8217;d love to hear an explanation.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F&amp;title=Psyco+and+Django" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F&amp;title=Psyco+and+Django" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Psyco+and+Django&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F&amp;title=Psyco+and+Django" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F&amp;title=Psyco+and+Django" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F&amp;title=Psyco+and+Django" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Psyco+and+Django+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpsyco-and-django%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/psyco-and-django/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Per-user caching in Django</title>
		<link>http://www.artfulcode.net/articles/per-user-caching-django/</link>
		<comments>http://www.artfulcode.net/articles/per-user-caching-django/#comments</comments>
		<pubDate>Tue, 12 Feb 2008 21:22:55 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/per-user-caching-django/</guid>
		<description><![CDATA[Django comes with an easy-to-use caching framework. With a few simple decorators, an application&#8217;s views are cached. Decorators can even be used to control upstream caches, such as those maintained by ISPs. Nevertheless, if a rendered view is customized with information individual to a user, these caching options cease to be useful. Django has several [...]]]></description>
			<content:encoded><![CDATA[<p>Django comes with an easy-to-use caching framework.  With a few simple decorators, an application&#8217;s views are cached.  Decorators can even be used to control upstream caches, such as those maintained by ISPs.  Nevertheless, if a rendered view is customized with information individual to a user, these caching options cease to be useful.  <span id="more-35"></span>Django has several solutions for this scenario:</p>
<pre><code>1. The CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting
2. The vary_on_cookie decorator
3. Template fragment caching
4. The low-level caching API
</code></pre>
<h4>The CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting</h4>
<p>The <code>CACHE_MIDDLEWARE_ANONYMOUS_ONLY</code> setting causes Django to ignore the cache if the user is not anonymous.  This is less helpful than it seems.  At the Dayton Daily News, we require a trivial registration to access many areas of the site.  Using this setting means that the entire page cannot be cached because of a simple &#8220;Welcome, username&#8221; line in the rendered view.</p>
<p>Another obstacle to using the site-level cache is that many demographic-tracking packages require setting client-specific Javascript variables in the rendered view and then accessing a script on another server.  The per-site cache will cache these as well, distorting your analytics.</p>
<h4>The vary_on_cookie decorator</h4>
<p>The <code>vary_on_cookie</code> decorator (found in <code>django.views.decorators.vary</code>) is a simple way to tell upstream caches to cache a view based on the content of the user&#8217;s cookie.  This means that each user will get their own page cached.</p>
<p>This is a useful decorator and a part of any caching setup for user-based sites.  On its own, however, it still means that if a user visits a page only once, your server must perform all the work of rendering a page.  The server gains no benefit when another user visits, since the page must be generated anew and then cached for this user as well.</p>
<h4>Template fragment caching</h4>
<p>This is a new feature in the development version of Django.  It consists of a simple template tag that signals the framework to cache a portion of the rendered template.  For example:</p>
<pre><code>{% load cache %} {# thanks to AdamG for noticing the typo here #}
...stuff you don't want to cache
{ cache 300 "some" "section" user.id }
...stuff you do want to cache
{% endcache %}
...more stuff you don't want to cache
</code></pre>
<p>The cache tag accepts the number of seconds for which the cache should remain valid and a series of keys used to uniquely identify the cache.  You may use any number of keys.  Addng <code>user.id</code> to the mix will make this portion of the template cached on a per-user basis.  Using something static will make it a standard, all-user, cache.</p>
<p>I experimented with template fragment caching while developing an application for which we expected extremely high traffic.  In the end, we decided that the overhead did not justify the savings.</p>
<p>This is a very new feature and naturally not ready for production use.  In the next stable release of Django I imagine that it will be considerably more efficient.</p>
<h4>The low-level caching API</h4>
<p>The low-level caching API is <strong>the</strong> solution for serious fine-tuning of your cache.  It is located in <code>django.core.cache</code>.  It is laughably simple to use:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span>
&nbsp;
CACHE_EXPIRES = <span style="color: #ff4500;">5</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> <span style="color: #808080; font-style: italic;"># 5 minutes</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> some_view<span style="color: black;">&#40;</span>request, object_id<span style="color: black;">&#41;</span>:
    cache_key = <span style="color: #483d8b;">&quot;someobjectcache%s&quot;</span> <span style="color: #66cc66;">%</span> object_id
    object_list = cache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>cache_key<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;">#if not object_list:</span>
    <span style="color: #808080; font-style: italic;">#AdamG noted that this check avoids empty lists</span>
    <span style="color: #808080; font-style: italic;">#evaluating to False, as &quot;if not object_list&quot; did</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> object_list <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        object_list = expensive_lookup<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        cache.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>cache_key, object_list, CACHE_EXPIRES<span style="color: black;">&#41;</span>
    ...</pre></div></div>

<p>The cache is accessed via a unique key.  You can cache anything that can be safely picked in Python, including query sets from Django&#8217;s ORM.  If the cache has expired, <code>cache.get(key)</code> returns <code>None</code>.  Setting a key in the cache requires the unique key, the object to cache, and the time in seconds for which the cache is valid.</p>
<p>Since Django&#8217;s template engine is <a href="http://www.codeirony.com/?p=9">quite fast</a>, we use the low-level API to cache the most expensive portions of each page: large database lookups, search results, the result of filtering large sets of data, ad infinitum.</p>
<p>This has given us the biggest savings in terms of memory, database hits, and CPU usage.</p>
<h4>One final trick</h4>
<p>A couple of our applications are real database hogs.  They have a wide range of queries that get pulled over and over.  Clearly, dropping into raw SQL and pulling lists rather than objects is the best way to streamline this type of demand, but then we lose the benefit of our custom model manager and model methods.  Another neat trick is to add caching to your model manager itself:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">sites</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Site
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">cache</span>
&nbsp;
CACHE_EXPIRES = <span style="color: #ff4500;">5</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> <span style="color: #808080; font-style: italic;"># 10 minutes</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> ObjectManager<span style="color: black;">&#40;</span>models.<span style="color: black;">Manager</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> get_query_set<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        cache_key = <span style="color: #483d8b;">'objectlist%d%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
            Site.<span style="color: black;">objects</span>.<span style="color: black;">get_current</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">id</span>, <span style="color: #808080; font-style: italic;"># unique for site</span>
            <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> a <span style="color: #ff7700;font-weight:bold;">in</span> args<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #808080; font-style: italic;"># unique for arguments</span>
            <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>k<span style="color: black;">&#41;</span>, <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>v<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> k, v <span style="color: #ff7700;font-weight:bold;">in</span> kwargs.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#41;</span>
&nbsp;
        object_list = cache.<span style="color: black;">get</span><span style="color: black;">&#40;</span>cache_key<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">#if not object_list:</span>
        <span style="color: #808080; font-style: italic;">#AdamG noted that this check avoids empty lists</span>
        <span style="color: #808080; font-style: italic;">#evaluating to False, as &quot;if not object_list&quot; did</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> object_list <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
            object_list = <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>ObjectManager, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_query_set</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
            cache.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span>cache_key, object_list, CACHE_EXPIRES<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> object_list</pre></div></div>

<p>This custom model manager caches query sets using the arguments passed to <code>get_query_set()</code>.  If they are fewer than 10 minutes old, they returned from the cache; otherwise, they are returned as a fresh query set and added to the cache.  This technique can be used for busy databases to cache all possible queries performed by your application.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F&amp;title=Per-user+caching+in+Django" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F&amp;title=Per-user+caching+in+Django" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Per-user+caching+in+Django&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F&amp;title=Per-user+caching+in+Django" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F&amp;title=Per-user+caching+in+Django" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F&amp;title=Per-user+caching+in+Django" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Per-user+caching+in+Django+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fper-user-caching-django%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/per-user-caching-django/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Dynamic URLs in Django</title>
		<link>http://www.artfulcode.net/articles/dynamic-urls-django/</link>
		<comments>http://www.artfulcode.net/articles/dynamic-urls-django/#comments</comments>
		<pubDate>Mon, 12 Nov 2007 21:40:00 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/dynamic-urls-django/</guid>
		<description><![CDATA[I long ago switched my company&#8217;s web applications from Code Igniter to Django. The main reasons were Django&#8217;s more powerful database API and Python&#8217;s maintainability and scalability over PHP. The only feature of Code Igniter that I really miss in Django is the ability to add a page without first registering the url, formulating a [...]]]></description>
			<content:encoded><![CDATA[<p>I long ago switched my company&#8217;s web applications from <a href="http://www.codeigniter.com">Code Igniter</a> to <a href="http://www.djangoproject.com">Django</a>.  The main reasons were Django&#8217;s more powerful database API and Python&#8217;s maintainability and scalability over PHP.<span id="more-43"></span></p>
<p>The only feature of Code Igniter that I really miss in Django is the ability to add a page without first registering the url, formulating a regular expression to describe the parameters and variations of the view function, and then creating the view and template.</p>
<p>For a production website, this is a better method than Code Igniter&#8217;s strategy of http://domain.com/class/method/arg/arg/&#8230;/, but CI&#8217;s is much easier during development.  My urls may change half a dozen (or more) times in the course of the project, especially if marketing or advertising is involved.</p>
<p>Fortunately, there is an easy fix.  A generic, introspective function and a carefully crafted pattern in urls.py can save the day.  The url pattern is simple enough:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^/path/to/app/root/(?P.+?)/(?:(?P.+?)/)?$'</span>, free_pattern<span style="color: black;">&#41;</span></pre></div></div>

<p>Placing this at the end of your urlpatterns tuple will allow any undefined urls to go through this as a last-chance catch-all.  It captures the view as first segment (after the application&#8217;s root path) as well as any other text afterward (leaving out leading and trailing slashes).</p>
<p>Here is the function:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> free_pattern<span style="color: black;">&#40;</span>request, view, segments=<span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span>:
    segments = segments.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        view_fn = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>PATH_TO_APP, view<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> Http404
    <span style="color: #ff7700;font-weight:bold;">return</span> view_fn<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>segments<span style="color: black;">&#41;</span></pre></div></div>

<p>The function is simple enough.  It accepts the request, the view&#8217;s name, and the rest of the segments.  The segments are split by the forward slash to turn them into a list.</p>
<p>If the view is found in the appropriate module (defined using PATH_TO_APP, which should point to whichever application we are talking about), it is run with *segments expanded as its arguments.  If the view is not found, we raise an Http404 error.</p>
<p>This could easily be expanded to introspect the path to the application, but since Django supports a number of different layouts for applications and projects, that will most likely be very customized to your setup.</p>
<p>For example, I typically store my applications in an apps module, each with its own urls.py file that is included at the project level.  That way, an update to an application does not require synchronizing changes across multiple projects.</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F&amp;title=Dynamic+URLs+in+Django" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F&amp;title=Dynamic+URLs+in+Django" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Dynamic+URLs+in+Django&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F&amp;title=Dynamic+URLs+in+Django" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F&amp;title=Dynamic+URLs+in+Django" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F&amp;title=Dynamic+URLs+in+Django" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Dynamic+URLs+in+Django+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fdynamic-urls-django%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/dynamic-urls-django/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Art is rough</title>
		<link>http://www.artfulcode.net/articles/art-rough/</link>
		<comments>http://www.artfulcode.net/articles/art-rough/#comments</comments>
		<pubDate>Fri, 01 Jun 2007 21:57:00 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Soap box]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[newlisp]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/articles/art-rough/</guid>
		<description><![CDATA[Why&#8217;s Poignant Guide claims that after learning Ruby you will write code so elegant it will make you cry. Paul Graham was not so dramatic, but he was closer to the mark. Lisp teaches you the elegance and grace of recursive and applicative programming. This creates beautiful and concise code. Unfortunately, there is sometimes quite [...]]]></description>
			<content:encoded><![CDATA[<p>Why&#8217;s Poignant Guide claims that after learning Ruby you will write code so elegant it will make you cry.  Paul Graham was not so dramatic, but he was closer to the mark.  Lisp teaches you the elegance and grace of recursive and applicative programming.  This creates beautiful and concise code.<span id="more-59"></span></p>
<p>Unfortunately, there is sometimes quite a bit of overhead associated with it.  On the newLisp forums, someone <a href="http://www.alh.net/newlisp/phpbb/viewtopic.php?p=9135" class="broken_link">asked for help</a> replacing items from one list that matched items from another.  He has two lists; list one contains about 30,000 strings.  List two is a two dimensional list containing about 100,000 strings total.</p>
<p>The idea is to check for equality against the 30k strings in list one on each of the cells in list two, then replace that with a predefined string if equality is met.</p>
<p>The elegant solution is to use applicative and recursive algorithms.  Naturally, the forum user used a recursive function, ref-all, which provides an index of placement of an atom in a list (i.e. <code>(ref-all "baz" '("foo" "bar" "baz" "bat"))</code> =&gt; 2).  Then he mapped a lambda to list one that ref-all&#8217;d the item from list one in list two, replacing it with &#8220;FOO&#8221;.</p>
<p>The problem was that this was using a recursive function on a huge list over and over again, and newLisp is not optimized for large lists of strings as it is.  It turns out that I was able to speed it up by using one of newLisp&#8217;s iterators, dolist, which simply iterates over a list.  The code I ended up with was:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> 'relacement <span style="color: #ff0000;">&quot;FOO&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">dolist</span> <span style="color: #66cc66;">&#40;</span>o one<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">dolist</span> <span style="color: #66cc66;">&#40;</span>r <span style="color: #66cc66;">&#40;</span>ref-all o two<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span>nth-<span style="color: #b1b100;">set</span> <span style="color: #66cc66;">&#40;</span>two r<span style="color: #66cc66;">&#41;</span> replacement<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>This reduced execution time by almost 10% on my machine (granted, my machine is powered by hamsters).</p>
<p>This just goes to show, efficiency is more important than elegance.  If the code doesn&#8217;t do what it needs to do in an effective manner, what does it matter how pretty it is?</p>
<!-- Social Bookmarks BEGIN -->
<div class="social_bookmark">
<a><strong><em>Submit article</em></strong></a>
<br />
<div class="d">
<br />
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://del.icio.us/post?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F&amp;title=Art+is+rough" rel="nofollow" title="Add to&nbsp;Del.icio.us"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/delicious.png" title="Add to&nbsp;Del.icio.us" alt="Add to&nbsp;Del.icio.us" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F&amp;title=Art+is+rough" rel="nofollow" title="Add to&nbsp;digg"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/digg.png" title="Add to&nbsp;digg" alt="Add to&nbsp;digg" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.dzone.com/links/add.html?description=Art+is+rough&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F&amp;title=Art+is+rough" rel="nofollow" title="Add to&nbsp;DZone"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/dzone.png" title="Add to&nbsp;DZone" alt="Add to&nbsp;DZone" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F" rel="nofollow" title="Add to&nbsp;Facebook"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/facebook.png" title="Add to&nbsp;Facebook" alt="Add to&nbsp;Facebook" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F&amp;title=Art+is+rough" rel="nofollow" title="Add to&nbsp;reddit"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/reddit.png" title="Add to&nbsp;reddit" alt="Add to&nbsp;reddit" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F&amp;title=Art+is+rough" rel="nofollow" title="Add to&nbsp;Stumble Upon"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/stumbleupon.png" title="Add to&nbsp;Stumble Upon" alt="Add to&nbsp;Stumble Upon" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://www.technorati.com/faves?add=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F" rel="nofollow" title="Add to&nbsp;Technorati"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/technorati.png" title="Add to&nbsp;Technorati" alt="Add to&nbsp;Technorati" /></a>
<a onclick="window.open(this.href, '_blank', 'scrollbars=yes,menubar=no,height=600,width=750,resizable=yes,toolbar=no,location=no,status=no'); return false;" href="http://twitter.com/home/?status=Check+out+Art+is+rough+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fart-rough%2F" rel="nofollow" title="Add to&nbsp;Twitter"><img class="social_img" src="http://www.artfulcode.net/wp-content/plugins/social-bookmarks/images/twitter.png" title="Add to&nbsp;Twitter" alt="Add to&nbsp;Twitter" /></a>
<br />
</div>
</div>
<!-- Social Bookmarks END -->
]]></content:encoded>
			<wfw:commentRss>http://www.artfulcode.net/articles/art-rough/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

