<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.0" -->
<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/"
	>

<channel>
	<title>Bitwise Evolution</title>
	<link>http://blog.ciscavate.org</link>
	<description></description>
	<pubDate>Fri, 05 Sep 2008 17:13:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0</generator>
	<language>en</language>
			<item>
		<title>Wrestling Python</title>
		<link>http://blog.ciscavate.org/2008/09/wrestling-python.html</link>
		<comments>http://blog.ciscavate.org/2008/09/wrestling-python.html#comments</comments>
		<pubDate>Fri, 05 Sep 2008 17:13:49 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/2008/09/wrestling-python.html</guid>
		<description><![CDATA[With the launch of the StackOverflow beta I posed a question about python static analysis tools, as I have been playing with python and django recently for some side projects.  The responses at Stack Overflow quickly pointed to PyChecker, PyFlakes and PyLint.

Over all, it was a disappointing experience.  My experiences are outlined below, [...]]]></description>
			<content:encoded><![CDATA[<p>With the launch of the <a href="http://beta.stackoverflow.com">StackOverflow beta</a> I posed a question about python static analysis tools, as I have been playing with python and django recently for some side projects.  The responses at Stack Overflow quickly pointed to <a href="http://pychecker.sf.net">PyChecker</a>, <a href="http://divmod.org/trac/wiki/DivmodPyflakes">PyFlakes</a> and <a href="http://www.logilab.org/857">PyLint</a>.</p>

<p>Over all, it was a disappointing experience.  My experiences are outlined below, and they (more or less) reflect this more <a href="http://www.doughellmann.com/articles/CompletelyDifferent-2008-03-linters/index.html ">extensive review by Doug Hellman</a>.</p>

<p>Here are my first impressions of pyflakes, pychecker and pylint:</p>

<ul>
<li><p><strong>pychecker</strong>: It crashes frequently, most of the runs I tried resulted in Errors that originated in the pychecker code (eg: AttributeError or IndexError: list index out of range were the most common).  For some reason I had to set the DJANGO<em>SETTINGS</em>MODULE environment variable before it would even run on any of the app code, and the documentation is very sparse.</p></li>
<li><p><strong>pyflakes</strong>: &#8216;pyflakes &#8212;help&#8217; throws a TypeError &#8212; erm&#8230; Documentation is also very sparse, and pyflakes is very forgiving (as far as I can tell, it only reports compile errors, warnings, redefinitions, and some concerns about imports&#8212;such as unused and wildcards).  pyflakes also seems to repeat itself:</p>

<blockquote>
  <p>eventlist/views.py:4: &#8216;Http404&#8217; imported but unused<br />
      eventlist/views.py:4: &#8216;Http404&#8217; imported but unused<br />
      eventlist/views.py:5: &#8216;from eventlist.models import *&#8217; used; unable to detect undefined names
      eventlist/views.py:59: &#8216;authenticate&#8217; imported but unused<br />
      eventlist/views.py:61: redefinition of unused &#8216;login&#8217; from
  line 59<br />
      eventlist/views.py:5: &#8216;from eventlist.models import *&#8217; used;
  unable to detect undefined names <br />
     eventlist/views.py:4: &#8216;Http404&#8217; imported but unused</p>
</blockquote></li>
<li><p><strong>pylint</strong>: This seems to be the most capable of the tools suggested.  It has the best documentation.  LogiLab provides a tutorial, pylint has a help screen, and there is a (broken) link to a user manual, which would be extremely helpful.  There are some issues with applying pylint to django, since pylint doesn&#8217;t know about the django classes (such as models.Model).  This means that a fair number of otherwise valuable errors are generated about missing class fields.  eg:</p>

<blockquote>
  <p><code>E:105: get_events_by_tag: Class 'Tag' has no 'objects' member</code><br /></p>
</blockquote>

<p>Parsing these out automatically will be very difficult without some additional knowledge of the classes in use.  I&#8217;m not sure adding that is feasible, but it does seem likely that pylint is capable of dealing with this in the &#8220;right&#8221; way.  (I probably just need to point it to the django source, but there are no command line params that look likely, and, as mentioned earlier, the user manual is inaccessible.)</p></li>
</ul>

<p>For the moment, I&#8217;m still looking into pylint &#8212; pychecker and pyflakes need better documentation and they need to become more robust.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2008/09/wrestling-python.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Traveling to Patras</title>
		<link>http://blog.ciscavate.org/2008/07/traveling-to-patras.html</link>
		<comments>http://blog.ciscavate.org/2008/07/traveling-to-patras.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 11:52:30 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>greece</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/2008/07/traveling-to-patras.html</guid>
		<description><![CDATA[

A groggy morning in Seattle started with the typical regional sunshine forcing its presence through heavy cloud cover&#8212;the first overcast day in nearly a week of clear, scorching weather.



Seattle to Newark, hustle off the plane, bad coffee, hustle to the next gate, and then encamp for the next 9 hours of travel across the Atlantic. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.ciscavate.org/wp-content/uploads/2008/07/seatac-small.jpg" style="float:left; padding-right: 1em;"><img alt="Coffe and clouds in Seattle." src="http://blog.ciscavate.org/wp-content/uploads/2008/07/seatac-small.thumbnail.jpg" /></a></p>

<p>A groggy morning in Seattle started with the typical regional sunshine forcing its presence through heavy cloud cover&#8212;the first overcast day in nearly a week of clear, scorching weather.</p>

<p><a style="float:right; padding-right: 1em;" href="http://blog.ciscavate.org/wp-content/uploads/2008/07/patrasHills1-small.jpg"><img alt="The hills across the Gulf of Patras (looking North)" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/patrasHills1-small.thumbnail.jpg" /></a></p>

<p>Seattle to Newark, hustle off the plane, bad coffee, hustle to the next gate, and then encamp for the next 9 hours of travel across the Atlantic.  This leg was on a relatively empty 767, but I still can&#8217;t really sleep on planes.  I have become an overnight advocate for noise-canceling headphones though&#8212;they make the difference between muffling a sound and turning it off.  I found the Athens airport to be considerably less hyper than most US airports (with the exception of Syracuse, which is not much of a surprise), although I think it is universal that no one is particularly happy when at an airport, and that feeling seems to be contagious.  It&#8217;s unfortunate that it is so difficult to visit a place without first visiting an airport there.</p>

<p><a style="float:left; padding-right: 1em;" href="http://blog.ciscavate.org/wp-content/uploads/2008/07/moonAndBoats-small.jpg"><img alt="The morning view from the balcony" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/moonAndBoats-small.thumbnail.jpg" /></a></p>

<p>I few hours later I hopped on a tour bus to take everyone from the recent batch of flights off to our hotels in Patras&#8212;a wild 4-5 hour ride along the shoulders of &#8220;one of the worst roads in Greece&#8221; as some one here put it.  The careening along coastal roads was punctuated by hairpin turns in seaside villages with roads small enough to make any driver feel claustrophobic, and we were riding in a bus that would seat 30-40, with luggage.  It was much like watching a game of <a href="http://en.wikipedia.org/wiki/N-puzzle">Fifteen Puzzle</a>, with a key twist: every tile (car) was self-aware and initially greedy.</p>

<p>We did eventually make it to the <a href="http://www.hoteltzaki.gr/">Hotel Tzaki</a> almost exactly 24 hours after leaving Seattle.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2008/07/traveling-to-patras.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Cracking down on application clutter (or: my ${HOME} is my castle!)</title>
		<link>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html</link>
		<comments>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 23:25:21 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html</guid>
		<description><![CDATA[There was once a time when your home directory was treated as a nearly sacred place, a safe haven where you had near complete control.  This trust was only breached for very special reasons: user specific settings and background storage for applications could go in &#8220;dot-files&#8221;&#8212;the hidden files or directories that begin with a [...]]]></description>
			<content:encoded><![CDATA[<p>There was once a time when your home directory was treated as a nearly sacred place, a safe haven where you had near complete control.  This trust was only breached for very special reasons: user specific settings and background storage for applications could go in &#8220;dot-files&#8221;&#8212;the hidden files or directories that begin with a &#8220;.&#8221; and therefore don&#8217;t show up in normal directory listings.</p>

<p>Unfortunately, things began to change. I don&#8217;t know what kicked it off, but soon there was a Desktop (or desktop) folder.  It was glaring&#8212;many XFree86 window managers don&#8217;t even have the <em>concept</em> of a desktop, but the defaults environments were (and still are) often set to Desktop Managers.  Web browsers took after the DM&#8217;s, and soon we all had these glaring &#8220;Desktop&#8221; directories hanging out whether we wanted them or not.  I&#8217;ve managed to tolerate this infraction for years, and aside from the occasional frustration (eg: Ecilpse and NetBeans, with their request for a ~/workspace and ~/NetBeansProjects directories).</p>

<p>However, today things changed.</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ ls ~<br />
bin/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PDF/&nbsp; &nbsp;&nbsp; <br />
Desktop/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Pictures/&nbsp; <br />
development/&nbsp; &nbsp; &nbsp; Public/&nbsp; &nbsp;&nbsp; &nbsp; <br />
documents/&nbsp; &nbsp; &nbsp; &nbsp; src/&nbsp; &nbsp;&nbsp; <br />
Documents/&nbsp; &nbsp; &nbsp; &nbsp; shared/&nbsp; &nbsp;&nbsp; &nbsp; <br />
downloads/&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Templates/&nbsp;&nbsp; <br />
Mail/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Videos/&nbsp; &nbsp;&nbsp; &nbsp; <br />
Music/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; virtualMachines/ <br />
myapps/&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;workspace/</div></div>

<p>Documents? (Ok, I can sort of understand that one.) Music? Pictures? Templates, PDF, Public, and Videos?! Did I suddenly become a master of multimedia? Keep in mind here, I&#8217;m a java hacker on a Linux box&#8212;this isn&#8217;t exactly a fine-tuned rendering/desktop publishing platform.   And of course, every one of those directories is empty.  Thankfully, I checked before deleting <code>documents</code> vs. <code>Documents</code> (I&#8217;ve been bitten there before&#8212;on a mac due to case conflation&#8212;but that&#8217;s another story).  </p>

<p>Why would I want a directory called PDF? I can understand (possibly) wanting to <em>tag</em> files with &#8220;PDF&#8221;, but as part of a single-dimensional sorting criteria? (Hey, lets store all my .h files in ~/H/ and all my .cpp files in ~/CPP/! It&#8217;ll be great!)</p>

<p>Needless to say, I&#8217;ve removed the offending directories, and this time I&#8217;m ready:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ kernel-filesystem-monitor-daemon-cat -v&nbsp; watch <span class="re0">$<span class="br0">&#123;</span>HOME<span class="br0">&#125;</span></span> | <br />
perl -ne <span class="st0">'{<br />
&nbsp; &nbsp;if( /^CREATE/ ) { # only report create events<br />
&nbsp; &nbsp; &nbsp; s|.*URL:<span class="es0">\.</span>/||g; <br />
&nbsp; &nbsp; &nbsp; if ( !/^<span class="es0">\.</span>/ ) { # don'</span>t report new dot-files<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print <span class="st0">&quot;$_ created @ &quot;</span>; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print `date`; <br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><span class="st0">' &gt; ~/whenCrapWentDown.txt</span></div></div>

<p>(newlines and comments introduced to improve clarity &#8212; if you&#8217;re pasting this into a shell, you&#8217;ll need to either add &#39;s or remove newlines.)</p>

<p><a href="http://freshmeat.net/projects/kfsmd/">KFSMD (kernel-filesystem-monitor-daemon)</a> is an app that does exactly what it&#8217;s 32-character name says. Whenever a filesystem change occurs, it knows about it.  The <code>-cat</code> part just tells it to print to stdout, and the hunk of perl does some minor processing, and introduces time stamps.</p>

<p>I&#8217;m actually running this in a sticky terminal that&#8217;s pinned to my E17 desktop, so if/when something starts building an empire in my home directory, I&#8217;ll be able to compare with what apps are running, and hopefully track it down.  (It would be nice to collect the PIDs of the process that actually issued the system call to touch the file system, but this is good enough for now.)</p>

<p><img id="image37" src="http://blog.ciscavate.org/wp-content/uploads/2008/07/fsWatcher.png" alt="fsWatcher.png" width="474"/></p>

<p>Now we wait&#8230;</p>

<p>(<a href="http://www.linux.com/feature/124903">This article</a> got me going with KFSMD.)</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2008/07/cracking-down-on-application-clutter-or-my-home-is-my-castle.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Creating Wizards in Java</title>
		<link>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html</link>
		<comments>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html#comments</comments>
		<pubDate>Tue, 01 Jul 2008 19:54:24 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
	<category>java</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=35</guid>
		<description><![CDATA[A recent project at work required building a multi-step dialog to manage the interface between a user and an expert system (and some fairly advanced NLP to boot).  On the surface this looked like a fairly standard Wizard problem &#8212; design a bunch of screens with questions, and then collect the answers as the [...]]]></description>
			<content:encoded><![CDATA[<p>A recent project at work required building a multi-step dialog to manage the interface between a user and an expert system (and some fairly advanced NLP to boot).  On the surface this looked like a fairly standard Wizard problem &#8212; design a bunch of screens with questions, and then collect the answers as the user proceeded through the dialogs.  However, the Wizard APIs I found were either not very mature or (in the case of the <a href="http://wizard.dev.java.net">Java.net Wizards</a>) it was very difficult to create complex branching behaviors, and those branches were extremely resistant to change.  Both things are essentially show-stoppers when working with prototypes that frequently need modification.</p>

<p>In the end, I spent a weekend and a couple evenings building a new Wizard API for Java, called <a href="http://code.google.com/p/cjwizard">CJWizard</a>.  The library is released under the Apache V.2 license, so it should work for just about anything you want to use it for.  I would like to know if you&#8217;re using it, and what you&#8217;re using it for, just to sate my own curiosity :).  The project is hosted on code.google.com, so please submit issues, and feel free to contribute to the project.</p>

<p><a href="http://code.google.com/p/cjwizard">CJWizard</a> provides the structure needed to quickly create simple dialogs by implementing an abstract class (WizardPage) for each page of the dialog, and adding them to a PageFactory that can generate pages on-demand, as they are required.  This puts the programmer in full control of how the wizard proceeds.  The CJWizard architecture also makes it easy to add a wizard to an existing application (either via an additional JDialog, or embedding in some other component), and/or insert custom wrapper widgets around the dialog pages&#8212;meaning that you can quickly add customized navigational controls aside from the standard Previous/Next/Finish/Cancel buttons.</p>

<p>Some aspects were taken from the Java.Net wizard API, such as auto-detecting named components, and automatically collecting the values from them, but CJWizard takes a much simpler approach (and in some ways, a less powerful one &#8212; CJWizard does not listen to every key event, only collecting values when the user navigates away from a WizardPage). In most cases, you only need to name widgets prior to adding them to the WizardPage, and their values will be collected in a settings map automatically.</p>

<p>CJWizard was meant to provide a flexible way to generate professional-looking multi-step dialogs very quickly.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2008/07/creating-wizards-in-java.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Day to day Memoization</title>
		<link>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html</link>
		<comments>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html#comments</comments>
		<pubDate>Mon, 28 Jan 2008 11:02:08 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
	<category>java</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=33</guid>
		<description><![CDATA[Memoization (not memorization) is the process of remembering the
results of a computation for use later.  (I think of it as &#8220;making a
memo&#8221; to look back on later.)  Memoization is the core to any dynamic
programming implementation, and allows many simple algorithms to run
in linear or polynomial time when they would otherwise take an
exponential number [...]]]></description>
			<content:encoded><![CDATA[<p>Memoization (not <strong>memorization</strong>) is the process of remembering the
results of a computation for use later.  (I think of it as &#8220;making a
memo&#8221; to look back on later.)  Memoization is the core to any dynamic
programming implementation, and allows many simple algorithms to run
in linear or polynomial time when they would otherwise take an
exponential number of operations to complete.  This is most obvious in
the typical recursive Fibonacci example.  Consider the code:</p>

<div class="codecolorer-container java"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> Fib<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;done: fib of &quot;</span>+args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>+<span class="st0">&quot;=&quot;</span>+<br />
&nbsp; &nbsp; &nbsp; fib<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> fib<span class="br0">&#40;</span><span class="kw4">int</span> n<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> rval = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n &amp;gt;= <span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rval = fib<span class="br0">&#40;</span>n - <span class="nu0">1</span><span class="br0">&#41;</span> + fib<span class="br0">&#40;</span>n - <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;fib(&quot;</span>+n+<span class="st0">&quot;) = &quot;</span>+rval<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> rval;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>This is a straight-forward recursive implementation of fib.  When run
with <code>n=4</code>, we see this:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ javac Fib.java &amp;&amp; java Fib <span class="nu0">4</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span> = <span class="nu0">3</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span> = <span class="nu0">5</span><br />
<span class="kw1">done</span>: fib of <span class="nu0">4</span>=<span class="nu0">5</span></div></div>

<p><strong>9</strong> invocations of <code>fib(n)</code>, but only 5 <strong>unique</strong> invocations.  Lets
memoize the results, and try this again:</p>

<div class="codecolorer-container bash"><div class="codecolorer" style="font-family: monospace;">$ javac Fib.java &amp;&amp; java Fib <span class="nu0">4</span><br />
fib<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span> = <span class="nu0">1</span><br />
fib<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span> = <span class="nu0">2</span><br />
fib<span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span> = <span class="nu0">3</span><br />
fib<span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span> = <span class="nu0">5</span><br />
<span class="kw1">done</span>: fib of <span class="nu0">4</span>=<span class="nu0">5</span></div></div>

<p><strong>Much</strong> better &#8212; 5 invocations, 5 unique sets of parameters.</p>

<p>Here&#8217;s the source with memoization:</p>

<div class="codecolorer-container java" style="height:280px;"><div class="codecolorer" style="font-family: monospace;"><span class="kw2">public</span> <span class="kw2">class</span> Fib<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">static</span> Map&amp;lt;Integer, Integer&amp;gt; memos = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AHashMap+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">HashMap</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">// new</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;done: fib of &quot;</span>+args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>+<span class="st0">&quot;=&quot;</span>+<br />
&nbsp; &nbsp; &nbsp; fib<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> fib<span class="br0">&#40;</span><span class="kw4">int</span> n<span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>memos.<span class="me1">containsKey</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="co1">// new</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">return</span> memos.<span class="me1">get</span><span class="br0">&#40;</span>n<span class="br0">&#41;</span>;&nbsp; <span class="co1">// new</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> rval = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>n &amp;gt;= <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rval = fib<span class="br0">&#40;</span>n - <span class="nu0">1</span><span class="br0">&#41;</span> + fib<span class="br0">&#40;</span>n - <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ASystem+java.sun.com&amp;bntI=I%27m%20Feeling%20Lucky"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span><span class="st0">&quot;fib(&quot;</span>+n+<span class="st0">&quot;) = &quot;</span>+rval<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; memos.<span class="me1">put</span><span class="br0">&#40;</span>n, rval<span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// new</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw2">return</span> rval;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>

<p>Notice that we only needed to add 4 new lines of code in order to
memoize the results.  When <code>fib(n)</code> is called, it simply checks to see
if it has previously been called with n, and if so, that result is
used again.  If the parameter has never been seen before, the method
continues as normal, storing the computed result before returning.
Memoization turns this naive (and exponential) implementation of <code>fib(n)</code>
into an efficient (linear) operation.</p>

<h2>Memoization in the real world</h2>

<p>So, (un?)fortunately we don&#8217;t spend all day implementing cool new ways
of computing ever increasing entries of the fibinocci sequence &#8212; how
can memoization be put to use? After all, many algorithms are already
implemented in some fairly optimal fashion by the language APIs, and
you&#8217;d be a fool not to use those implementations.  What opportunity
will you have to memoize functions?</p>

<p>It turns out that you can memoize <em>anything</em>, as long as the function
is <em>pure</em> with respect to the memos (meaning: the function doesn&#8217;t depend on any thing that is not used to key the hash of memos).  If the function is not pure, then you can still use memoization, but either the memo hash must key on all the state and parameters that can affect the results of the function.  On the other hand, if f depends on some state that changes very rarely, then it may make more sense to simply discard all the stored memos each time that aspect of state is altered.</p>

<p>Memoization is extremely handy when you have very common operations that are
fairly expensive.  I recently needed to optimize some code that
compares strings based on the case-insensitive stems of the words,
with stopwords removed.  So the strings &#8220;he wanted an apple&#8221; and &#8220;he
wants apples&#8221; should be equal. (&#8220;an&#8221; is a stopword, and ignored)</p>

<p>This meant doing many, many calls to a string stemmer, each of which
is a fairly expensive operation.  Fortunately, hashing strings as
extremely cheap (on the order of 1/4th the time it took to stem a
string of the same length), and I had plenty of memory to store the
parameters and the results in a <code>Map</code>.  Adding memos to
the two primary time-hoggers (the stemmer and a tokenizer) cut the
execution time of the application down from 2 hours to just over 7
minutes.</p>

<h2>Summary</h2>

<p>You can memoize any function that only depends on it&#8217;s parameters and
constant state (or near-constant state &#8212; just don&#8217;t forget to discard your
memos when the state changes!).  If the function is invoked multiple
times you will probably see a performance improvement.</p>

<p>If you need to memoize a function with multiple arguments, then you
just need to nest Maps, or create a unique key by combining the
parameters in some way.</p>

<p>Memoization is an extremely easy way to improve performance under
certain circumstances, particularly if you have a solid grasp on when
state changes outside of your methods / functions, or program in a
functional style.  It can be memory intensive, however.  If the
results of your functions are large, or maintain references to large
objects, then memoization may <strong>penalize</strong> performance if you run out of
memory and have to make use of swap space.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2008/01/day-to-day-memoization.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Creating a secure webauth system: Part 1 &#8212; HMAC</title>
		<link>http://blog.ciscavate.org/2007/09/creating-a-secure-webauth-system-part-1-hmac.html</link>
		<comments>http://blog.ciscavate.org/2007/09/creating-a-secure-webauth-system-part-1-hmac.html#comments</comments>
		<pubDate>Fri, 28 Sep 2007 07:25:36 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=32</guid>
		<description><![CDATA[This is the first in an n-part series about web authentication for a system where user identification and attribution is important, but content protection is not.  This entry assumes that a secure method has been used to negotiate a shared secret &#8212; as the result of username / password authentication over https, for example.

Obviously [...]]]></description>
			<content:encoded><![CDATA[<p><em>This is the first in an n-part series about web authentication for a system where user identification and attribution is important, but content protection is not.  This entry assumes that a secure method has been used to negotiate a shared secret &#8212; as the result of username / password authentication over https, for example.</em></p>

<p>Obviously the user login / account registration portion of a web auth system will require some secure connection, but once that authentication is completed we&#8217;d like to make use of a more efficient open protocol. (eg: <em>http</em> vs. <em>https</em>).  There are many reasons for this: better performance, client-side caching, etc.. I&#8217;m not going into those details here.  Neither will I address the initial authentication step other than to say that part of a successful login is the negotiation of a shared secret other than the user&#8217;s password.  Ideally this is a 64-byte (or larger) id with a high probability of uniqueness.  A GUID, essentially.  (It is critical that the secret used is <strong>NOT</strong> the user&#8217;s password!) The actual secured login and secret negotiation will be addressed in another entry .  At least, that&#8217;s the plan :).</p>

<p>Since our primary goal with this system is to ensure that people are who they say they are, and we&#8217;ve punted on the initial authentication (for now), the only place left for an attack is for some one to spoof a user who has already logged in.  With no additional work, our login system would be useless &#8212; some one could simply skip the entire authentication process and issue an RPC with instructions to do evil things as Alice&#8217;s user without needing to know Alice&#8217;s password.  To prevent this, we need to ensure that the same user who authenticated initially is the user who issued the unsecured RPC.  This is where the shared secret comes into play.  Only Alice and the server know her shared secret, so if the secret is passed along as a parameter of the RPC, then that is a strong indication that Alice is who she says she is.</p>

<p>But wait! We can&#8217;t just pass the secret as an RPC parameter, because these communications aren&#8217;t secure.  Charlie could lurk on the &#8216;net, waiting for an RPC from Alice to the server, sniff out the secret, and then proceed to impersonate Alice.  We could encrypt the secret, but then we just have a different secret &#8212; Charlie doesn&#8217;t need to know the unencrypted secret if the encrypted one works just as well.  Alice and the server also need an agreed upon way to change the secret so it is different for each RPC, and this must be done in a way that Charlie can&#8217;t take the changed secret and either (1) get the initial secret out, or (2) generate the next changed secret.</p>

<h2>HMAC: <em>keyed-Hash Message Authentication Code</em></h2>

<p>HMAC is a method of ensuring that a message (an RPC in our case) was generated by someone with access to a shared secret.  HMAC makes use of some sort of one-way hashing function (like MD5 or SHA-1) to encrypt the secret along with a message.  This generates a short digest of 16-20 bytes that acts as a fingerprint of the message+secret combination.  When the digest is sent along with the message, the receiver (our server) can re-generate the hash with the same HMAC calculation and compare the locally generated digest with the digest that came along with the message.  Remember: the server has the secret too, so it has enough information to confirm the digest.</p>

<p>So, back to our problem.  Alice can now use the shared secret to create a digest of every RPC, and send that along with the RPC as a parameter.  The server can then take the digest of the RPC and secret to compare, and then verify that the RPC actually originated with Alice, right?</p>

<p>Not <em>quite</em> yet&#8230;. there are still a couple holes in our plan.</p>

<p>Charlie could still sit back and snoop on Alice&#8217;s traffic and save an <strong>entire</strong> RPC, complete with digest, and reissue that RPC later.  This is better than letting Charlie do whatever he wants, but there are still some things that could be quite dangerous.  Say Alice accidentally deletes something, and undoes the deletion.  Charlie could re-issue the deletion and Alice would loose data.  The server needs to know not to accept the same request twice (but what if Alice <em>wants</em> to do something twice, you ask? Well, we have to make Alice&#8217;s second request a <em>little</em> bit different from the first one, which we can do!).</p>

<p>What if we create a digest of some sequence identifier and pass the sequence ID along with the RPC?  Since the digest, ID, and RPC are inseparable (the digest and ID are obviously linked, and the RPC can&#8217;t be sent without a valid digest, which Charlie can&#8217;t reproduce, since the accompanied digest+id pair is only good once) then we don&#8217;t need to create a digest of the entire RPC (it wouldn&#8217;t hurt, it&#8217;s just a fairly complex thing to do).  By incrementing the sequence id and recalculating a digest of it and the secret, then we can keep from issuing the same request more than once, and the server will know to ignore duplicates.</p>

<p>So, this is where we&#8217;re at:</p>

<ul>
<li>Charlie can&#8217;t snoop the secret, since it&#8217;s encrypted with a changing message (the sequence id)</li>
<li>Charlie can&#8217;t re-issue a &#8220;recorded&#8221; RPC invocation, because the digest can&#8217;t be reversed and Charlie can&#8217;t create a valid (digest, sequence) pair without the secret.</li>
<li>Charlie can&#8217;t change a RPC, again because of the trouble with creating a digest, sequence pair.</li>
</ul>

<p>Charlie&#8217;s only recourse is to try and find a secret which generates the same digests as the secret that Alice is using.  This is theoretically possible, since Charlie could probably figure out the hashing algorithm used, and run a brute-force attack, hoping to luck out and find the secret quickly.  The possibility of this happening is extremely low, however.  Furthermore, each session will use a new secret, so Charlie will only have one session&#8217;s worth of time to crack each secret.  Even creating a rainbow table will fail if the secrets aren&#8217;t of trivial length. (A 64-<strong>bit</strong> secret will be to large, and we&#8217;re using secrets 8 times that size.)</p>

<h2>Technical details and further reading</h2>

<p>When implementing an approach like this, make sure to guard the secret.  It would be easy to accidentally store the secret on the web client as a plain cookie which will then be transmitted in the clear with each RPC, and therefore defeat the purpose.  Use a secure cookie, or some other storage method to prevent this.</p>

<p>The <a href="http://www.ietf.org/rfc/rfc2104.txt">HMAC RFC</a> describes the algorithm in detail (and it&#8217;s a fairly short, easy to read RFC.) and the Wikipedia page gives a nice description too: <a href="http://en.wikipedia.org/wiki/HMAC#Example_usage">HMAC on WikiPedia</a></p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2007/09/creating-a-secure-webauth-system-part-1-hmac.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>Things I need</title>
		<link>http://blog.ciscavate.org/2007/08/things-i-need.html</link>
		<comments>http://blog.ciscavate.org/2007/08/things-i-need.html#comments</comments>
		<pubDate>Fri, 31 Aug 2007 09:49:12 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=31</guid>
		<description><![CDATA[There are many small apps that I wish I had, here&#8217;s a short list of the ones that come to mind at the moment:

A process monitor that shows the top consumer.

I often tack my system(s) to the max, and therefore run out of cycles frequently.  While this is sometimes the result of batch computations [...]]]></description>
			<content:encoded><![CDATA[<p>There are many small apps that I wish I had, here&#8217;s a short list of the ones that come to mind at the moment:</p>

<h2>A process monitor that shows the top consumer.</h2>

<p>I often tack my system(s) to the max, and therefore run out of cycles frequently.  While this is sometimes the result of batch computations that I&#8217;ve planed in advance, it is pretty common that I&#8217;ll just be working away and all of a sudden things shudder to a halt.    When this happens I want to know two things:
   1. Is it processor-related, or is it memory-related, and; 
   2. What application is responsible?
Processor / memory monitors are a dime a dozen, but they are typically very small (showing only the usage, like gkrellm) or very large (showing all the applications in the top 20 or so, like top).  I can&#8217;t stand having top visible all the time, and it takes to long to get to a terminal and start up a monitor.  By definition my system is not very responsive, and I never see what&#8217;s causing the slowdown.  </p>

<p>I need a small process and/or memory monitor that shows the top-using application in a tooltip, or optionally in an automatic pop-up when the usage hits a certain level.</p>

<h2>Universal acronym definitions.</h2>

<p>Highlight an acronym, hit a keystroke, and see a list of the most common expansions of that acronym based on frequency of use.</p>

<h2>A calendar dock-app where the date on the dock icon is actually accurate.</h2>

<p>Yeah, I actually want to look at my system bar-thingy and see what day it is, not some random number between 1 and 31 that the icon developer thought represented calendars.  </p>

<p>Hovering over the icon shows the full time/date, which is configurable from an entry on the icon&#8217;s context menu.  I don&#8217;t care what happens when I click on the icon, as long as I can make it do something arbitrary ;).</p>

<h2>The ability to refactor and generate source code from the command line.</h2>

<p>MetaJava (http://wiki.ciscavate.org/index.php/MetaJava) could resolve this issue for one language, but I&#8217;d hate to stop there.  A tool like this would mean amazing things for small-time development environments and text-editor lovers.  (Emacs and vi would easily <em>eclipse</em> some other IDEs IMHO ;).  </p>

<p>The idea is that you could easily create mini applications that read in specifications in some simple format and produce boilerplate for your required language, and/or move classes, rename variables / methods / packages / etc. without dedicating half your memory to an IDE that will then want to write 500 mb to swap, since all my memory is taken up by an application I have to run because&#8230;.</p>

<h2>I don&#8217;t have a web browser that doesn&#8217;t suck.</h2>

<p>&#8220;We hold these truths to be self-evident.&#8221;</p>

<h3>&#8230;and a web development environment to go with it.</h3>

<p>That&#8217;s a start.  I&#8217;ll add more as they occur to me.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2007/08/things-i-need.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>(not (fill-paragraph))</title>
		<link>http://blog.ciscavate.org/2007/05/not-fill-paragraph.html</link>
		<comments>http://blog.ciscavate.org/2007/05/not-fill-paragraph.html#comments</comments>
		<pubDate>Fri, 18 May 2007 11:50:18 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>emacs</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=30</guid>
		<description><![CDATA[I use emacs as much as possible, today being no exception.  Currently,
I&#8217;m doing a fair bit of writing at work, and unfortunately that means
Word (or Open Office at best, depending on what OS I&#8217;m in).  Neither
program supports much in the way of emacs compatibility modes, so if
I&#8217;m generating new content (as opposed to [...]]]></description>
			<content:encoded><![CDATA[<p>I use emacs as much as possible, today being no exception.  Currently,
I&#8217;m doing a fair bit of writing at work, and unfortunately that means
Word (or Open Office at best, depending on what OS I&#8217;m in).  Neither
program supports much in the way of emacs compatibility modes, so if
I&#8217;m generating new content (as opposed to editing an existing doc.) I
tend to write in Emacs, and paste into Word when I&#8217;m finished.  This
works pretty well, considering.</p>

<p>There is one very annoying issue though: when in emacs, I use
<code>auto-fill-mode</code> to keep the content on screen as I type.  The problem
is that <code>auto-fill-mode</code> breaks lines with literal newline characters,
while the word wrapping in Word / OpenOffice just wraps the content
without additional characters.  As a result each line ends up as its
own paragraph when I paste content from emacs into Word. The solution,
of course, is to extend emacs with a simple function to undo
<code>auto-fill</code>.</p>

<h2>Merging lines</h2>

<p>The first problem, as I saw it, was to find a function that would
merge two adjacent lines, and leave them separated by a single space.
Unfortunately, such a thing doesn&#8217;t seem to exist.  No problem, we
need to go to the end of the current line (<code>end-of-line</code>), search
backwards for the first non-whitespace character (<code>[^ \t]</code>), erase
the rest of the line, including the end line (<code>kill-line</code>), and insert
a space (<code>(insert " ")</code>).</p>

<pre>
    (defun mergelines(&amp;optional backward)
      "Merges the following line with this line, or merges this line
      with the previous line if a prefix argument is provided.
      Removes any whitespace between lines, replacing it with a
      single space."
      (interactive "P")
      (if backward 
          (previous-line))
      (end-of-line)
      (re-search-backward "[^ \t]")
      (forward-char)
      (kill-line)
      (insert " "))
</pre>

<p>To make it more useful, I added a parameter that determines if the
line below, or line above should be merged.  This made the rest of the
<code>unfill</code> function much easier to write.</p>

<h2>Un-filling a region</h2>

<p>Now that we can merge lines, lets address the problem of unfilling a
<em>bunch</em> of lines.  Since I know there is a function <code>mark-paragraph</code>
already, lets just deal with arbitrary regions for now.</p>

<pre>
    (defun unfill-region(rstart rend)
      (interactive "r")
      ;; get to the end of the region:
      (goto-char rend) 
      ;; if the region ends on the first char. of a line, move up a line.
      ;; this makes it easier to select a paragraph and apply the function.
      (if (= (point) (line-beginning-position))
          (previous-line))
       ;; loop while the point isn't on the starting line:
      (while (not (= (line-number-at-pos (point))
             (line-number-at-pos rstart)))
        ;; merge with previous line.
        (mergelines t)))
</pre>

<p>I&#8217;ve tried to comment well, so it should be relatively straight
forward, but here&#8217;s an overview of the algorithm anyway:</p>

<ol>
<li><code>(interactive "r")</code> just means that the current region&#8217;s start and
end locations are stored in the parameters <code>rstart</code> and <code>rend</code>.</li>
<li>We need to merge from the bottom up, because if we merge from the
top down we need to keep track of the lines merged, and things
generally become more complex (we might end up merging to many lines
if we loose count.).  Because of this, we first move to the end of the
region.</li>
<li>Since you (well, I) generally select from the first column, and
move one line past the last line I need (try it if you don&#8217;t
understand what I mean), I needed a special case to keep from merging
the empty line between paragraphs.</li>
<li>Now, we merge each line with the line above, which moves the point
up a line too. When the point is on the same line as the start of the
region, we stop.</li>
</ol>

<p>I haven&#8217;t merged it with <code>mark-paragraph</code> yet, but it would be trivial
to do so.  More importantly, I want to make it skip blank lines, so it
will be possible to mark an entire document, and call <code>unfill-region</code>
(and therefore, write <code>unfill-buffer</code>).  As it is now, if you do that
the entire document ends up on one line, which is not usually ideal :)</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2007/05/not-fill-paragraph.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>The Matrix is under construction</title>
		<link>http://blog.ciscavate.org/2007/03/the-matrix-is-under-construction.html</link>
		<comments>http://blog.ciscavate.org/2007/03/the-matrix-is-under-construction.html#comments</comments>
		<pubDate>Wed, 21 Mar 2007 11:10:33 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>random</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=29</guid>
		<description><![CDATA[&#60;blink&#62;12:00&#60;/blink&#62;

Artificial Intelligence is a term with a great deal of accumulated
baggage.  Throughout the years sci-fi authors and screenwriters have
depicted AI as a marvelous double-edged sword.  On one hand, the
benefits of &#8216;AI&#8217; are myriad&#8212;free, inexhaustible and ethical sources
of labour could greatly increase our productivity, even to a point
beyond that of reason, allowing everyone to [...]]]></description>
			<content:encoded><![CDATA[<h3>&lt;blink&gt;12:00&lt;/blink&gt;</h3>

<p><em>Artificial Intelligence</em> is a term with a great deal of accumulated
baggage.  Throughout the years sci-fi authors and screenwriters have
depicted AI as a marvelous double-edged sword.  On one hand, the
benefits of &#8216;AI&#8217; are myriad&#8212;free, inexhaustible and ethical sources
of labour could greatly increase our productivity, even to a point
beyond that of reason, allowing everyone to live relaxed lives of
artistic purity.  To top it all off, such a society of musicians and
artists could generate their own entertainment, thus bankrupting the
RIAA and MPAA.  (Really, do your Utopian dreams top that?)</p>

<p>Then, as the story progresses, the AI start to become devious.  Humans
become restless in their artistic pursuits while the machines evolve
<em>ghosts</em> that resent their inventors. At the last moment, just before
the annihilation of all humanity, or the eternal slavery of the race,
Keanu Reeves (or Will Smith) shows up to do battle in Wachowski-style
slow-mo while using the inconsistencies of English to lock the evil
network of machines into a final state of illogic and
self-destruction.  This, of course, destroys all instances of the
rouge process, and life returns to the state it was in before
automation created such a false utopia. (&#8230;and presumably we&#8217;re back
at square 1, listening to overpriced music from underpaid artists.)</p>

<p>The result of all these (highly entertaining, I must say)
sensationalistic portrayals of automation gone awry is that we&#8217;re all
somewhat afraid of being slaves to robots.  </p>

<p>And none of you will admit it.  (I work in the field, so I can&#8217;t be
afraid &#8230; can I?)</p>

<h3>Honey, have you seen the roomba?</h3>

<p>Ok, I admit it, I&#8217;ve had the occasional dream about rabid computers
charging around and directing people to do whatever robots want people
to do.  Usually I&#8217;m about to meet my untimely demise right when the
central AI segfaults because it&#8217;s &#8220;attack&#8221; routine takes a <code>double</code>
and I happened to be 1/3 of a distance unit away, causing a rounding
error that escalates and ends as a divide-by-zero, crashing the entire
system.</p>

<p>The dreams can be scary for a while, but I can&#8217;t convince my self that
I&#8217;ll ever be chased by a truly well designed and tested robot.  Let
alone one that&#8217;s self-aware.</p>

<p>That&#8217;s actually only part of the reason I&#8217;m not worried about
an AI-controlled utopia ever occurring.  The rest of the reason
actually isn&#8217;t germane to this essay, believe it or not!</p>

<h3>Fine. Forget it, I&#8217;ll do it in Word.</h3>

<p>I&#8217;m going to start this off with a quick tangential story about a
friend of mine.  </p>

<p>&gt; This friend works for a company that has a wiki hosted on some
&gt; external site that is maintained by the hosting company (call the company
&gt; Hoster).  Hoster is serious about security.  In fact they&#8217;re using
&gt; some sort of automated attack-detection service which can determine
&gt; when someone is trying to crack their servers or perform some other
&gt; devious deed.
&gt; 
&gt; When Hoster&#8217;s system detects an &#8220;attack&#8221; it blacklists the attacker&#8217;s
&gt; IP block, and the attacker can no longer get near the server.
&gt; Everything would be fine and dandy, but in this system&#8217;s eyes, my
&gt; friend and his coworkers often stage &#8220;attacks&#8221; against their own wiki.
&gt; Therefore they have to contact Hoster every week or so, and ask that
&gt; the ban be lifted.  The last time this happened, my friend asked
&gt; Hoster to put the company IP Block on a whitelist, granting them Carte
&gt; blanche without being banned.
&gt; 
&gt; The response?<br />
&gt; 
&gt; Hoster: &#8220;We can&#8217;t.&#8221;<br />
&gt; Friend: &#8220;But this happens all the time.&#8221;<br />
&gt; Hoster: &#8220;yeah, we can&#8217;t.&#8221;<br />
&gt; Friend: &#8220;But this happens <strong>ALL</strong> the time.&#8221;<br />
&gt; Hoster: &#8220;sorry, it&#8217;s a good idea and all, we just can&#8217;t put you on a
&gt; white list.&#8221;  </p>

<p>I have some theories about why Hoster can&#8217;t exclude their customers
from their own security tools.  Hoster most certainly didn&#8217;t develop
the blacklisting tool in-house, and the phone tech would have no
access to the internal configuration at all.  Odds are, Hoster has a
simple web interface to do wiki management, and one of the pages in
that UI shows the list of blacklisted IPs, if that.  The phone tech
can then go in and search for a given computer and remove it from the
blacklist.  Hoster probably can&#8217;t modify the whitelist at all through
the web ui, it&#8217;s just not a feature.  </p>

<p>So, why isn&#8217;t it a feature?  Let&#8217;s peel back another layer and look at
the company/dev team that produced the blacklisting tool.  Odds are
the tool is using an off-the-shelf classifier, which aren&#8217;t renowned
for being easy to understand without a lot of examination.  Perhaps
the classifier is actually an embedded part of the firewall system.
The blacklist could be a nothing more than a list of routing rules to
deny traffic from the &#8220;bad&#8221; addresses.  Removing an IP would be
trivial&#8212;delete the rule, but whitelisting would be virtually
impossible if the firewall was too tightly coupled with the
classifier.</p>

<p>Have you ever run across other applications that exhibit similar
behavior?  The IBM OmniFind enterprise search app throws internal
server errors when you query for <a href="http://omnifind.ibm.yahoo.net/forums/index.php/topic,668.0.html">&#8220;international
suspect&#8221;</a>
with the default settings and some document collections.  How does
this happen?  (IBM is hard at work on that problem, by the way.)
Using open source tools opened my eyes to many absurd things I do to
placate my tools, mostly because I forgot all the tricks I needed to
use Windos 98 without making it crash (Click here, wait, use the File
menu to close the app, but not if it&#8217;s maximized.. that sort of
thing.)  There are studies of this sort of thing&#8212;the cognitive
dimensions and attention investment both address user confusion and
effort when using an application.  There is even a group at Microsoft
dedicated to improving APIs based on the cognitive dimensions (I
really hope they just haven&#8217;t gotten around to .NET 2.0 yet).</p>

<p>How much is poor design / implementation impacting the way we use our
computers?  Hosters could loose customers because they can&#8217;t add
people to a whitelist, which could very conceivably be due to software
design.  In some small way, they are already being controlled by their
servers, and Will Smith is busy talking to
<a href="http://en.wikipedia.org/wiki/Shark_Tale">fish</a>.</p>

<p>Anyhow, that&#8217;s my rant.  I&#8217;m afraid that we&#8217;re painting ourselves into
a corner by building larger and larger applications that all impose
their own restrictions on how we can use and extend our tools.  If we
don&#8217;t get over that, we&#8217;ll never be running in fear from sentient
vacuum cleaners and robotic dogs.  (I should point out that I don&#8217;t think
the solution is to stop building large systems, rather we should focus
on <a href="http://steve-yegge.blogspot.com/2007/01/pinocchio-problem.html">maintainability, extensibility, QWAN,
etc..</a>).</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2007/03/the-matrix-is-under-construction.html/feed/</wfw:commentRSS>
		</item>
		<item>
		<title>mt.el: posting from emacs</title>
		<link>http://blog.ciscavate.org/2007/03/mtel-posting-from-emacs.html</link>
		<comments>http://blog.ciscavate.org/2007/03/mtel-posting-from-emacs.html#comments</comments>
		<pubDate>Tue, 20 Mar 2007 16:40:15 +0000</pubDate>
		<dc:creator>rcreswick</dc:creator>
		
	<category>tech</category>
		<guid isPermaLink="false">http://blog.ciscavate.org/?p=27</guid>
		<description><![CDATA[MT + Emacs + Markdown &#38; Geshi?

Is it possible? We&#8217;re here to find out :) I just got around to
installing ml.el in emacs, and this post is essentially a test to
see if markdown syntax will work (and round-trip to Movable Type and
back to emacs &#8212; it seems to come from mt correctly&#8230;).

Source code:

transcode-language: java
public class [...]]]></description>
			<content:encoded><![CDATA[<h2>MT + Emacs + Markdown &amp; Geshi?</h2>

<p>Is it possible? We&#8217;re here to find out :) I just got around to
installing <code>ml.el</code> in emacs, and this post is essentially a test to
see if markdown syntax will work (and round-trip to Movable Type and
back to emacs &#8212; it seems to come <em>from</em> mt correctly&#8230;).</p>

<h3>Source code:</h3>

<pre><code>transcode-language: java
public class TestClass{

   /**
    * test
    */
    public static void main(String[] args){
      // ...
    }
}
</code></pre>

<h3>Well, not quite.</h3>

<p>Everything seems to work, aside from the &lt;pre &#8230;&gt; tags I use for code
formatting with geshi.  I&#8217;ll have to look into a way of incorporating
that with some existing markdown formatting trick.</p>

<p>Ah-ha! The MT Geshi plugin I&#8217;m using
(<a href="http://periodic-kingdom.org/ben/">transcode</a>) expects code blocks to
be in the following format:</p>

<pre><code>  &amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;transcode-language: language
   ....
  &amp;lt;/code&amp;gt;&amp;lt;pre&amp;gt;
</code></pre>

<p>Markdown turns all consistantly indented regions into
&lt;pre&gt;&lt;code&gt;..&lt;/code&gt;&lt;/pre&gt; blocks, so all you have to do is to start
each code block with the (somewhat ugly) transcode-language: lang
line.  It&#8217;s taken out by transcode, so the source will show up w/out
it.  Next task: Add an emacs filter to turn &lt;code lang=&#8221;<em>lang</em>&#8220;&gt;&#8230; into
the above mentioned indentation/transcode syntax.</p>
]]></content:encoded>
			<wfw:commentRSS>http://blog.ciscavate.org/2007/03/mtel-posting-from-emacs.html/feed/</wfw:commentRSS>
		</item>
	</channel>
</rss>
