<?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; Programming</title>
	<atom:link href="http://www.artfulcode.net/categories/programming/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>goto statement considered</title>
		<link>http://www.artfulcode.net/articles/goto-statement-considered/</link>
		<comments>http://www.artfulcode.net/articles/goto-statement-considered/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 03:09:40 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Soap box]]></category>
		<category><![CDATA[goto]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=816</guid>
		<description><![CDATA[Everyone knows not to use goto, right?  Dijkstra's words on the subject have risen to the level of gospel in the programming community. Not that I do not completely agree... in most cases.]]></description>
			<content:encoded><![CDATA[<p>Everyone knows not to use goto, right?  Dijkstra&#8217;s words on the subject have risen to the level of gospel in the programming community. Not that I do not completely agree&#8230; in most cases.<span id="more-816"></span></p>
<p>I have to admit that I occasionally resort to goto myself. This week was one such an occasion. But before you pick up your torch and farming implement of choice and join the mob heading for my castle gates, please consider that  Dijkstra&#8217;s letter was complaining about unrestricted goto, which was a popular feature of languages at the time. It was an unstructured precursor of the subroutine and structured programming, which put goto on a leash and taught it not to bark at the neighbors. In restricting goto to local jumps, as most modern languages supporting the feature do, the beast became much less fearsome. In fact, a while loop is just a structured goto, as is try/catch (albeit with a little extra magic.)</p>
<p>Perl, of course, does not impose such restrictions on a programmer (although it does prohibit jumping into blocks that require initialization, such as other functions.) With a little discipline, though, goto is a feature and quite useful. It can be used to make extremely complex loops explicit and easy to follow as well as allow a loop to break to any outer loop in the current call stack.</p>
<p>As an example, I recently wrote a function to increment a string of arbitrary alphanumeric characters, where letters must maintain their case but increment as base-26 numbers and numbers increment normally (base 10). For example, if a letter increments past z, it becomes a and the next character to the left is then incremented. The increment logic fit into a function that took two of these strings and calculated all possible values in between to support some limited set operations against two alphanumeric ranges.</p>
<p>My original code for the increment logic was grisly at best. It took a series of nested while loops and state variables that were incremented or decremented as needed. I avoided recursion because the sequences were of arbitrary length. Breaking the code into subroutines made it more complex to maintain loop state. Using goto allowed me to break apart the logic into blocks without the overhead or state-passing necessary to shoehorn the logic into subroutines. I was able to label each part clearly and jump between them as needed to increment or &#8220;carry the 1.&#8221; I reduced the size of the code to just a couple dozen lines, including safety checks, and found that the goto code was much easier to read and reason about.</p>
<p>That said, I want to emphasize strongly that goto should be kept local. Jumping to outer function calls makes the logic of a program difficult to reason about and changes scope in confusing ways. But as a way of structuring complex loops and iterative logic, you just can&#8217;t beat goto.</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%2Fgoto-statement-considered%2F&amp;title=goto+statement+considered" 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%2Fgoto-statement-considered%2F&amp;title=goto+statement+considered" 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=goto+statement+considered&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fgoto-statement-considered%2F&amp;title=goto+statement+considered" 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%2Fgoto-statement-considered%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%2Fgoto-statement-considered%2F&amp;title=goto+statement+considered" 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%2Fgoto-statement-considered%2F&amp;title=goto+statement+considered" 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%2Fgoto-statement-considered%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+goto+statement+considered+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fgoto-statement-considered%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/goto-statement-considered/feed/</wfw:commentRss>
		<slash:comments>9</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>Runtime ChoiceField filtering in Django&#8217;s admin</title>
		<link>http://www.artfulcode.net/articles/runtime-choicefield-filtering-in-djangos-admin/</link>
		<comments>http://www.artfulcode.net/articles/runtime-choicefield-filtering-in-djangos-admin/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 13:34:03 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=741</guid>
		<description><![CDATA[Django 1.x brought with it much finer grained control over the admin application with admin forms and inline form sets. However, I still keep running into the same problem that I have since I started using Django &#8211; you cannot provide a limited queryset for a select field that depends on other instance variables. Take [...]]]></description>
			<content:encoded><![CDATA[<p>Django 1.x brought with it much finer grained control over the admin application with admin forms and inline form sets. However, I still keep running into the same problem that I have since I started using Django &#8211; you cannot provide a limited queryset for a select field that depends on other instance variables.<span id="more-741"></span></p>
<p>Take this trivial example:</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;">db</span> <span style="color: #ff7700;font-weight:bold;">import</span> models
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Sport<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    name = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Season<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    starts = models.<span style="color: black;">DateField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    ends = models.<span style="color: black;">DateField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    sport = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Sport<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Team<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    name = models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
    sport = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Sport<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Game<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    season = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Season<span style="color: black;">&#41;</span>
    home_team = models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Team, related_name=<span style="color: #483d8b;">&quot;home_games&quot;</span><span style="color: black;">&#41;</span>
    away_team = modesl.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Team, related_name=<span style="color: #483d8b;">&quot;away_games&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>In the admin change form for <code>Game</code>, it is obviously desirable to only permit teams to be selected that match the <code>Season</code>&#8216;s <code>Sport</code>. Unfortunately, because fields are defined on the <em>class</em> rather than the <em>instance</em> (such as inside of <code>__init__</code>), there is no obvious way to create a relationship based on the values in the instance.</p>
<p>Inside the <code>ModelAdmin</code> class is the method <code>get_formset(self, request, obj=None, **kwargs)</code>. The parameter <code>obj</code> stores the current instance, if any. The significance of this is that this method is a hook with access to the instance data and is called for every form as it is built.</p>
<p>That makes it possible to filter the <code>Teams</code> based on the current form&#8217;s instance.</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: #ff7700;font-weight:bold;">import</span> admin
<span style="color: #ff7700;font-weight:bold;">from</span> django <span style="color: #ff7700;font-weight:bold;">import</span> forms
<span style="color: #ff7700;font-weight:bold;">from</span> myapp.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Team, Game
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> game_form_factory<span style="color: black;">&#40;</span>sport<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">class</span> RuntimeGameForm<span style="color: black;">&#40;</span>forms.<span style="color: black;">ModelForm</span><span style="color: black;">&#41;</span>:
        home_team = forms.<span style="color: black;">ModelChoiceField</span><span style="color: black;">&#40;</span>label=<span style="color: #483d8b;">&quot;Home&quot;</span>,
                queryset=Team.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>sport=sport<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        away_team = forms.<span style="color: black;">ModelChoiceField</span><span style="color: black;">&#40;</span>label=<span style="color: #483d8b;">&quot;Away&quot;</span>,
                queryset=Team.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>sport=sport<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
            model = Game
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> RuntimeGameForm
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> GameAdmin<span style="color: black;">&#40;</span>admin.<span style="color: black;">modelAdmin</span><span style="color: black;">&#41;</span>:
    model = Game
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_formset<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, obj=<span style="color: #008000;">None</span>, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> obj <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">form</span> = game_form_factory<span style="color: black;">&#40;</span>obj.<span style="color: black;">season</span>.<span style="color: black;">sport</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>GameAdmin, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_formset</span><span style="color: black;">&#40;</span>request, obj, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span></pre></div></div>

<p>Here is how it works. When the <code>GameAdmin</code> form is built, <code>get_formset</code> is called. If this is an edit form (add form&#8217;s will not have instance data) the <code>Game</code> instance is passed as the <code>obj</code> parameter. In this case, the instance sets the form attribute to be the result of calling <code>game_form_factory</code>, which is a class factory function.</p>
<p>What if we want the <code>Game</code> form to be an inline form for the <code>Season</code> form? The major difference with inline form sets is that the instance passed to <code>get_formset</code> is now that of the parent form, rather than the form set model (in this case, <code>Season</code> instead of <code>Game</code>.)</p>
<p>The class factory function remains essentially unchanged. The <code>Game</code> admin model requires only a small change.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> GameAdminInline<span style="color: black;">&#40;</span>admin.<span style="color: black;">TabularInline</span><span style="color: black;">&#41;</span>:
    model = Game
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_formset<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, obj=<span style="color: #008000;">None</span>, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> obj <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">form</span> = game_form_factory<span style="color: black;">&#40;</span>obj.<span style="color: black;">sport</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># obj is a Season</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>GameAdminInline, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_formset</span><span style="color: black;">&#40;</span>request, obj,
                <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span></pre></div></div>

<!-- 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%2Fruntime-choicefield-filtering-in-djangos-admin%2F&amp;title=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin" 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%2Fruntime-choicefield-filtering-in-djangos-admin%2F&amp;title=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin" 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=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fruntime-choicefield-filtering-in-djangos-admin%2F&amp;title=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin" 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%2Fruntime-choicefield-filtering-in-djangos-admin%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%2Fruntime-choicefield-filtering-in-djangos-admin%2F&amp;title=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin" 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%2Fruntime-choicefield-filtering-in-djangos-admin%2F&amp;title=Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin" 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%2Fruntime-choicefield-filtering-in-djangos-admin%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+Runtime+ChoiceField+filtering+in+Django%26%238217%3Bs+admin+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fruntime-choicefield-filtering-in-djangos-admin%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/runtime-choicefield-filtering-in-djangos-admin/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Pointers, arrays, and string literals</title>
		<link>http://www.artfulcode.net/articles/pointers-arrays-and-string-literals/</link>
		<comments>http://www.artfulcode.net/articles/pointers-arrays-and-string-literals/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 12:52:56 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[c]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=698</guid>
		<description><![CDATA[A recently posted question on Stack Overflow highlighted a common misconception about the role of pointers and arrays held by many programmers learning C.]]></description>
			<content:encoded><![CDATA[<p>A recently posted <a href="http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c/">question on Stack Overflow</a> highlighted a common misconception about the role of pointers and arrays held by many programmers learning C.<br />
<span id="more-698"></span><br />
The confusion stems from a misunderstanding concerning the role of pointers and strings in C. A pointer is an address in memory. It often points to an index in an array, such as in the function <code>strtoupper</code> in the following code:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> strtoupper<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>  <span style="color: #666666; font-style: italic;">// null ptr check, courtesy of Michael</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>str <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// destructively modify the contents at the current pointer location</span>
            <span style="color: #666666; font-style: italic;">// using the dereference operator to access the value at the current</span>
            <span style="color: #666666; font-style: italic;">// pointer address.</span>
            <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #339933;">++</span>str<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> my_str<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span>
    strtoupper<span style="color: #009900;">&#40;</span>my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><code>my_str</code> is actually a pointer to a block of memory holding chars. This allows us to use address math to access indices of the array and modify them using the dereference operator. In fact, an array index such as <code>my_str[3]</code> is identical to the expression <code>*(my_str + 3)</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span> my_str<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">*</span>my_str <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>my_str <span style="color: #339933;">+</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>my_str <span style="color: #339933;">+</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// prints, &quot;Hello World&quot;</span></pre></div></div>

<p>However, if <code>my_str</code> is declared as a char pointer to the string literal &#8220;hello world&#8221; rather than a char array, these operations fail:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>my_str <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">*</span>my_str <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// fails</span>
<span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>my_str <span style="color: #339933;">+</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>my_str <span style="color: #339933;">+</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// fails</span>
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> my_str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Let&#8217;s explore the difference between the two declarations.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>a <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> b<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;hello world&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>In the compiled program, it is likely that &#8220;hello world&#8221; is stored literally inside the executable. It is effectively an immutable, constant value. Pointing <code>char *a</code> to it provides the scope with read-only access to an immutable block of memory. Therefore, attempting to assign a value might cause other code that points to the same memory to behave erratically (read <a href="http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c/1011545#1011545">this response to the above post on Stack Overflow</a> for an excellent explanation of this behavior.)</p>
<p>The declaration of <code>char b[]</code> instead declares a locally allocated block of memory that is then filled with the chars, &#8220;hello world&#8221;. <code>b</code> is now a pointer to the first address of that array. The complete statement, combining the declaration and assignment, is shorthand. Dispensing with the array size (e.g., <code>char</code> instead of <code>char[12]</code>) is permitted as the compiler is able to ascertain its size from the string literal it was assigned.</p>
<p>In both cases the pointer is used to access array indices:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%c&quot;</span><span style="color: #339933;">,</span> toupper<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>However, only with <code>b</code> is the program able to modify the values in memory, since it is explicitly copied to a mutable location on the stack in its declaration:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span>
    b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> toupper<span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<!-- 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%2Fpointers-arrays-and-string-literals%2F&amp;title=Pointers%2C+arrays%2C+and+string+literals" 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%2Fpointers-arrays-and-string-literals%2F&amp;title=Pointers%2C+arrays%2C+and+string+literals" 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=Pointers%2C+arrays%2C+and+string+literals&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpointers-arrays-and-string-literals%2F&amp;title=Pointers%2C+arrays%2C+and+string+literals" 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%2Fpointers-arrays-and-string-literals%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%2Fpointers-arrays-and-string-literals%2F&amp;title=Pointers%2C+arrays%2C+and+string+literals" 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%2Fpointers-arrays-and-string-literals%2F&amp;title=Pointers%2C+arrays%2C+and+string+literals" 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%2Fpointers-arrays-and-string-literals%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+Pointers%2C+arrays%2C+and+string+literals+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fpointers-arrays-and-string-literals%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/pointers-arrays-and-string-literals/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Custom session storage with newLISP Web</title>
		<link>http://www.artfulcode.net/articles/custom-session-storage-with-newlisp-web/</link>
		<comments>http://www.artfulcode.net/articles/custom-session-storage-with-newlisp-web/#comments</comments>
		<pubDate>Fri, 29 May 2009 18:35:52 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[newlisp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=684</guid>
		<description><![CDATA[The Web module's default session storage engine uses serialized contexts in the /tmp directory. The advantage of this method is that, apart from the directory (which is customizable), it is reasonably platform independent and has low overhead. The disadvantages of this are numerous. Files are stored unencrypted, so anyone with access to the server may view them. It is therefor advantageous to design a custom storage module for sessions.]]></description>
			<content:encoded><![CDATA[<p><a href="http://static.artfulcode.net/newlisp/web.lsp.html">The Web module&#8217;s</a> default session storage engine uses serialized contexts in the <em>/tmp</em> directory. The advantage of this method is that, apart from the directory (which is customizable), it is reasonably platform independent and has low overhead. The disadvantages of this are numerous. Files are stored unencrypted, so anyone with access to the server may view them. It is therefor advantageous to design a custom storage module for sessions.<span id="more-684"></span></p>
<p>Storing sessions in a database is a good solution. Backups are easier; persistence and pruning orphaned sessions are simpler. Security is available through the database server&#8217;s security.  We will use MySQL, since it is the best supported in newLISP.</p>
<h2>Setting up the database</h2>
<p>First, we need a table in which to store session data. Using a MySQL <code>TIMESTAMP</code> column will provide us with an automatically updating time stamp on the last modification of the session, which we will use below to find old sessions to remove.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> sessions <span style="color: #66cc66;">&#40;</span>
	sid VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">,</span>
	<span style="color: #993333; font-weight: bold;">DATA</span> TEXT <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
	ts TIMESTAMP
<span style="color: #66cc66;">&#41;</span></pre></div></div>

<h2>Designing the storage module</h2>
<p>Several functions need to be defined to handle storing data. First, we must ensure that the <a href="http://www.newlisp.org/code/modules/mysql.lsp.html">MySQL module</a> is loaded and initialized. We will do this in a separate module that we will call <code>DBSessions</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">context</span> 'DBSessions<span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">unless</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">sym</span> <span style="color: #3AA43E;">&quot;MYSQL&quot;</span> 'MySQL <span style="color: #2028B8;">nil</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; do not reinitialize if already loaded</span>
  <span style="color: #AF0500;">&#40;</span>module <span style="color: #3AA43E;">&quot;mysql5.lsp&quot;</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; with newlisp 10.1, this will change to &quot;mysql.lsp&quot;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">init</span><span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">connect</span> <span style="color: #3AA43E;">&quot;127.0.0.1&quot;</span> <span style="color: #3AA43E;">&quot;user&quot;</span> <span style="color: #3AA43E;">&quot;secret&quot;</span> <span style="color: #3AA43E;">&quot;somedb&quot;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">context</span> '<span style="color: #2028B8;">MAIN</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>Next, we define a function to create or resume a session from the database. Sessions are stored in memory as contexts, making our job easier. Our function will query MySQL to see if the session id exists, and either create a new session and insert it or retrieve an existing session and load it. The function <code>Web:session-id</code> gives us the current session id from the session cookie or creates a new one and sends the client a cookie to store it. <code>Web:session-context</code> returns a symbol pointed to the context storing the current session.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>open-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">when</span> <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;SELECT data FROM sessions WHERE sid = '%s'&quot;</span> <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
    <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">let</span> <span style="color: #AF0500;">&#40;</span><span style="color: #AF0500;">&#40;</span>data <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">fetch-row</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
      <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">if</span> data
        <span style="color: #808080; font-style: italic;">;; Evaluate the serialized context into the current session context</span>
        <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">eval-string</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">first</span> data<span style="color: #AF0500;">&#41;</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
        <span style="color: #808080; font-style: italic;">;; Create a new session and save it</span>
        <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;INSERT INTO sessions (sid, data) VALUES ('%s', '%s')&quot;</span>
          <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
          <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">source</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>Next, we need a function to write any changes to the session to storage. Since the session is stored as a context, this is quite simple.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>close-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;UPDATE sessions SET data = '%s' WHERE sid = '%s'&quot;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">source</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>We also need a function to delete entire sessions when necessary. This is also simple.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>delete-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;DELETE FROM sessions WHERE sid = '%s'&quot;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>Finally, a function to cull old sessions from the database. For this, we use the variable <code>Web:SESSION_MAX_AGE</code> to determine which sessions have expired.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>clean-sessions<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;DELETE FROM sessions WHERE NOW() &gt;= DATE_ADD(ts, INTERVAL %d SECOND)&quot;</span>
    Web:<span style="color: #2028B8;">SESSION_MAX_AGE</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<h2>Registering the handler in Web</h2>
<p>Last, the handler functions need to be registered in the <code>Web</code> module.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">define-session-handlers</span>
  open-session close-session delete-session clean-sessions<span style="color: #AF0500;">&#41;</span></pre></div></div>

<h2>Putting it all together</h2>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">unless</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">sym</span> <span style="color: #3AA43E;">&quot;MYSQL&quot;</span> 'MySQL <span style="color: #2028B8;">nil</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; do not reinitialize if already loaded</span>
  <span style="color: #AF0500;">&#40;</span>module <span style="color: #3AA43E;">&quot;mysql5.lsp&quot;</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; with newlisp 10.1, this will change to &quot;mysql.lsp&quot;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">init</span><span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">connect</span> <span style="color: #3AA43E;">&quot;127.0.0.1&quot;</span> <span style="color: #3AA43E;">&quot;user&quot;</span> <span style="color: #3AA43E;">&quot;secret&quot;</span> <span style="color: #3AA43E;">&quot;somedb&quot;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">context</span> 'DBSessions<span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>open-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">when</span> <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;SELECT data FROM sessions WHERE sid = '%s'&quot;</span> <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
    <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">let</span> <span style="color: #AF0500;">&#40;</span><span style="color: #AF0500;">&#40;</span>data <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">fetch-row</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
      <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">if</span> data
        <span style="color: #808080; font-style: italic;">;; Evaluate the serialized context into the current session context</span>
        <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">eval-string</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">first</span> data<span style="color: #AF0500;">&#41;</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
        <span style="color: #808080; font-style: italic;">;; Create a new session and save it</span>
        <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;INSERT INTO sessions (sid, data) VALUES ('%s', '%s')&quot;</span>
          <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
          <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">source</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>close-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;UPDATE sessions SET data = '%s' WHERE sid = '%s'&quot;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">source</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-</span><span style="color: #2028B8;">context</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>delete-session<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;DELETE FROM sessions WHERE sid = '%s'&quot;</span>
    <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">escape</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session-id</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">define</span> <span style="color: #AF0500;">&#40;</span>clean-sessions<span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span>MySQL:<span style="color: #2028B8;">query</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">format</span> <span style="color: #3AA43E;">&quot;DELETE FROM sessions WHERE NOW() &gt;= DATE_ADD(ts, INTERVAL %d SECOND)&quot;</span>
    Web:<span style="color: #2028B8;">SESSION_MAX_AGE</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">define-session-handlers</span>
  open-session close-session delete-session clean-sessions<span style="color: #AF0500;">&#41;</span>
&nbsp;
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">context</span> '<span style="color: #2028B8;">MAIN</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<!-- 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%2Fcustom-session-storage-with-newlisp-web%2F&amp;title=Custom+session+storage+with+newLISP+Web" 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%2Fcustom-session-storage-with-newlisp-web%2F&amp;title=Custom+session+storage+with+newLISP+Web" 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=Custom+session+storage+with+newLISP+Web&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcustom-session-storage-with-newlisp-web%2F&amp;title=Custom+session+storage+with+newLISP+Web" 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%2Fcustom-session-storage-with-newlisp-web%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%2Fcustom-session-storage-with-newlisp-web%2F&amp;title=Custom+session+storage+with+newLISP+Web" 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%2Fcustom-session-storage-with-newlisp-web%2F&amp;title=Custom+session+storage+with+newLISP+Web" 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%2Fcustom-session-storage-with-newlisp-web%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+Custom+session+storage+with+newLISP+Web+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fcustom-session-storage-with-newlisp-web%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/custom-session-storage-with-newlisp-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A better newLISP web library</title>
		<link>http://www.artfulcode.net/articles/a-better-newlisp-web-library/</link>
		<comments>http://www.artfulcode.net/articles/a-better-newlisp-web-library/#comments</comments>
		<pubDate>Fri, 29 May 2009 13:32:29 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[newlisp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=648</guid>
		<description><![CDATA[One problem from which newLISP suffers is the lack of a really useful library for web-based applications. The <a href="http://newlisp.nfshost.com/code/modules/cgi.lsp.html">official CGI module</a> has serious enough problems to justify an entirely new library. After some thought, I decided moreover that the <a href="http://static.artfulcode.net/newlisp/request.lsp.html">request</a> and <a href="http://static.artfulcode.net/newlisp/response.lsp.html">response</a> modules that I designed were neither practical nor sufficient. To that end, I have designed a new, monolithic library to provide the essential functionality required for web programming]]></description>
			<content:encoded><![CDATA[<p>One problem from which newLISP suffers is the lack of a really useful library for web-based applications. The <a href="http://newlisp.nfshost.com/code/modules/cgi.lsp.html">official CGI module</a> has serious enough problems to justify an entirely new library. After some thought, I decided moreover that the <a href="http://static.artfulcode.net/newlisp/request.lsp.html">request</a> and <a href="http://static.artfulcode.net/newlisp/response.lsp.html">response</a> modules that I designed were neither practical nor sufficient. To that end, I have designed a new, monolithic library to provide the essential functionality required for web programming.<span id="more-648"></span></p>
<p>The official CGI module has some real issues. First, it combines POST and GET variables into a single structure. This has two serious consequences: 1) the application has no way to determine the method by which a parameter is passed (that information is completely lost), and 2) name clashes between GET and POST result in the loss of one or the other parameter (in the case of the CGI module, GET information would be overwritten.)</p>
<p>Another issue in the CGI module is with the <code>put-page</code> function, which breaks if &#8220;%&gt;&#8221; is used inside of a code island, even legitimately, such as in a string.</p>
<p><a href="http://static.artfulcode.net/newlisp/web.lsp.html">Web</a> fixes both of these problems and provides a number of other features, including:</p>
<ul>
<li>ASP/PHP-style templates</li>
<li>Getting/setting cookies, GET, and POST parameters</li>
<li>Entity encoding and decoding</li>
<li>HTTP header control</li>
<li>Sessions</li>
<li>Custom session storage</li>
<li>URL building and parsing</li>
<li>URL encoding and decoding</li>
<li>Query string building and parsing</li>
</ul>
<p>Additionally, Web does not suffer from the GET/POST issues that the CGI module does, nor does it mishandle tags inside of code.</p>
<h2>HTTP Headers</h2>
<p>Headers are set using <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_header"><code>Web:header</code></a>, which accepts two parameters &#8211; the header name and the header value. By default, one header is already set: <strong>Content-type: text/html</strong>. Headers are output using <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_send-headers"><code>Web:send-headers</code></a>, which is called before any other output. The convenience function <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_redir"><code>Web:redir</code></a> redirects the browser to the passed URL.</p>
<h2>GET and POST</h2>
<p>GET and POST variables are accessed using <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_get"><code>Web:get</code></a> and <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_post"><code>Web:post</code></a>, which may be called in two ways. When called with a single parameter, these functions act like <code>lookup</code> and return the GET/POST parameter with the named key. When called with no parameters, they return an association list of the corresponding query.</p>
<h2>Cookies</h2>
<p>Cookies must be set before headers are sent. They are set using the <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_cookie"><code>Web:cookie</code></a> function, which accepts up to six parameters.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">;; Set a basic cookie</span>
<span style="color: #AF0500;">&#40;</span>cookie <span style="color: #3AA43E;">&quot;foo&quot;</span> <span style="color: #3AA43E;">&quot;bar&quot;</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #808080; font-style: italic;">;; Access a cookie value</span>
<span style="color: #AF0500;">&#40;</span>cookie <span style="color: #3AA43E;">&quot;foo&quot;</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #808080; font-style: italic;">;; Delete a cookie by setting expires to now</span>
<span style="color: #AF0500;">&#40;</span>cookie <span style="color: #3AA43E;">&quot;foo&quot;</span> <span style="color: #2028B8;">nil</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">date-value</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #808080; font-style: italic;">;; Set a cookie that expires in an hour</span>
<span style="color: #AF0500;">&#40;</span>cookie <span style="color: #3AA43E;">&quot;foo&quot;</span> <span style="color: #3AA43E;">&quot;bar&quot;</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">+</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">date-value</span><span style="color: #AF0500;">&#41;</span> <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">*</span> <span style="color: #675400;">60</span> <span style="color: #675400;">60</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>See the <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_cookie">documentation</a> for a full list of accepted parameters.</p>
<h2>Sessions</h2>
<p>By default, sessions use file-based storage (located at /tmp). They are controlled with a few simple functions. The default <code>exit</code> function is wrapped to ensure that <code>Web:close-session</code> is called at the end of a script (at least, a script that calls <code>exit</code> at its end.)</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">open-session</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session</span> <span style="color: #3AA43E;">&quot;foo&quot;</span> <span style="color: #3AA43E;">&quot;bar&quot;</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; store &quot;foo&quot; as &quot;bar&quot;</span>
<span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">send-headers</span><span style="color: #AF0500;">&#41;</span> <span style="color: #808080; font-style: italic;">; start output</span>
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">println</span> <span style="color: #3AA43E;">&quot;&lt;p&gt;&lt;strong&gt;foo is:&lt;/strong&gt; &quot;</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">session</span> <span style="color: #3AA43E;">&quot;foo&quot;</span><span style="color: #AF0500;">&#41;</span> <span style="color: #3AA43E;">&quot;&lt;/p&gt;&quot;</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">exit</span> <span style="color: #675400;">0</span><span style="color: #AF0500;">&#41;</span></pre></div></div>

<p>It is a simple matter to design and use custom storage handlers. The function <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_define-session-handlers"><code>Web:define-session-handlers</code></a> allows customization of which functions are called to begin/load, close/write, delete a session, and clear old sessions. See the <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_define-session-handlers">documentation</a> for a list of helpful functions and variables for custom storage handlers.</p>
<h2>Templates</h2>
<p>Templates work almost identically to the official CGI module, with a few differences. First, <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_eval-template"><code>Web:eval-template</code></a> is called with a string, rather than a file, to permit other storage methods and programmatic building of templates. Second, &lt;%= .. %&gt; may be substituted for the default opening tag as a shortcut for &lt;% (print &#8230; ) %&gt;. Last, the opening and closing tags may be customized by setting values of <code>Web:OPEN_TAG</code> and <code>Web:CLOSE_TAG</code>. The shortcut tag will always be <code>Web:OPEN_TAG</code> appended with and equal sign.</p>
<h2>Encoding and decoding</h2>
<p>There are several functions to make encoding, decoding, and escaping strings easier for dealing with URLs, javascript, and HTML entities.</p>
<p><a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_escape"><code>Web:escape</code></a> takes a string and encodes the basic HTML character entities (apostrophe, quote, ampersand, and left and right angle brackets.) <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_unescape"><code>Web:unescape</code></a> provides the reverse. The function <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_escape-js"><code>Web:escape-js</code></a> does no encoding of entities, but instead ensures that a string may be safely output in javascript string without causing syntax errors.</p>
<p><a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_encode-entities"><code>Web:encode-entities</code></a> encodes all HTML entities, including a number of entities that are not fully supported by all browser. The full list of entities is derived from <a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references">Wikipedia</a>. Its reverse, <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_decode-entities"><code>Web:decode-entities</code></a>, translates entities back into their character equivalents.</p>
<p>The functions <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_url-encode"><code>Web:url-encode</code></a> and <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_url-decode"><code>Web:url-decode</code></a> deal with hex-encoding/decoding strings for use in URLs.</p>
<p>Query strings are easily created using <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_build-query"><code>Web:build-query</code></a>, modeled after the PHP function  <code>http_build_query</code>.  Its counterpart, <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_parse-query"><code>Web:parse-query</code></a>, takes a query string and turns it into an association list.</p>
<p>For URLs, it is simpler to use <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_build-url"><code>Web:build-url</code></a>, which takes a URL and any number of association lists which it uses to build a complete URL. Each alist may overwrite parameters from the previous, including any parameters on the passed URL.</p>

<div class="wp_syntax"><div class="code"><pre class="newlisp" style="font-family:monospace;"><span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">let</span> <span style="color: #AF0500;">&#40;</span><span style="color: #AF0500;">&#40;</span>url <span style="color: #3AA43E;">&quot;http://www.artfulcode.net/?s=newlisp&quot;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
  <span style="color: #AF0500;">&#40;</span><span style="color: #2028B8;">println</span> <span style="color: #AF0500;">&#40;</span>Web:<span style="color: #2028B8;">build-url</span> url '<span style="color: #AF0500;">&#40;</span><span style="color: #AF0500;">&#40;</span><span style="color: #3AA43E;">&quot;s&quot;</span> <span style="color: #3AA43E;">&quot;newlisp web module&quot;</span><span style="color: #AF0500;">&#41;</span> <span style="color: #AF0500;">&#40;</span><span style="color: #3AA43E;">&quot;foo&quot;</span> <span style="color: #3AA43E;">&quot;bar&quot;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span><span style="color: #AF0500;">&#41;</span>
<span style="color: #808080; font-style: italic;">;; =&gt; http://www.artfulcode.net/?s=newlisp+web+module&amp;foo=bar</span></pre></div></div>

<p>It also has a counterpart, <a href="http://static.artfulcode.net/newlisp/web.lsp.html#Web_parse-url"><code>Web:parse-url</code></a>, which breaks a URL up into an association list of its component parts.</p>
<h2>Download</h2>
<p>You can find it in the <a href="http://static.artfulcode.net/newlisp/index.html">repository</a> or download it directly <a href="http://static.artfulcode.net/newlisp/web.lsp">here</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%2Fa-better-newlisp-web-library%2F&amp;title=A+better+newLISP+web+library" 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%2Fa-better-newlisp-web-library%2F&amp;title=A+better+newLISP+web+library" 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=A+better+newLISP+web+library&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fa-better-newlisp-web-library%2F&amp;title=A+better+newLISP+web+library" 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%2Fa-better-newlisp-web-library%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%2Fa-better-newlisp-web-library%2F&amp;title=A+better+newLISP+web+library" 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%2Fa-better-newlisp-web-library%2F&amp;title=A+better+newLISP+web+library" 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%2Fa-better-newlisp-web-library%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+A+better+newLISP+web+library+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fa-better-newlisp-web-library%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/a-better-newlisp-web-library/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Updated Json module for newLISP</title>
		<link>http://www.artfulcode.net/articles/updated-json-module-for-newlisp/</link>
		<comments>http://www.artfulcode.net/articles/updated-json-module-for-newlisp/#comments</comments>
		<pubDate>Fri, 22 May 2009 18:10:01 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[newlisp]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=643</guid>
		<description><![CDATA[Thanks to Andrew Pennebaker for pointing out where the decoder was broken. This update includes a complete rewrite of the JSON decoder. It is now slightly more forgiving and much more accurate. You can download it here or upgrade using nl-install. Submit article]]></description>
			<content:encoded><![CDATA[<p>Thanks to Andrew Pennebaker for pointing out where the decoder was broken. This update includes a complete rewrite of the JSON decoder. It is now slightly more forgiving and much more accurate. You can download it <a href="http://static.artfulcode.net/newlisp/json.lsp.html">here</a> or upgrade using <a href="http://static.artfulcode.net/nl-install/packages.lsp">nl-install</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%2Fupdated-json-module-for-newlisp%2F&amp;title=Updated+Json+module+for+newLISP" 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%2Fupdated-json-module-for-newlisp%2F&amp;title=Updated+Json+module+for+newLISP" 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=Updated+Json+module+for+newLISP&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fupdated-json-module-for-newlisp%2F&amp;title=Updated+Json+module+for+newLISP" 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%2Fupdated-json-module-for-newlisp%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%2Fupdated-json-module-for-newlisp%2F&amp;title=Updated+Json+module+for+newLISP" 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%2Fupdated-json-module-for-newlisp%2F&amp;title=Updated+Json+module+for+newLISP" 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%2Fupdated-json-module-for-newlisp%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+Updated+Json+module+for+newLISP+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fupdated-json-module-for-newlisp%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/updated-json-module-for-newlisp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP is a framework</title>
		<link>http://www.artfulcode.net/articles/php-is-a-framework/</link>
		<comments>http://www.artfulcode.net/articles/php-is-a-framework/#comments</comments>
		<pubDate>Fri, 15 May 2009 18:12:26 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Soap box]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web design]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=624</guid>
		<description><![CDATA[Rails, Django, Spring &#8211; application frameworks like these are now ubiquitous in the development of web-based applications. This is part of a trend in many general purpose languages of building toward the web. For these, the application framework is not just a buzzword; it is the abstraction used to build the language up to the [...]]]></description>
			<content:encoded><![CDATA[<p>Rails, Django, Spring &#8211; application frameworks like these are now ubiquitous in the development of web-based applications. This is part of a trend in many general purpose languages of building toward the web. For these, the application framework is not just a buzzword; it is the abstraction used to build the language up to the browser.<span id="more-624"></span></p>
<p>PHP was designed with the reverse in mind. In its first release, it could have been considered to be a DSL for web-based applications. It was written to specifically address the needs to writing web applications, and is now building toward a more general purpose language. In all likelihood, this is the wrong way around. It certainly does not fall into the bottom-up design Shangri-La of which Paul Graham is such a proponent.</p>
<p>In reality, though, web-based applications are driving the industry. PHP is still very relevant in that domain. From very early on, PHP was centered on functionality that is considered basic to any web-based framework. Functionality without which each library is simply a thin wrapper over CGI. Features like easy access to GET and POST variables, session handling, header control, and database access have been built into PHP from, if not the beginning, then close enough that dinosaurs like myself don&#8217;t remember it ever being otherwise.</p>
<p>PHP has its own share of frameworks, too, which allow the programmer to painstakingly map SQL schema to XML or vice versa. They carefully abstract the logic out of the view and force the programmer to jump through hoops to write a simple application (although, for complex applications, this often makes the programmer&#8217;s life *much* easier.)</p>
<p>PHP does not need any of this. In fact, the most pragmatic framework I have used to date for PHP is the <a href="http://clickontyler.com/simple-php-framework/">Simple PHP Framework</a>, which is just a set of useful classes to automate some of the more tedious areas of web development. What it does not do is get in the programmer&#8217;s way. It is <a href="http://en.wikipedia.org/wiki/Occam's_razor">Occam&#8217;s razor</a> at work in the world of web development. From the SPF website, quoting a non-existent link:</p>
<blockquote><p>&#8220;All the web frameworks in the world won’t turn a shitty programmer into a good one.&#8221;</p></blockquote>
<p>What PHP is not is elegant. It does not have beauty of prose, nor those features that make languages like ML and Lisp so exciting, such as closures, functions-as-objects, or lazy evaluation. Instead, PHP is, above all, a practical language. Instead, it has less sexy features, such as built-in support for XML, XSLT, and Xpath, support most databases, and the built-in ability to serialize to and from JSON and cookie strings.</p>
<p>It is easy to overlook how simple PHP makes many tasks that are complex in other frameworks. For example, Django&#8217;s form library is large and complex. I&#8217;ve no doubt that most other frameworks have equally Byzantine systems for developing reusable forms. In PHP, one might just write:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">function input($type, $name, $display, $value)
{
    &lt; ?
        &lt;label&gt;&lt; ?= $display ?&gt;
        &lt;input type=&quot;<span style="color: #000000; font-weight: bold;">&lt;?=</span> <span style="color: #000088;">$type</span> ?<span style="color: #339933;">/&gt;</span><span style="color: #0000ff;">&quot; value=&quot;</span><span style="color: #339933;">&lt;</span> ?<span style="color: #339933;">=</span> <span style="color: #000088;">$value</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; /&gt;
    ?&gt;
}</pre></div></div>

<p>The function could be refined to separate the template and the code by putting the HTML into a separate include:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> input<span style="color: #009900;">&#40;</span><span style="color: #000088;">$type</span><span style="color: #339933;">,</span> <span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$dispaly</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'templates/input.inc.php'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Simple, right? Which is not to say that PHP&#8217;s faults are not legion. That said, I think that PHP sometimes does a better job of building toward general purpose programming than many other languages do of building toward web development.</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%2Fphp-is-a-framework%2F&amp;title=PHP+is+a+framework" 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%2Fphp-is-a-framework%2F&amp;title=PHP+is+a+framework" 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=PHP+is+a+framework&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fphp-is-a-framework%2F&amp;title=PHP+is+a+framework" 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%2Fphp-is-a-framework%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%2Fphp-is-a-framework%2F&amp;title=PHP+is+a+framework" 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%2Fphp-is-a-framework%2F&amp;title=PHP+is+a+framework" 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%2Fphp-is-a-framework%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+PHP+is+a+framework+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fphp-is-a-framework%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/php-is-a-framework/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Phorms: a PHP form library</title>
		<link>http://www.artfulcode.net/articles/phorms-a-php-form-library/</link>
		<comments>http://www.artfulcode.net/articles/phorms-a-php-form-library/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 20:29:45 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=587</guid>
		<description><![CDATA[Phorms is a general purpose, easy-to-use HTML forms library. Phorms aims to provide a simple framework for generating complex forms. Forms are created by extending the abstract Phorm class. Validation is simple and easy to implement. Django users especially will find Phorms&#8217; validation familiar: require_once&#40;'lib/phorms/phorms.php'&#41;; &#160; function required&#40;$value&#41; &#123; if &#40;$value == '' &#124;&#124; is_null&#40;$value&#41;&#41; [...]]]></description>
			<content:encoded><![CDATA[<p>Phorms is a general purpose, easy-to-use HTML forms library.  Phorms aims to provide a simple framework for generating complex forms.<span id="more-587"></span></p>
<p>Forms are created by extending the abstract Phorm class.  Validation is simple and easy to implement.  Django users especially will find Phorms&#8217; validation familiar:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lib/phorms/phorms.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> required<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">''</span> <span style="color: #339933;">||</span> <span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    throw <span style="color: #000000; font-weight: bold;">new</span> ValidationError<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This field is required.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> CommentForm <span style="color: #000000; font-weight: bold;">extends</span> Phorm
<span style="color: #009900;">&#123;</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> define_fields<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Define form fields</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post_id</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HiddenField<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">first_name</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> TextField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;First name&quot;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">last_name</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> TextField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Last name&quot;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">email</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> EmailField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Email address&quot;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> URLField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Home page&quot;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">25</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">number</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IntegerField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Favorite number&quot;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">7</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">message</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> LargeTextField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Message'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">40</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notify</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> BooleanField<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Reply notification'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Add some help text</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">notify</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set_help_text</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Email me when my comment receives a response.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">email</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set_help_text</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'We will never give out your email address.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Setting default values is simple:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CommentForm<span style="color: #009900;">&#40;</span>Phorm<span style="color: #339933;">::</span><span style="color: #004000;">POST</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'post_id'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">42</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'notify'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And form validation is a breeze:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$valid</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">is_valid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Phorm instances serialize to an HTML table and provide methods to open and close the form:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">open</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'PHP_SELF'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The Phorms library:</p>
<ul>
<li>supports file and image uploads</li>
<li>has easy to use validation</li>
<li>is extensible by subclassing the build-in PhormField and PhormWidget classes</li>
<li><a href="http://static.artfulcode.net/phorms/doc/">is completely documented with phpdoc</a></li>
</ul>
<p>You can download it from my <a href="http://www.artfulcode.net/phorms/">projects page</a> or <a href="http://static.artfulcode.net/phorms/phorms.zip">directly</a>.</p>
<p><strong>Update:</strong> fixed a couple bugs and put API docs online.</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%2Fphorms-a-php-form-library%2F&amp;title=Phorms%3A+a+PHP+form+library" 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%2Fphorms-a-php-form-library%2F&amp;title=Phorms%3A+a+PHP+form+library" 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=Phorms%3A+a+PHP+form+library&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fphorms-a-php-form-library%2F&amp;title=Phorms%3A+a+PHP+form+library" 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%2Fphorms-a-php-form-library%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%2Fphorms-a-php-form-library%2F&amp;title=Phorms%3A+a+PHP+form+library" 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%2Fphorms-a-php-form-library%2F&amp;title=Phorms%3A+a+PHP+form+library" 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%2Fphorms-a-php-form-library%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+Phorms%3A+a+PHP+form+library+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fphorms-a-php-form-library%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/phorms-a-php-form-library/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Thread pool module for Pike</title>
		<link>http://www.artfulcode.net/articles/thread-pool-module-for-pike/</link>
		<comments>http://www.artfulcode.net/articles/thread-pool-module-for-pike/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 17:14:09 +0000</pubDate>
		<dc:creator>Jeff</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[pike]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://www.artfulcode.net/?p=572</guid>
		<description><![CDATA[Async provides a simple process pool that allocates a number of worker threads
that may then be utilized collectively without having to deal directly with
threads. Results of jobs sent to the pool are "future" objects, called Asyncs.
Asyncs' values are then acquired by calling Async.sync, which blocks until the
value has been set by the pool. A supervisor thread monitors the worker threads
and restarts any that terminate abnormally.]]></description>
			<content:encoded><![CDATA[<h2>Async.pmod</h2>
<p>Download it <a href="http://www.artfulcode.net/wp-content/uploads/2009/03/async.pmod">here</a>.</p>
<p>Async provides a simple process pool that allocates a number of worker threads<br />
that may then be utilized collectively without having to deal directly with<br />
threads. Results of jobs sent to the pool are &#8220;future&#8221; objects, called Asyncs.<br />
Asyncs&#8217; values are then acquired by calling Async.sync, which blocks until the<br />
value has been set by the pool. A supervisor thread monitors the worker threads<br />
and restarts any that terminate abnormally.<span id="more-572"></span></p>
<p>Usage is simple:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// create a pool of four processes</span>
Pool pool <span style="color: #339933;">=</span> Pool<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#41;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// send a job to the pool</span>
Async result <span style="color: #339933;">=</span> Pool<span style="color: #339933;">-&gt;</span>send<span style="color: #009900;">&#40;</span>exp<span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// get the result</span>
result<span style="color: #339933;">-&gt;</span>sync<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// =&gt; 22026.46484375</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// alternately, you can call an async</span>
result<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// =&gt; 22026.46484375</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// pools can conveniently map across a sequence</span>
Async mapped_result <span style="color: #339933;">=</span> pool<span style="color: #339933;">-&gt;</span>map<span style="color: #009900;">&#40;</span>exp<span style="color: #339933;">,</span> enumerate<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
mapped_result<span style="color: #339933;">-&gt;</span>sync<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// =&gt; ({ 1.0, 2.718281745910645, 7.389056205749512, 20.08553695678711, 54.59814834594727 })</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// or iterate without collecting return values</span>
<span style="color: #993333;">int</span> x <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
pool<span style="color: #339933;">-&gt;</span>iter<span style="color: #009900;">&#40;</span>lambda <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> n<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> x <span style="color: #339933;">+=</span> n<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> enumerate<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
write<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d&quot;</span><span style="color: #339933;">,</span> x<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// =&gt; 4950</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// close the pool, blocking until all workers have terminated</span>
pool<span style="color: #339933;">-&gt;</span>close<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<!-- 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%2Fthread-pool-module-for-pike%2F&amp;title=Thread+pool+module+for+Pike" 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%2Fthread-pool-module-for-pike%2F&amp;title=Thread+pool+module+for+Pike" 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=Thread+pool+module+for+Pike&amp;url=http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fthread-pool-module-for-pike%2F&amp;title=Thread+pool+module+for+Pike" 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%2Fthread-pool-module-for-pike%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%2Fthread-pool-module-for-pike%2F&amp;title=Thread+pool+module+for+Pike" 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%2Fthread-pool-module-for-pike%2F&amp;title=Thread+pool+module+for+Pike" 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%2Fthread-pool-module-for-pike%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+Thread+pool+module+for+Pike+@+http%3A%2F%2Fwww.artfulcode.net%2Farticles%2Fthread-pool-module-for-pike%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/thread-pool-module-for-pike/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

