<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>sn.printf.net</title>
	<link>http://sn.printf.net/</link>
	<language>en</language>
	<description>sn.printf.net - http://sn.printf.net/</description>

<item>
	<title>MononcQc: Keep Your ORM Out of my Controller</title>
	<guid>http://ferd.ca/keep-your-orm-out-of-my-controller.html</guid>
	<link>http://ferd.ca/keep-your-orm-out-of-my-controller.html</link>
	<description>&lt;div&gt;&lt;h2&gt;Keep Your ORM Out of my Controller&lt;/h2&gt;&lt;p&gt;One thing I've learned by working on a few legacy server applications is how a very small leak in an abstraction can be enough to make you lose weeks of work when tiptoeing around it to add or modify a feature, years later.&lt;/p&gt;&lt;p&gt;ORM usage as demonstrated in tutorials online (and therefore in many real life applications) frequently suffers from such leaks. This is a rant about it.&lt;/p&gt;&lt;h3&gt;ORMs Are Middleware, Not an Abstraction&lt;/h3&gt;&lt;p&gt;Object-Relational Mappers are all about abstracting away how you fetch data: they hide SQL, they hide implementation specific idiosyncrasiesm etc. That's a fine goal in itself, but the problem is how it is being used instead.&lt;/p&gt;&lt;p&gt;I frequently see them used straight in the controller to access data from the model layer. After all, most ORMs let you model your object transparently over the database table and often support all the CRUD idioms you might need. Adding more feels like abstraction for the sake of it and a loss of time.&lt;/p&gt;&lt;p&gt;As a perfect study case, let's take the following example from the &lt;a href=&quot;http://www.djangobook.com/en/1.0/chapter05/&quot;&gt;5th chapter of the Django Book&lt;/a&gt;. The following snippet is named &lt;cite&gt;The &quot;Dumb&quot; Way to Do Database Queries in Views&lt;/cite&gt; (&lt;em&gt;views&lt;/em&gt; are Django's equivalent to controllers):&lt;/p&gt;&lt;pre&gt;
def book_list(request):
     db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
     cursor = db.cursor()
     cursor.execute('SELECT name FROM books ORDER BY name')
     names = [row[0] for row in cursor.fetchall()]
     db.close()
     return render_to_response('book_list.html', {'names': names})
&lt;/pre&gt;&lt;p&gt;Now, I agree this isn't the place to put SQL queries. The following solution is instead suggested:&lt;/p&gt;&lt;pre&gt;
 book_list(request):
    books = Book.objects.order_by('name')
    return render_to_response('book_list.html', {'books': books})
&lt;/pre&gt;&lt;p&gt;That's much better, really. The &lt;code&gt;book_list&lt;/code&gt; controller now has a quick access to the objects it needs and is reduced to a much shorter two lines of code.&lt;/p&gt;&lt;p&gt;The problem I see with this is that the really important details are still there. I can still see &quot;Give me a list of all books ordered by name.&quot; Okay, that doesn't sound too bad. That's because the query is very simple. Imagine that your boss comes in and asks you to have a block on a page that returns a list of all books having more than 150 pages, written by British authors who were born in the past century. Moreover, it should be possible to limit the books to a specific category (say, biographies) and it'd be nice to sort them by title.&lt;/p&gt;&lt;p&gt;Suddenly, the query isn't as simple anymore. You begrudgingly replace this and add the query to your controller. It now looks something like (pardon the pseudo-code ORM, no longer Django's): &lt;/p&gt;&lt;pre&gt;
Book.objects.filter('pages', larger_than=150).filter('author.nationality', 'British').filter('author.birthdate', larger_than=1900, smaller_than=2000).filter('category', 'Biography').order_by('name')
&lt;/pre&gt;&lt;p&gt;Oh. Well this is still nicer than the underlying SQL statement to be sure. No handling of joins, no handling of query building.&lt;/p&gt;&lt;p&gt;Now your boss has decided he wants this example search on 6 different pages (that require 6 different controllers). What do you do?&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Copy/paste the query within all 6 controllers&lt;/li&gt;&lt;li&gt;Create a class with a method (or just a function) to handle it&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Chances are the second solution is the best one. Not that we hate the ORM, but the query is pretty complex. What we really want might be something like &quot;OldBritishBiographies()&quot; and use that call in the 6 controllers instead. Now, why is it okay to use the ORM directly in the controller when the query is short, but we all cringe when it's long and ugly? Shouldn't we use only one way or the other?&lt;/p&gt;&lt;p&gt;I argue that &lt;em&gt;all&lt;/em&gt; ORM calls should be wrapped in functions or methods. Otherwise, the programmer reading the code now has to understand something about 'author.birthdate', 'author.nationality' or yet 'name' (why not title?), etc. which are usually database column names.&lt;/p&gt;&lt;p&gt;This means that we're in the controller but we still have to grasp what the hell is going on in the database. The abstraction is leaking! We still need to know how the database works in order to fetch data from our models. That is because ORMs don't abstract away any applicative logic. All they abstract away is 'how you get the data', not 'what you are trying to get'. ORMs are middleware.&lt;/p&gt;&lt;p&gt;Any code base you have that will last a few years and scale up a bit will require a change in technology at some point. You want to move the book inventory to a web service, based on RESTful HTTP calls. Suddenly, none of the ORM calls above work without either tweaking the ORM a whole lot, or changing the calls to books in every controller that deals with them.&lt;/p&gt;&lt;p&gt;Except maybe that call about old British authors. It turns out this one only needs to be changed once, in its implementation. I suggest that this is because &lt;em&gt;adding that descriptive function call completed the abstraction&lt;/em&gt;: you can get your results without caring about whatever the underlying implementation is. It could be done with or without an ORM, straight from text files, or even from a physical scanner with OCR. We just don't care, it needs to be implemented once and that's it.&lt;/p&gt;&lt;p&gt;The ORM is middleware between you and a database. A proper model is an abstraction between the data you get and whatever business logic is hidden behind it.&lt;/p&gt;&lt;h3&gt;But wait, there's more!&lt;/h3&gt;&lt;p&gt;To add to this all, keeping the ORM outside of the controller and inside the model as suggested above makes it infinitely much easier to do any kind of unit or integration testing.&lt;/p&gt;&lt;p&gt;It becomes easy to use whatever integration testing method you want to make sure your code fetches and stores data correctly from and to the database. It also becomes easy to build mock objects or functions to pass to the controller to test it independently from the model implementation.&lt;/p&gt;&lt;p&gt;Conversely, with ORM queries in the controller, verifying that everything goes fine is limited to testing the ORM itself or the controller &lt;em&gt;and&lt;/em&gt; the underlying model at once. There is no easy way to test only one or the other without some copy/paste abuse because the ORM queries only exist as part of the controller.&lt;/p&gt;&lt;p&gt;So on one hand you have code that is easier to modify (because you need to change it at only one place) and to test. On the other hand you have code that is harder to maintain (because it is spread across controllers) and harder to test, just to add a kick to the nuts of the developer responsible of doing it.&lt;/p&gt;&lt;p&gt;Of course, using an ORM in the controller is still leagues better than what I'm having to maintain as described earlier. However, you should not assume your application won't live for more than a few years or that you do not need things such as 'being easier to test'. Please, for the sake of programmers doing maintenance on your code in the future, do your abstractions right. A small leak today is a flood tomorrow.&lt;/p&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 26 Aug 2010 03:25:00 +0000</pubDate>
</item>
<item>
	<title>LOLLERZ: Kittyball go!</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-4364671268218953056</guid>
	<link>http://blake8086.blogspot.com/2010/08/kittyball-go.html</link>
	<description>My game, Kittyball, just went live!&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://itunes.apple.com/us/app/kittyball/id384866969?mt=8&quot;&gt;http://itunes.apple.com/us/app/kittyball/id384866969?mt=8&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/_rsZUZ8HzRaQ/TG39dBFXLII/AAAAAAAAAOI/I7cvoiM4Wec/s1600/kittyball.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/_rsZUZ8HzRaQ/TG39dBFXLII/AAAAAAAAAOI/I7cvoiM4Wec/s320/kittyball.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;After several months of work, and all of Sarah's art contributions, it's nice to finally see it up for sale!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-4364671268218953056?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 19 Aug 2010 23:59:29 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>heeen: Day 6 - Big Basin Park</title>
	<guid>tag:heeen.de,2010:/blog//1.20</guid>
	<link>http://heeen.de/blog/2010/08/day-6---big-basin-park.html</link>
	<description>Es ist Samstag und es steht ein ganztägiger Ausflug an. Wir brechen zeitig auf um den Big Basin Park, bekannt für die gigantischen Redwoord Bäume bzw.&amp;nbsp;&lt;a href=&quot;http://de.wikipedia.org/wiki/K%C3%BCstenmammutbaum&quot;&gt;Küstenmammutbäume&lt;/a&gt;&amp;nbsp;zu besuchen. Der &lt;a href=&quot;http://maps.google.de/maps?f=q&amp;source=s_q&amp;hl=de&amp;geocode=FfNSOgIdt3y5-CHxLUJxd7FKsCnhBF6D3baPgDGermyg990WnQ%3BFUgkNwIdKgq3-CHkCxUiKl5JbQ&amp;q=hilton+garden+inn,+mountain+view+nach+big+basin+park&amp;sll=51.151786,10.415039&amp;sspn=10.727977,28.256836&amp;ie=UTF8&amp;ll=37.274055,-122.11516&amp;spn=0.425093,0.883026&amp;z=10&amp;saddr=hilton+garden+inn,+mountain+view&amp;daddr=big+basin+park&quot;&gt;Weg dorthin&lt;/a&gt;&amp;nbsp;schlängelt sich auf den letzten 10 Meilen durch Wälder und Berge, sehr malerisch und eine tolle Route zu fahren.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/mtview/DSC_4498.jpg&quot;&gt;&lt;img alt=&quot;DSC_4498.jpg&quot; src=&quot;http://heeen.de/blog/assets_c/2010/08/DSC_4498-thumb-600x399-50.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;http://heeen.de/galleries/bigbasin&quot;&gt;mehr Bilder...&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Im Park wandern wir eine kürzere der zahlreichen Wanderrouten. Start- und Endpunkt der Kreisrouten ist dabei das Rangerhauptquartier, Holzhütten wie aus dem Pfadfinderbilderbuch. Die Bäume sind wirklich riesig und ihr Ausmass wird einem erst bewusst wenn man sich an den Stamm stellt und die Arme ausbreitet. Die Route führt an einem Wasserfall vorbei, der sich jedoch eher als Rinnsal herausstellt. Es soll auf weiteren Routen noch wesentlich größere Wasserfälle geben.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wieder am Ranger Hauptquartier besuchen wir noch den Souvenierladen. Neben allerlei Kitsch, Nippes und T-Shirts gibt es auch Campingartikel. In der Mitte des Laden befindet sich eine Couch vor einem offenen Holzkamin - sehr gemütlich.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Bevor wir uns auf den Heimweg machen, beschließen wir einfach aufs geradewohl zur Pazifikküste zu fahren. Als es aus den Hügeln geht, halten wir am nächstbesten Parkplatz an und finden eine Bucht wie aus dem Reiseführer: Sandstrand und an Felsen brechende Wellen. Die Bucht ist zweigeteilt, vorne halten einige Familien Piknik während der hintere Teil nur von einer Hand voll nackter Männer beim Sonnenbad besiedelt ist. Das hat mich überrascht, hält man doch Amerika für das Land der Prüderie - doch darf man nicht vergessen daß wir im Dunstkreis von San Francisco befinden.&lt;/div&gt;</description>
	<pubDate>Thu, 19 Aug 2010 05:46:38 +0000</pubDate>
</item>
<item>
	<title>zootm: Simple JVM sandboxing</title>
	<guid>tag:blogger.com,1999:blog-9162692450121869291.post-8364813598985053242</guid>
	<link>http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html</link>
	<description>&lt;p&gt;I have written an dumb IRC bot which (among other things) can &lt;a href=&quot;http://calumleslie.tumblr.com/post/39267836/my-stupid-irc-bot-works&quot;&gt;run scripts in arbitrary languages&lt;/a&gt;, provided they have Java implementations wrapped by the &lt;a href=&quot;https://scripting.dev.java.net/&quot;&gt;JSR-223 scripting API&lt;/a&gt; (a.k.a. &lt;code&gt;javax.script&lt;/code&gt; in Java 6). At the moment I've got it doing Ruby, Groovy, Javascript and Scheme.&lt;/p&gt;
&lt;p&gt;As part of this I decided that I needed to security restrict the script runner, since by design people will essentially be able to run arbitrary code in it. Java is so kind as to provide this sort of sandboxing functionality in its core framework (this is the same sort of security protection offered when you ran Java as an applet on a webpage years ago when applets were still cool), and although it's very well documented on a high-level online, I found it difficult to find a low-level explanation on exactly how to use the code to build a sandbox like I wanted, so here's how I ended up doing it.&lt;/p&gt;
&lt;p&gt;It's worth noting that my IRC bot is actually written in Scala, so the actual Java code here (translated) is probably not well-tested. I've put the Scala wrapper I made at the foot of the entry in case it's useful to anyone.&lt;/p&gt;
&lt;h2&gt;First step &amp;ndash; enable a SecurityManager&lt;/h2&gt;
&lt;p&gt;The first thing to realise (I certainly didn't) is that none of the security infrastructure in Java does anything until you enable it. By default the security policy checks are disabled (presumably for performance reasons); to enable them you need to attach an instance of &lt;code&gt;SecurityManager&lt;/code&gt; to the system. You only need to do this once, and I'd recommend doing it as part of your app setup. It's really easy to do:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-java&quot;&gt;System.setSecurityManager(new SecurityManager());&lt;/pre&gt;
&lt;p&gt;The important thing to notice is that the current security policy &amp;mdash; as defined by your &lt;code&gt;.java.policy&lt;/code&gt; file in your home directory (I believe this is the same on Windows, incidentally), which will fall back to a very restrictive policy (the one used for applets) if the file doesn't exist. Now really I'd like any code that resides on my machine to run without sandboxing even when a security manager is in place (I like to live dangerously), so I can enter the following into my &lt;code&gt;/home/calum/.java.policy&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;grant codeBase &quot;file:/home/calum/-&quot; {
  permission java.security.AllPermission;
};&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;/-&lt;/code&gt; at the end matches all files below that directory recursively. One can also use &lt;code&gt;/*&lt;/code&gt; to match all JAR and class files in a directory, &lt;code&gt;/&lt;/code&gt; to match only class files, and specify individual files. For more information on policy files, check out &lt;a href=&quot;http://java.sun.com/j2se/1.3/docs/guide/security/PolicyFiles.html&quot;&gt;this tasty document&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Once you create this file, it overrides the default Java policy for anything you have a rule for. &lt;em&gt;Do not just blanket grant permissions without a &lt;code&gt;codeBase&lt;/code&gt;&lt;/em&gt;, you will be opening yourself to a world of hurt, in security terms.&lt;/p&gt;
&lt;p&gt;Once you've restricted your JVM's permissions by adding a &lt;code&gt;SecurityManager&lt;/code&gt;, then un-restricted them by granting the permissions back, you're ready to actually manipulate security on parts of code in your app.&lt;/p&gt;
&lt;h2&gt;Constructing an simple sandbox&lt;/h2&gt;
&lt;p&gt;Code can be invoked at modified privilege levels by the static &lt;code&gt;AccessController.doPrivileged(PrivilegedAction,AccessControlContext)&lt;/code&gt; method. For this, we need to construct a &lt;code&gt;PrivilegedAction&amp;lt;T&amp;gt;&lt;/code&gt; (essentially a &lt;code&gt;Callable&amp;lt;T&amp;gt;&lt;/code&gt;) which encapsulates the logic to be run (if the logic throws an exception, you can use &lt;code&gt;PrivilegedExceptionAction&amp;lt;T&amp;gt;&lt;/code&gt; instead). For our simple case we can fill this context with a single &lt;code&gt;ProtectionDomain&lt;/code&gt; with a &lt;code&gt;CodeSource&lt;/code&gt; (codesource can never be null) which is constructed will &lt;code&gt;null&lt;/code&gt; values to indicate unsigned code from an unknown location, and a &lt;code&gt;PermissionCollection&lt;/code&gt; consisting &lt;em&gt;only&lt;/em&gt; of the permissions we'd like to grant our code (represented below as &lt;code&gt;perms&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-java&quot;&gt;// Cast to Certificate[] required because of ambiguity:
ProtectionDomain domain = new ProtectionDomain( new CodeSource( null, (Certificate[]) null ), perms ); 
AccessControlContext context = new AccessControlContext( new ProtectionDomain[] { domain } );
T result = AccessController.doPrivileged(action, context);&lt;/pre&gt;
&lt;p&gt;Here's a full Java program which demonstrates the use of these methods (huge, I'm afraid &amp;mdash; I've omitted the imports for brevity):&lt;p&gt;
&lt;pre class=&quot;prettyprint lang-java&quot;&gt;public class SandboxTest {
 private static final File file = new File( &quot;/etc/motd&quot; );
 
 public static void main(String[] args) throws Exception
 {
  // Do not forget this line!
  System.setSecurityManager( new SecurityManager() );
  
  System.out.println( &quot;Calling method directly:&quot; );
  
  System.out.println( readFirstFileLine(file).run() );
  
  System.out.println( &quot;Calling method in restrictive sandbox:&quot; );
  
  System.out.println( callInSandbox( new Permissions() ) );
  
  System.out.println( &quot;Calling method with file read permission:&quot; );
  
  Permissions perms = new Permissions();
  perms.add( new FilePermission( &quot;/etc/motd&quot;, &quot;read&quot; ) );
  
  System.out.println( callInSandbox(perms) );
 }
 
 private static String callInSandbox( PermissionCollection perms )
 {
  ProtectionDomain domain = new ProtectionDomain( new CodeSource( null, (Certificate[]) null ), perms );
  AccessControlContext context = new AccessControlContext( new ProtectionDomain[] { domain } );
  try
  {
   return AccessController.doPrivileged( readFirstFileLine(file), context );
  }
  catch( Exception e )
  {
   return e.toString();
  }
 }
 
 private static PrivilegedExceptionAction&amp;lt;String&amp;gt; readFirstFileLine( final File file )
 {
  return new PrivilegedExceptionAction&amp;lt;String&amp;gt;() 
  {
   @Override
   public String run() throws Exception {
    BufferedReader reader = new BufferedReader( new FileReader( file ) );
    
    try
    {
     return reader.readLine();
    }
    finally
    {
     reader.close();
    }
   }
  };
 }
}&lt;/pre&gt;
&lt;p&gt;On my machine, this yields:&lt;/p&gt;
&lt;pre&gt;Calling method directly:
Linux thoth 2.6.24-19-generic #1 SMP Wed Jun 4 16:35:01 UTC 2008 i686
Calling method in restrictive sandbox:
java.security.AccessControlException: access denied (java.io.FilePermission /etc/motd read)
Calling method with file read permission:
Linux thoth 2.6.24-19-generic #1 SMP Wed Jun 4 16:35:01 UTC 2008 i686&lt;/pre&gt;
&lt;h2&gt;Touch of Scala&lt;/h2&gt;
&lt;p&gt;Since I developed my app in Scala, here's a little object I built for simplifying this process. It works similarly to the &lt;code&gt;callInSandbox&lt;/code&gt; method above, but also wraps Scala functions so you can use closures pretty simply:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;import java.security._
import java.net.URL

object Security {
  private val codeSource = new CodeSource( null: URL, null: Array[cert.Certificate] )

  def sandboxed[T]( perms: PermissionCollection )( f: =&gt; T): T = {
    val domain = new ProtectionDomain( codeSource, perms )
    val context = new AccessControlContext( Array( domain ) )

    AccessController.doPrivileged( new Action( f ), context )
  }

  private class Action[T]( f: =&gt; T ) extends PrivilegedAction[T] {
    override def run() = f
  }
}&lt;/pre&gt;
&lt;p&gt;In order to use this, construct your &lt;code&gt;Permissions&lt;/code&gt; that you want to grant to the item, import &lt;code&gt;Security.sandboxed&lt;/code&gt;, and just wrap like this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;sandboxed( perms ) {
  println( &quot;This code is running within the sandbox!&quot; )
}&lt;/pre&gt;
&lt;p&gt;I hope this helps someone out!&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9162692450121869291-8364813598985053242?l=calumleslie.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 19 Aug 2010 06:33:31 +0000</pubDate>
	<author>noreply@blogger.com (Calum)</author>
</item>
<item>
	<title>zootm: Java gotcha o' the day</title>
	<guid>tag:blogger.com,1999:blog-9162692450121869291.post-2697427375758817600</guid>
	<link>http://calumleslie.blogspot.com/2008/02/java-gotcha-o-day.html</link>
	<description>Here's something in Java that I just couldn't predict what it was going to do:

&lt;pre class=&quot;prettyprint lang-java&quot;&gt;
try
{
    try
    {
        throw new RuntimeException(&quot;Lost?&quot;);
    }
    finally
    {
        throw new RuntimeException(&quot;Interloper&quot;);
    }   
}
catch (Exception e)
{
    System.out.println(e);
}
&lt;/pre&gt;

In hindsight I guess it's obvious that the exception thrown in the &lt;tt&gt;finally&lt;/tt&gt; block would take precedence, but losing exceptions without having to explicitly deal with them seems quite the dangerous thing. It's just strange to say.

That said, anyone throwing exceptions from a &lt;code&gt;finally&lt;/code&gt; block should probably be strung up anyway.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9162692450121869291-2697427375758817600?l=calumleslie.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 19 Aug 2010 06:31:04 +0000</pubDate>
	<author>noreply@blogger.com (Calum)</author>
</item>
<item>
	<title>zootm: Here's a feature I made earlier</title>
	<guid>tag:blogger.com,1999:blog-9162692450121869291.post-592799253480128552</guid>
	<link>http://calumleslie.blogspot.com/2008/03/after-being-suitably-wowed-by-max.html</link>
	<description>&lt;p&gt;After being suitably wowed by &lt;a href=&quot;http://blog.omega-prime.co.uk&quot;&gt;Max Bolingbroke&lt;/a&gt;'s &lt;a href=&quot;http://blog.omega-prime.co.uk/2007/08/25/implementing-the-disposable-pattern-in-scala/&quot;&gt;implementing the Disposable pattern from C# in my current language-of-obsession Scala&lt;/a&gt;, I was looking at some of the other features of C#/.NET which are quite nice, and wondering how they could be implemented.&lt;/p&gt;
&lt;p&gt;One set of stuff that is available in C# is the much-talked-about 
&lt;abbr title=&quot;Language INtegrated Query&quot;&gt;LINQ&lt;/abbr&gt; system, which lets you combine and query lists in a way fairly similar to SQL. They also do a bunch of clever things (like actually translating these queries into SQL, from what I can tell) but let's gloss over that for now.&lt;/p&gt;
&lt;p&gt;In any case, there was a few of these operators don't exist in the Scala library, and since it's fairly easy to push new things onto objects in Scala, I decided to see how easily I could model them. For kicks.&lt;/p&gt;

&lt;p&gt;Before I start proper I should mention two things:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;I'm assuming programming knowledge, and probably some Scala experience here. That said, if you're used to this type of language you shouldn't have too much trouble reading the code examples, and hopefully you'll like the way the language works. If there's any questions, though, just comment. I don't imagine I'm a great writer.&lt;/li&gt;
 &lt;li&gt;There is probably better ways to do this stuff; I'm not hugely experienced with the language (I have at least thought of alternate ways to do some of the things). I'd be interested to hear any other approaches people have on this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the first of two posts. In this one I'm going to set the stage, and do something simple. In the next one I'm going to continue down the same road, and so something a little more complicated.&lt;/p&gt;

&lt;h2&gt;&quot;Adding&quot; our own methods onto an existing class&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: &lt;a href=&quot;http://calumleslie.blogspot.com/2008/03/better-classing-through-scala.html&quot;&gt;This follow-up article&lt;/a&gt; shows a way of doing this that should make the code a bit more re-usable. The principle is pretty much the same, though.&lt;/p&gt;
&lt;p&gt;This is just a bit of preparation for other things. Trust me when I say that we're going to want to put (or appear to put) extra methods onto objects with the &lt;code&gt;Iterable&lt;/code&gt; trait. It's what all the cool kids are doing.&lt;/p&gt;
&lt;p&gt;Following the naming scheme put forth by the Scala standard library, we can create a &lt;code&gt;RichIterable&lt;/code&gt; class which will house the extra stuff we're going to be putting on the normal &lt;code&gt;Iterable&lt;/code&gt; class, and make it a class which &quot;wraps&quot; an existing iterable object. With an implicit type conversion function which will wrap it up transparently, we can treat any &lt;code&gt;Iterable&lt;/code&gt; as a &lt;code&gt;RichIterable&lt;/code&gt; whereever the function is imported. This is done like so:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;object RichIterable
{
  implicit def iterable2RichIterable[A]( iterable: Iterable[A]) = new RichIterable( iterable )
}

class RichIterable[A]( inner: Iterable[A] )
{ 
  // Extra functions go here...
}&lt;/pre&gt;
&lt;p&gt;Now all one needs to do is add the line &lt;code&gt;import whatever.package.RichIterable._&lt;/code&gt; and the power of these new methods will be theirs.&lt;/p&gt;

&lt;h2&gt;Pushing things into a map &amp;ndash; &lt;code&gt;toMap&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This first one is the simplest of the methods I decided to implement; it is based on the &lt;a href=&quot;http://blogs.msdn.com/timng/archive/2007/12/12/using-the-todictionary-extension-method.aspx&quot;&gt;ToDictionary&lt;/a&gt; method available in .NET. Basically the motivation is this:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;I have a set of items with some distinguising property. I would like to put them into a Map object keyed on this property so I can look them, or maybe some property derived from them, up quickly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's a more concrete example; we have our typical terrible-example-of-object-orientation class representing a car by its registration plate number and the name of its driver, which looks like so:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;class Car( registration: String, driver: String )
{
  val getRegistration = registration
  val getDriver = driver
}&lt;/pre&gt;
&lt;p&gt;We have a big list of cars (a &lt;code&gt;List[Car]&lt;/code&gt;, if you will), but what we really want is a map from the registration plate number to the driver name, so we can do something like this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;val guiltyDriver = registrationMap( registrationOfCarSeenLeavingInAHurry )&lt;/pre&gt;
&lt;p&gt;We'd like to generate this map quickly and easily, and this is where the &lt;code&gt;toMap&lt;/code&gt; function comes in; we want to be able to do something like:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;val registrationMap = carList.toMap( _.getRegistration, _.getDriver )&lt;/pre&gt;
&lt;p&gt;This is fairly easy to achieve via a number of means, but I chose to build the inputs to the immutable &lt;code&gt;Map&lt;/code&gt;'s factory method. It takes any number of two-item tuples (doubles) and gives you a &lt;code&gt;Map&lt;/code&gt; object back. So to construct those tuples from values in the list in this case we could do something like this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;a =&gt; ( a.getRegistration, a.getDriver )&lt;/pre&gt;
&lt;p&gt;Or more generally for a given function for the key, and one for the value:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;a =&gt; ( keyFunc(a), valFunc(a) )&lt;/pre&gt;
&lt;p&gt;So to map an entire Iterable object (like our List) using these two functions, we could do this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;val tuples = inner.map( a =&gt; ( keyFunc(a), valFunc(a) ) ).toStream&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;toStream&lt;/code&gt; at the end is just there because the fussy &lt;code&gt;Map&lt;/code&gt; constructor wants a &lt;code&gt;Seq&lt;/code&gt;. Presumably because it wants some guarantee that there's a finite number of elements. Wuss.&lt;/p&gt;
&lt;p&gt;So to put this into a function we just need to take in the two functions, and push it out to the &lt;code&gt;Map&lt;/code&gt; factory method:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;def toMap[K,V]( keyFunc: (A) =&gt; (K), valFunc: (A) =&gt; (V) ): Map[K,V]  = {
  val tuples = inner.map( a =&gt; ( keyFunc(a), valFunc(a) ) ).toStream
    
  Map( tuples: _* )
}&lt;/pre&gt;
&lt;p&gt;This uses &lt;code&gt;K&lt;/code&gt; for the type of the key, and &lt;code&gt;V&lt;/code&gt; for the type of the value. The &lt;code&gt;_*&lt;/code&gt; type parameter makes the &lt;code&gt;Seq&lt;/code&gt; of tuples appear like a bunch of arguments, since this isn't automatic (this is similar to &lt;code&gt;params&lt;/code&gt; in C# or the &lt;code&gt;...&lt;/code&gt; thing in Java).&lt;/p&gt;
&lt;p&gt;This now works fine; so we can do something like this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;import RichIterable._
  
val cars = List(
    new Car( &quot;SANTA1&quot;, &quot;Santa Claus&quot; ),
    new Car( &quot;PANDA1&quot;, &quot;P.C. Plod&quot; ),
    new Car( &quot;12345&quot;, &quot;Count Count&quot; ) )
      
val registrationMap = cars.toMap( _.getRegistration, _.getDriver )

println( registrationMap )
  
println( registrationMap(&quot;SANTA1&quot;) )&lt;/pre&gt;
&lt;p&gt;And we get the output:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;Map(SANTA1 -&gt; Santa Claus, PANDA1 -&gt; P.C. Plod, 12345 -&gt; Count Count)
Santa Claus&lt;/pre&gt;
&lt;p&gt;...which is of course ridiculous, since Santa rides in a sleigh rather than driving a car.&lt;/p&gt;
&lt;p&gt;For convenience, we can also fulfil the situation where we just want to push our objects into a map keyed by the result of a function; that is, the same as the above, but the value should just be the input object. This is likely to be a fairly common use-case, so let's not make people type a lot to do it:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;def toMap[K]( keyFunc: (A) =&gt; (K) ): Map[K, A] = toMap( keyFunc, a =&gt; a )&lt;/pre&gt;
&lt;p&gt;This is just calling the existing &lt;code&gt;toMap&lt;/code&gt; function with &lt;code&gt;a =&gt; a&lt;/code&gt; (the identity function, a fancy name for a function which does nothing at all) as &lt;code&gt;valFunc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the next entry, I'm going to do something more substantial; an analogue to &lt;code&gt;GROUP BY&lt;/code&gt; in SQL, which was the feature of LINQ I wanted the most. If you're too anxious to wait, &lt;a href=&quot;http://www.zootm.co.uk/coding/RichIterable.scala&quot;&gt;this code is available here&lt;/a&gt;. It's a little untidy and uncommented at present, though (and doesn't currently contain a bunch of improvements I've since added).&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9162692450121869291-592799253480128552?l=calumleslie.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 19 Aug 2010 06:29:00 +0000</pubDate>
	<author>noreply@blogger.com (Calum)</author>
</item>
<item>
	<title>zootm: Better classing through Scala</title>
	<guid>tag:blogger.com,1999:blog-9162692450121869291.post-6836806578507959284</guid>
	<link>http://calumleslie.blogspot.com/2008/03/better-classing-through-scala.html</link>
	<description>&lt;p&gt;Rather than the promised follow-up to my last post (it's coming, honest), I'm just going to update the way that I did the first section of that post. I realised earlier that rather than making my hastily-constructed &lt;code&gt;RichIterable&lt;/code&gt; a &lt;em&gt;class&lt;/em&gt;, I should have made it a &lt;em&gt;trait&lt;/em&gt;. In this way, other classes can use its functionality explicitly if they know about it and, critically, can override the functionality in a way that makes more sense to them.&lt;/p&gt;
&lt;p&gt;To do this and still be able to do the implicit cast thing I showed, we also need a concrete class to mix the trait in with. Since you can't (&lt;em&gt;as far as I know&lt;/em&gt;) mix in traits after you've created an object, if we just create a wrapper class for &lt;code&gt;Iterable&lt;/code&gt; objects:&lt;/p&gt;
&lt;pre&gt;class IterableWrapper[A]( underlying: Iterable[A] ) extends Iterable[A]
{
  override def elements = underlying.elements
}&lt;/pre&gt;
&lt;p&gt;Which means we can now express the implicit function from before as so, creating a new wrapper with our trait mixed in:&lt;/p&gt;
&lt;pre&gt;implicit def iterable2RichIterable[A]( iterable: Iterable[A]) = {
  new IterableWrapper( iterable ) with RichIterable[A]
}&lt;/pre&gt;
&lt;p&gt;This means that any other collection can just extend the &lt;code&gt;RichIterable&lt;/code&gt; trait if they don't want to require the type conversion to use the new methods, or if they want to replace the functions with better implementations. Our actual &lt;code&gt;RichIterable&lt;/code&gt; trait can be a subtrait of &lt;code&gt;Iterable&lt;/code&gt;, too, meaning less indirection. It's wonderful I tells ya.&lt;/p&gt;
&lt;p&gt;The extra curly brackets here do absolutely nothing; I just feel it's clearer to add them in if an expression like this one is too long to fit on a line.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9162692450121869291-6836806578507959284?l=calumleslie.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 19 Aug 2010 06:23:12 +0000</pubDate>
	<author>noreply@blogger.com (Calum)</author>
</item>
<item>
	<title>zootm: Silly placeholder post</title>
	<guid>tag:blogger.com,1999:blog-9162692450121869291.post-1298444682332567855</guid>
	<link>http://calumleslie.blogspot.com/2009/04/silly-placeholder-post.html</link>
	<description>&lt;p&gt;I should update this blog more. Maybe just a little thing right now: I really like the option parsing library &lt;a href=&quot;http://trollop.rubyforge.org/&quot;&gt;Trollop&lt;/a&gt; for Ruby. It's a great little system, and its values (or the ones important to me, at least) are that &lt;em&gt;it is as easy as possible for the library consumer to use&lt;/em&gt;. I've been experimenting with making one with similar values for Scala, adding in the type safety and the like that you get with that language, while aiming to still keep a fluent interface.&lt;/p&gt;
&lt;p&gt;Using it looks like this:&lt;/p&gt;
&lt;pre class=&quot;prettyprint lang-scala&quot;&gt;object Main extends OptionApplication {
 val options = new Options {
   banner = &quot;&quot;&quot;
This is my test application.
There are many like it, but this one is mine.

Usage: Main [options]
&quot;&quot;&quot;
  
   val name = string( &quot;Name to greet&quot;, default( &quot;Nobody&quot; ) )
   val alternativeGreeting = flag( &quot;Use an alternative greeting&quot; )
 }

 import options._

 def main() {
   val greeting = if( alternativeGreeting.value ) {
     &quot;Bonjour, %s!&quot;
   } else {
     &quot;Hello, %s!&quot;
   }
  
   println( greeting format name.value )
 }
}&lt;/pre&gt;
&lt;p&gt;Calling it from the &quot;command line&quot; (okay, I did it through Eclipse):&lt;/p&gt;
&lt;pre&gt;&amp;gt; Main --help
This is my test application.
There are many like it, but this one is mine.

Usage: Main [options]

Options:
-a, --alternative-greeting - Use an alternative greeting
               -h, --help - This help page
               -n, --name - Name to greet (default: Nobody)&lt;/pre&gt;
&lt;pre&gt;&amp;gt; Main -n Calum --alternative-greeting
Bonjour, Calum!&lt;/pre&gt;
&lt;pre&gt;&amp;gt; Main --pleasehelpme
Problem with options: unrecognised argument 'pleasehelpme'
Try --help for help.&lt;/pre&gt;
&lt;p&gt;Anyway, beyond just a random tour of that, why do I think this sort of thing is interesting? I like the idea that Scala works as a statically-type &quot;scripting&quot; language, as well as in the domains where Java works. I like the idea that command line tools and so on could be built with this easily. Java tends to only be used for huge big systems run inside containers and the like, because it's geared very much towards building the sort of huge system where this makes sense. Scala is fluid enough to give a lot of the advantages in fluidity you see from languages like Python and Ruby, and while it's a little more verbose, I think it's a useful alternative depending on your values.&lt;/p&gt;
&lt;p&gt;What Scala is really missing, to me, is little &quot;fun&quot; libraries like you find in the form of Python Eggs and Ruby Gems. There's a lot of nice, impressive, projects but I'd like to see more in the realm of small projects that aren't necessarily a work of architectural genius, but are useful (or quirky) and encourage people to dabble and play. Java lacks a sense of fun and there's no reason that Scala should end up down that route. I might go into more detail with that feeling later; this is pretty poorly-drafted. Oh well!&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/9162692450121869291-1298444682332567855?l=calumleslie.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 18 Aug 2010 17:48:43 +0000</pubDate>
	<author>noreply@blogger.com (Calum)</author>
</item>
<item>
	<title>LOLLERZ: New Project</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-64463469213939262</guid>
	<link>http://blake8086.blogspot.com/2010/08/new-project.html</link>
	<description>I have started a project to create a site for developers and designers to share and collaborate on UI mockups and designs.&lt;br /&gt;&lt;br /&gt;In the past, I have found it extremely frustrating to work on UI design with the current tools available. &amp;nbsp;Trading zips of files through email and giant PDFs of mockup screens on shared storage are terrible ways to work.&lt;br /&gt;&lt;br /&gt;It's hard to keep track of different versions.&lt;br /&gt;It's hard to keep track of comments everyone has made.&lt;br /&gt;It's hard for more than 2 people to be involved in the process.&lt;br /&gt;It's hard to highlight changes.&lt;br /&gt;&lt;br /&gt;I'm going to solve all of those problems.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-64463469213939262?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 17 Aug 2010 01:05:34 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>LOLLERZ: Kittyball submitted!</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-5464412711970251586</guid>
	<link>http://blake8086.blogspot.com/2010/08/kittyball-submitted.html</link>
	<description>I somehow forgot to mention this when I did it, but I submitted KittyBall to the App Store on Monday, August 9th. &amp;nbsp;I guess we'll see what Apple thinks of it.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-5464412711970251586?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 17 Aug 2010 01:04:28 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>king_kllr: Education Slides</title>
	<guid>http://alexgaynor.net/2010/aug/16/education-slides/</guid>
	<link>http://alexgaynor.net/2010/aug/16/education-slides/</link>
	<description>&lt;p&gt;This past weekend I attended a symposium on authentic learning, in Santa Barbara, California.  I gave a talk there about Open Source, and how we emulate the practices of a learning community (as often seen in colleges and universities) and whether the pedagogal practices we engange in (to help get new contributors started, and hopefully guide them to becoming committers) are applicable to other fields.  Unfortunately the talk wasn't recorded, however my slides are available &lt;a class=&quot;reference external&quot; href=&quot;http://www.scribd.com/doc/35967063&quot;&gt;online&lt;/a&gt;, there is also an accompanying paper that will be available in the future.&lt;/p&gt;</description>
	<pubDate>Mon, 16 Aug 2010 18:30:06 +0000</pubDate>
</item>
<item>
	<title>MononcQc: Yet Another Article on Zippers</title>
	<guid>http://ferd.ca/yet-another-article-on-zippers.html</guid>
	<link>http://ferd.ca/yet-another-article-on-zippers.html</link>
	<description>&lt;div&gt;&lt;h2&gt;Yet Another Article on Zippers, in Erlang&lt;/h2&gt;&lt;h3&gt;What are zippers?&lt;/h3&gt;&lt;p&gt;In Erlang (and in many other programming languages which include a functional subset), operations on purely functional data structures are frequently limited to &lt;code&gt;O(log n)&lt;/code&gt; time complexity: there is no such thing as a true array with constant time access. No destructive updates. Nothing like pointers either.&lt;/p&gt;&lt;p&gt;Because of this, you end up with a bunch of modules like &lt;a href=&quot;http://erldocs.com/R14A/stdlib/array.html&quot;&gt;array&lt;/a&gt;, &lt;a href=&quot;http://erldocs.com/R14A/stdlib/dict.html&quot;&gt;dict&lt;/a&gt;, &lt;a href=&quot;http://erldocs.com/R14A/stdlib/gb_trees.html&quot;&gt;gb_trees&lt;/a&gt; and whatnot, which are all built either on lists or trees with varying branching factors. None of them do better than &lt;code&gt;O(log n)&lt;/code&gt;, and list-based solutions don't do better than &lt;code&gt;O(n)&lt;/code&gt; (although they can average &lt;code&gt;n/2&lt;/code&gt;.)&lt;/p&gt;&lt;p&gt;There is, however, a class of data-structures that allow for &lt;a href=&quot;http://en.wikipedia.org/wiki/Amortized_constant_time&quot;&gt;amortized constant time&lt;/a&gt; for some operations: &lt;a href=&quot;http://en.wikipedia.org/wiki/Finger_tree&quot;&gt;finger trees&lt;/a&gt; and zippers are examples of this.&lt;/p&gt;&lt;p&gt;So let's say you are writing a text editor and you need to hold a list of all the events typed in the currently open document. The naive implementation with standard data structures such as lists would force something a bit like &lt;code&gt;[{TimeN, ChangeN}, {TimeN-1, ChangeN-1}, ..., {Time1, Change1}}]&lt;/code&gt;. That is, every time the user modifies the document, an entry of the form &lt;code&gt;{Time, Change}&lt;/code&gt; is added to the beginning of the list.&lt;/p&gt;&lt;p&gt;What happens when the user wants to go back in history? A lot of programmers might just borrow the non-functional 'array and indexes' method: we keep a counter in memory (which acts like an index), and when the user presses some 'back' button, the index becomes N+1, N+2, etc. Conversely, when the user presses 'next', we remove 1 from that number:&lt;/p&gt;&lt;pre class=&quot;brush:eshell&quot;&gt;
1&amp;gt; lists:nth(1,[current,recent,old,older,oldest]).
current
2&amp;gt; lists:nth(2,[current,recent,old,older,oldest]).
recent
3&amp;gt; lists:nth(3,[current,recent,old,older,oldest]).
old
4&amp;gt; lists:nth(2,[current,recent,old,older,oldest]).
recent
&lt;/pre&gt;&lt;p&gt;This approach is directly based on how we're used to deal with arrays or dictionaries that support constant time access. Sadly, it's rather inefficient with functional data structures: the access time in the example above is &lt;code&gt;O(n)&lt;/code&gt;. If the document's history contains thousands of changes and the user loves to go through them, you end up doing a bunch of useless lookups, all the time. It's even worse if you allow the user to update the history and whatnot: not only do you need to traverse the list for lookups, but you need to rewrite a good part of the data structure every time you update it.&lt;/p&gt;&lt;p&gt;A valid alternative solution is to store everything we have traversed before in a secondary structure in order for the 'current' element to always be accessible in constant time. Instead of storing something like &lt;code&gt;{3,[d,c,b,a]}&lt;/code&gt;, you'd store &lt;code&gt;{[c,d],[b,a]}&lt;/code&gt;, or more generally: &lt;code&gt;{Previous, [Current|Next]}&lt;/code&gt;, where &lt;var&gt;Previous&lt;/var&gt; (the history of visited items) and &lt;var&gt;Next&lt;/var&gt; (those left to go through) are both lists and &lt;var&gt;Current&lt;/var&gt; is a single term. See the code below for an idea of how this works with more detail.&lt;/p&gt;&lt;p&gt;Not only does this approach make the current element accessible in constant time, but the previous and next one too! This lets you use the list a bit as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Doubly_linked_list&quot;&gt;doubly-linked list&lt;/a&gt; in languages that support them, as in you can hold a 'pointer' to the current list location, and you can iterate backwards and forwards with little overhead. Moreover, changes to the list can be made in constant time (once you're at the right position) and the cost of modifying the elements is spent only when going backwards in the list.&lt;/p&gt;&lt;p&gt;Well that's a zipper. In this particular case, this would be a zipper with a list. &lt;em&gt;Zipper&lt;/em&gt; is a generic term used to qualify a data structure that you can arbitrarily modify and navigate through.&lt;/p&gt;&lt;p&gt;I don't know if I'm being clear enough, but I nevertheless suggest the following articles if you want to get real information on zippers, rather than just my own little primer:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Zipper_(data_structure)&quot;&gt;Zipper (data structure) on Wikipedia&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.haskell.org/haskellwiki/Zipper&quot;&gt;Zippers with trees on Haskell wiki&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://blog.ezyang.com/2010/04/you-could-have-invented-zippers/&quot;&gt;You could have invented zippers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://en.wikibooks.org/wiki/Haskell/Zippers&quot;&gt;Theseus and the Zipper&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I especially recommend the last link (the part before type differentiation). It's the one I found the easiest to understand, although you need to be able to grasp Haskell's type system to understand it.&lt;/p&gt;&lt;h2&gt;Zipper lists&lt;/h2&gt;&lt;p&gt;So as described above, a list that we can go through in both directions [because we store seen elements] is a zipper, and can be implemented by holding a list/stack of all the elements we went through. Here's an implementation of zipper lists (abbreviated to zlists) according to the &lt;code&gt;{Previous, [Current | Next]}&lt;/code&gt; structure:&lt;/p&gt;&lt;pre class=&quot;brush:erl&quot;&gt;
-module(zlists).
-export([list_to_zlist/1, zlist_to_list/1,
         prev/1, next/1, current/1,
         replace/2, insert/2, delete/1,
         map/2, rmap/2]).

%% A zlist, or zipper list, allows to 'browse' a list
%% in two directions, much like a doubly-linked list.
%% Access to the next and previous element are both
%% constant time, and so is the cost of insertion and
%% deletion.
%% Lookups remain O(n).

%% {Previous, [Current | Next]}.
-type zlist() :: {list(), list()}.

%% Most zippers data structures wouldn't really need to convert between
%% types, but lists are kind of ubiquitous in usage, so it might be
%% proper to convert them.
%% Convert from standard list to zlist
-spec list_to_zlist(list()) -&amp;gt; zlist().
list_to_zlist(L) when is_list(L) -&amp;gt; {[], L}.

-spec zlist_to_list(zlist()) -&amp;gt; list().
zlist_to_list({Pre, Post}) -&amp;gt; lists:reverse(Pre) ++ Post.

%% Zipper lists can be moved inside in both direction, much like a
%% doubly-linked list in languages that support them. The functions
%% prev/1 and next/1 allow to move in such a manner. They crash whenever
%% you reach the end or the beginning of the zlist, exactly like the
%% functions erlang:hd/1 and erlang:tl/1 do.
-spec prev(zlist()) -&amp;gt; zlist().
prev({[H|T], Post}) -&amp;gt; {T, [H|Post]}.

-spec next(zlist()) -&amp;gt; zlist().
next({Pre, [H|T]}) -&amp;gt; {[H|Pre], T}.

%% current/1 allows to read the value of the list. fails on empty 
%% zlists, exactly the way erlang:hd/1 does. Also fails on lists where
%% the end has been reached.
-spec current(zlist()) -&amp;gt; term().
current({_, [Current|_]}) -&amp;gt; Current.

%% Replace changes the value of the current zlist item.
-spec replace(term(), zlist()) -&amp;gt; zlist().
replace(Val, {Pre, [_|Post]}) -&amp;gt; {Pre, [Val|Post]}.

-spec insert(term(), zlist()) -&amp;gt; zlist().
insert(Val, {Pre, Post}) -&amp;gt; {Pre, [Val|Post]}.

-spec delete(zlist()) -&amp;gt; zlist().
delete({Pre, [_|Post]}) -&amp;gt; {Pre, Post}.

%% Map and reverse maps as an example of potentially
%% useful functions
map(_, L = {_, []}) -&amp;gt; L;
map(F, {P, [H|T]}) -&amp;gt; map(F, {[F(H)|P], T}).

rmap(_, L = {[], _}) -&amp;gt; L;
rmap(F, {[H|T], N}) -&amp;gt; rmap(F, {T, [F(H)|N]}).
&lt;/pre&gt;&lt;p&gt;Not every useful function is implemented here. As an example, it could be nice to have an &lt;code&gt;extract(zlist()) -&amp;gt; {term(), zlist()}&lt;/code&gt; function that removes the current value from the list while returning it, but I consider such functions to be shortcuts around the functions already presented here.&lt;/p&gt;&lt;p&gt;The zlists module could be used to implement the history feature mentioned in the first section of this post. You'd only need to use the prev/1, next/1, current/1 and insert/2 functions to do it.&lt;/p&gt;&lt;p&gt;Here's the &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zlists.erl&quot;&gt;link to the zlists module&lt;/a&gt; if you want it, and the &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zlists_tests.erl&quot;&gt;unit tests module&lt;/a&gt; that goes with it. The unit tests are in a separate file because the error assertions would piss dialyzer off for the type checks.&lt;/p&gt;&lt;h3&gt;Zipper Binary Trees&lt;/h3&gt;&lt;p&gt;Zipper lists are conceptually simple enough to be easy to reinvent and replace with queues. More interesting are trees, because storing the history of how you go through them is a bit more complex.&lt;/p&gt;&lt;p&gt;Let's imagine a 'Book where you are the hero.' A simplified version of such a book could be represented as a decision tree where you can pick 'yes/no' to a question. Picking 'yes' goes to the right node, and picking 'no' goes to the left one. Each of these nodes then have more questions until you die or succeed. Going down such a decision tree is trivial. What's more interesting is when you need to go back one or more levels up in the tree to change your mind because you died and feel like cheating.&lt;/p&gt;&lt;p&gt;You could use a queue or zipper list to store all the choices you've made: &lt;code&gt;{[yes, no, yes, yes, no, ..., yes], [yes]}&lt;/code&gt;. Going back one level would then be about traversing the queue and going down the tree following each decision except the last one in the zipper list. If you want to go up 4 levels, you need to go back 4 elements in the zlist, then down the tree. Again, this is not exactly optimal. By transforming a binary tree into a zipper, it becomes simpler to handle everything.&lt;/p&gt;&lt;p&gt;This is done by storing the past part of the tree (the previous node &lt;em&gt;and&lt;/em&gt; the paths you didn't take) every time you go down a level. When going back up, just graft the child back onto the parent. Here's the initial tree:&lt;/p&gt;&lt;img src=&quot;http://ferd.ca/static/img/zipbintree1.png&quot; alt=&quot;binary tree&quot; height=&quot;170&quot; width=&quot;266&quot; /&gt;&lt;p&gt;And here's what the zipper could look like once choosing 'yes' once:&lt;/p&gt;&lt;img src=&quot;http://ferd.ca/static/img/zipbintree2.png&quot; alt=&quot;going down the right node in a zipper binary tree&quot; height=&quot;263&quot; width=&quot;365&quot; /&gt;&lt;p&gt;And then picking 'no':&lt;/p&gt;&lt;img src=&quot;http://ferd.ca/static/img/zipbintree3.png&quot; alt=&quot;then going to the left node&quot; height=&quot;303&quot; width=&quot;279&quot; /&gt;&lt;p&gt;As described above, when going back up a level, take the part on the 'current' side, and put it as the right child (because we went to the right) of the past tree. That will give you the original tree back.&lt;/p&gt;&lt;p&gt;To represent this in Erlang, we'll need a few constructs. First of all, a node of a tree (which would hold the questions and then the left and right branch) can be defined either as the atom &lt;code&gt;undefined&lt;/code&gt; or as a tuple of the form &lt;code&gt;{fork, Question, Left, Right}&lt;/code&gt;, where &lt;var&gt;Left&lt;/var&gt; and &lt;var&gt;Right&lt;/var&gt; are both nodes themselves.&lt;/p&gt;&lt;p&gt;The 'past' section will be called a &lt;em&gt;thread&lt;/em&gt; and will be a stack of previously seen &lt;em&gt;branches&lt;/em&gt; (or &lt;em&gt;choices&lt;/em&gt; in the code below). A branch is simply a tuple containing the direction that was taken and the tree without the 'current' section. This will give a zipper of the form &lt;code&gt;{Thread = [{Direction, Value, ParentNode}|_], CurrentNode}&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Here it is as implemented in the &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zbintrees.erl&quot;&gt;zbintrees module&lt;/a&gt;:&lt;/p&gt;&lt;pre class=&quot;brush:erl&quot;&gt;
-module(zbintrees).
-export([root/1, get/1, put/2, right/1, left/1, top/1,
         set_left_branch/2, set_right_branch/2]).
-compile({no_auto_import,[get/1, put/2]}).

-type node(A) :: undefined
               | {fork, A, Left::node(A), Right::node(A)}.

-type choice(A) :: {left, A, node(A)}
                 | {right, A, node(A)}.

-type thread(A) :: [choice(A)].

-type zipper(A) :: {thread(A), node(A)}.

%% Creates a basic binary zipper tree. Should be called first when
%% declaring the data structure
-spec root(A) -&amp;gt; zipper(A).
root(A) -&amp;gt; {[], {fork, A, undefined, undefined}}.

%% Fetches the value of the current position
-spec get(zipper(Val)) -&amp;gt; Val.
get({_Thread, {fork, Val, _Left, _Right}}) -&amp;gt; Val.

%% Either replaces or create a new node (if it was 'undefined')
%% at the current position in the zipper binary tree. The
%% value of the node is the one in the second argument.
-spec put(A, zipper(A)) -&amp;gt; zipper(A).
put(Val, {Thread, undefined}) -&amp;gt;
    {Thread, {fork, Val, undefined, undefined}};
put(Val, {Thread, {fork, _OldVal, L, R}}) -&amp;gt;
    {Thread, {fork, Val, L, R}}.

%% Moves down the tree one level, picking the right child.
-spec right(zipper(A)) -&amp;gt; zipper(A).
right({Thread, {fork, Val, L, R}}) -&amp;gt; {[{right, Val, L}|Thread], R}.

%% Moves down the tree one level, picking the left child.
-spec left(zipper(A)) -&amp;gt; zipper(A).
left({Thread, {fork, Val, L, R}}) -&amp;gt; {[{left, Val, R}|Thread], L}.

%% Moves back up one level. When doing so, it reassembles the
%% Current and Past parts of the trees as a complete node.
-spec top(zipper(A)) -&amp;gt; zipper(A).
top({[{left, Val, R}|Thread], L}) -&amp;gt;  {Thread, {fork, Val, L, R}};
top({[{right, Val, L}|Thread], R}) -&amp;gt; {Thread, {fork, Val, L, R}}.

%% Shortcut function to add a left child
set_left_branch(A, Zipper) -&amp;gt;
    top(put(A, left(Zipper))).

%% Shortcut function to add a right child
set_right_branch(A, Zipper) -&amp;gt;
    top(put(A, right(Zipper))).
&lt;/pre&gt;&lt;p&gt;And you can also get the &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zbintrees_tests.erl&quot;&gt;unit tests&lt;/a&gt;. An example usage of the tree could look a bit like what follows:&lt;/p&gt;&lt;pre class=&quot;brush:eshell&quot;&gt;
1&amp;gt; Tree = {[], {fork,
1&amp;gt;              &quot;Open door?&quot;,
1&amp;gt;              {fork,
1&amp;gt;               &quot;Enter hallway?&quot;,
1&amp;gt;               {fork, &quot;you die alone.&quot;, undefined, undefined},
1&amp;gt;               {fork, &quot;you die in a hallway&quot;, undefined, undefined}},
1&amp;gt;              {fork,
1&amp;gt;               &quot;Eat the bacon?&quot;,
1&amp;gt;               {fork, &quot;You die of hunger&quot;, undefined, undefined},
1&amp;gt;               {fork,
1&amp;gt;                &quot;Eat more bacon?&quot;,
1&amp;gt;                {fork, &quot;You die of hunger&quot;, undefined, undefined},
1&amp;gt;                {fork, &quot;Hooray for bacon!&quot;, undefined, undefined}}}}}.
{[],
 {fork,&quot;Open door?&quot;,
       {fork,&quot;Enter hallway?&quot;,
             {fork,&quot;you die alone.&quot;,undefined,undefined},
             {fork,&quot;you die in a hallway&quot;,undefined,undefined}},
       {fork,&quot;Eat the bacon?&quot;,
             {fork,&quot;You die of hunger&quot;,undefined,undefined},
             {fork,&quot;Eat more bacon?&quot;,
                   {fork,&quot;You die of hunger&quot;,undefined,undefined},
                   {fork,&quot;Hooray for bacon!&quot;,undefined,undefined}}}}}
2&amp;gt; zbintrees:get(Tree).
&quot;Open door?&quot;
3&amp;gt; zbintrees:get(zbintrees:right(Tree)).
&quot;Eat the bacon?&quot;
4&amp;gt; zbintrees:get(zbintrees:left(zbintrees:right(Tree))).
&quot;You die of hunger&quot;
5&amp;gt; zbintrees:get(zbintrees:top(zbintrees:left(zbintrees:right(Tree)))).
&quot;Eat the bacon?&quot;
6&amp;gt; zbintrees:get(zbintrees:right(zbintrees:top(zbintrees:left(zbintrees:right(Tree))))).
&quot;Eat more bacon?&quot;
7&amp;gt; zbintrees:get(zbintrees:right(zbintrees:right(zbintrees:top(zbintrees:left(zbintrees:right(Tree)))))).
&quot;Hooray for bacon!&quot;
8&amp;gt; &quot;I won!&quot;.
&quot;I won!&quot;
&lt;/pre&gt;&lt;p&gt;I cheated the tree creation by doing it with the internal representation, but yeah. As the 'game' goes, you can see that I actually die (&lt;samp&gt;&quot;You die of hunger&quot;&lt;/samp&gt;), then use the &lt;code&gt;zbintrees:top/1&lt;/code&gt; function to go back a level and keep going. A real world use would likely go through these steps in an imperative manner rather than just chaining the functions the way I do.&lt;/p&gt;&lt;h3&gt;Zipper Forests&lt;/h3&gt;&lt;p&gt;The zipper binary trees were fine for the simplified 'yes/no' decision tree, but the use cases are kind of limited. How many things can you think of where a binary tree going both up and down is really necessary? It's a bit more useful to have trees with as many nodes as you want. To build one, I'll use a structure similar to that is used in &lt;a href=&quot;http://en.wikipedia.org/wiki/N-ary_tree&quot;&gt;N-ary trees&lt;/a&gt;. N-ary trees usually have a maximum number of elements on each level, but for the purpose of simplicity I won't limit the number of elements.&lt;/p&gt;&lt;p&gt;A simple way to do things with N-ary trees is to hold each nodes of a level in a list. As such, one of our n-trees could look a bit like:&lt;/p&gt;&lt;pre&gt;
      [a,  b,   c,   d]
     /     |    |     \
[l,m,n]  [o] [p,q,r] [s,t,u,v,x]
                        |
                [1,2,3,4,5,6,7,8,9]
&lt;/pre&gt;&lt;p&gt;How to make this into a zipper? It's not just storing left or right and then rejoining the nodes like with zipper binary trees. Fortunately, we had zipper lists. By using them, we can simulate going from left to right and have an 'unlimited' number of nodes on each level. By nesting lists, we get the n-ary tree behavior we need.&lt;/p&gt;&lt;p&gt;The structure of the tree will go as follows. Each node has the form &lt;code&gt;{Value, Children}&lt;/code&gt;. These nodes go into a zipper list to form a &lt;em&gt;znode&lt;/em&gt; (I'm just coining terms/types for the hell of it). Each level of the tree is a znode. The tree as a whole has the form &lt;code&gt;{Thread, Znode}&lt;/code&gt;. The following tree would be a valid zipper n-tree:&lt;/p&gt;&lt;pre class=&quot;brush:erl&quot;&gt;
{[], % thread
 {[], [{a, {[], [{d, {[], []}},
                 {e, {[], []}}]}},
       {b, {[], [{f, {[], []}},
                 {g, {[], [{k, {[], []}}]}}]}},
       {c, {[], [{h, {[], []}},
                 {i, {[], []}},
                 {j, {[], []}}]}}]}}.
&lt;/pre&gt;&lt;p&gt;Or in a more visual manner:&lt;/p&gt;&lt;pre&gt;
    [a,  b,  c]
   /     |     \
[d,e]  [f,g]  [h,i,j]
           \
           [k]
&lt;/pre&gt;&lt;p&gt;I should already say that it's a bit of a misnomer to call them 'zipper n-trees' given I don't enforce the limit, but I'll stick to it for this post. I'll go as far as naming the module &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zntrees.erl&quot;&gt;zntrees&lt;/a&gt;. The module supports basic operations: inserting, replacing, deleting values, creating an empty tree, moving to the left and right, and going to the current element's children or parent:&lt;/p&gt;&lt;pre class=&quot;brush:erl&quot;&gt;
-module(zntrees).
-export([root/1, value/1,
         replace/2, insert/2, delete/1,
         left/1, right/1, children/1, parent/1, rparent/1]).

-type zlist(A) :: {Left::list(A), Right::list(A)}.
-type znode()  :: zlist({term(), zlist(_)}). % znode is a zlist of nodes
-type thread() :: [znode()].
-type zntree() :: {thread(), znode()}.

%% creates a tree with an empty thread and Val as the root.
-spec root(term()) -&amp;gt; zntree().
root(Val) -&amp;gt; {[], {[], [{Val, {[], []}}]}}.

%% Extracts the node's value from the current tree position.
-spec value(zntree()) -&amp;gt; term().
value({_Thread, {_Left, [{Val, _Children} | _Right]}}) -&amp;gt; Val.

%% Replaces the value from at the current tree position, without touching
%% the children nodes.
-spec replace(term(), zntree()) -&amp;gt; zntree().
replace(Val, {T, {L, [{_Val, Children}|R]}}) -&amp;gt;
    {T, {L, [{Val,Children}|R]}}.

%% Add a new node at the current position with the value Val.
-spec insert(term(), zntree()) -&amp;gt; zntree().
insert(Val, {Thread, {L, R}}) -&amp;gt;
    {Thread, {L, [{Val, {[], []}} | R]}}.

%% Deletes the node at the current position and its children.
%% The next one on the right becomes the current position.
-spec delete(zntree()) -&amp;gt; zntree().
delete({Thread, {L, [_|R]}}) -&amp;gt;
    {Thread, {L, R}}.

%% Moves to the left of the current level.
-spec left(zntree()) -&amp;gt; zntree().
left({Thread, {[H|T], R}}) -&amp;gt;
    {Thread, {T, [H|R]}}.

%% Moves to the right of the current level
-spec right(zntree()) -&amp;gt; zntree().
right({Thread, {L, [H|T]}}) -&amp;gt;
    {Thread, {[H|L], T}}.

%% Goes down one level to the children of the current node.
%% Note that in order for this to work, the {Val, Children} tuple
%% needs to be broken in two: the value goes in the Thread's zlist
%% while the Children become the current level.
-spec children(zntree()) -&amp;gt; zntree().
children({Thread, {L, [{Val, Children}|R]}}) -&amp;gt;
    {[{L,[Val|R]}|Thread], Children}.

%% Moves up to the direct parent level. Doesn't rewind the current
%% level's zlist. This means that if you have a tree, go to the
%% children, browse to the right 2-3 times, then go back up and
%% down to the children again, you'll be at the same position you were
%% before.
%% If you prefer the children to be 'rewinded', use rparent/1.
-spec parent(zntree()) -&amp;gt; zntree().
parent({[{L, [Val|R]}|Thread], Children}) -&amp;gt;
    {Thread, {L, [{Val, Children}|R]}}.

%% Moves up to the direct parent level, much like parent/1. However,
%% it rewinds the current level's zlist before doing so. This allows
%% the programmer to access children as if it were the first time,
%% all the time.
-spec rparent(zntree()) -&amp;gt; zntree().
rparent({[{ParentL, [Val|ParentR]}|Thread], {L, R}}) -&amp;gt;
    {Thread, {ParentL, [{Val, {[], lists:reverse(L)++R}}|ParentR]}}.
&lt;/pre&gt;&lt;p&gt;And now you can declare trees with any number of nodes. See the &lt;a href=&quot;http://ferd.ca/static/erl/zippers/zntrees_tests.erl&quot;&gt;unit tests&lt;/a&gt; if you want.&lt;/p&gt;&lt;p&gt;The use cases for such trees are more abundant: &lt;a href=&quot;http://vimdoc.sourceforge.net/htmldoc/usr_32.html&quot;&gt;undo trees&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Xml#Document_Object_Model_.28DOM.29&quot;&gt;XML navigating with DOM&lt;/a&gt;, representing more complex 'choose your own adventure' books (or decision trees), directories in a filesystem, etc.&lt;/p&gt;&lt;p&gt;Here we'll try a DOM tree example with the following fake document:&lt;/p&gt;&lt;pre&gt;
&amp;lt;html&amp;gt;
    &amp;lt;header&amp;gt;
        &amp;lt;title&amp;gt;Hello, World!&amp;lt;/title&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Hello, World!&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;How are you, planet?&amp;lt;/p&amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li&amp;gt;Bat&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Man&amp;lt;/li&amp;gt;
            &amp;lt;li&amp;gt;Na Na Na Na&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;p&gt;You could build the tree as a zntree by using the functions root/1, children/1, insert/2, right/1 and parent/1, but this would be a little too verbose, so I'll declare it in it's final form:&lt;/p&gt;&lt;pre class=&quot;brush:eshell&quot;&gt;
1&amp;gt; Document = 
1&amp;gt; {[],
1&amp;gt;  {[],
1&amp;gt;   [{html,
1&amp;gt;     {[],
1&amp;gt;      [{header,
1&amp;gt;        {[],
1&amp;gt;         [{title, {[],[{&quot;Hello, World!&quot;,{[],[]}}]}}]}},
1&amp;gt;       {body,
1&amp;gt;        {[],
1&amp;gt;         [{h1,{[], [{&quot;Hello, World!&quot;, {[],[]}}]}},
1&amp;gt;          {p, {[], [{&quot;How are you, planet?&quot;, {[],[]}}]}},
1&amp;gt;          {ul,
1&amp;gt;           {[],
1&amp;gt;            [{li, {[],[{&quot;Bat&quot;, {[],[]}}]}},
1&amp;gt;             {li, {[],[{&quot;Man&quot;, {[],[]}}]}},
1&amp;gt;             {li, {[],[{&quot;Na Na Na Na&quot;, {[],[]}}]}}]}}]}}]}}]}}.
{[],
 {[],
  [{html,{[],
          [{header,{[],[{title,{[],[{&quot;Hello, World!&quot;,{[],[]}}]}}]}},
           {body,{[],
                  [{h1,{[],[{&quot;Hello, World!&quot;,{[],[]}}]}},
                   {p,{[],[{&quot;How are you, planet?&quot;,{[],[]}}]}},
                   {ul,{[],
                        [{li,{[],[{[...],...}]}},
                         {li,{[],[{...}]}},
                         {li,{[],[...]}}]}}]}}]}}]}}
&lt;/pre&gt;&lt;p&gt;Ugly, but yeah. We can now play and navigate around the tree. The functions left/1 and right/1 can be used to access the current element's siblings while parent/1 and children/1 can be used to go up and down the hierarchy:&lt;/p&gt;&lt;pre class=&quot;brush:eshell&quot;&gt;
2&amp;gt; zntrees:value(zntrees:children(Document)).
header
3&amp;gt; zntrees:value(zntrees:right(zntrees:children(Document))).
body
4&amp;gt; Body = zntrees:right(zntrees:children(Document)).
&amp;lt;huge structure&amp;gt;
5&amp;gt; zntrees:value(zntrees:right(zntrees:right(zntrees:children(Body)))).
ul
6&amp;gt; List = zntrees:right(zntrees:right(zntrees:children(Body))).
&amp;lt;huge structure&amp;gt;
7&amp;gt; zntrees:value(zntrees:children(zntrees:left(zntrees:rparent(zntrees:right(zntrees:children(List)))))).
&quot;How are you, planet?&quot;
&lt;/pre&gt;&lt;p&gt;That last one is a bit exaggerated, I agree. Anyway, this zipper makes it possible to change a node's value in constant time. In the following example, I'll go to the first element of the list and replace &lt;code&gt;&quot;Bat&quot;&lt;/code&gt; by &lt;code&gt;&quot;Platypus&quot;&lt;/code&gt;. The &lt;code&gt;log n&lt;/code&gt; modifications needed to rewrite the data structure in normal trees are now amortized over the calls to parent/1, if you ever actually need to call it (if you don't, you never really have to pay that rewrite cost):&lt;/p&gt;&lt;pre class=&quot;brush:eshell&quot;&gt;
8&amp;gt; NewDocument = zntrees:replace(&quot;Platypus&quot;, zntrees:children(zntrees:children(List))).
&amp;lt;huge structure&amp;gt;
9&amp;gt; zntrees:parent(zntrees:parent(zntrees:parent(zntrees:parent(NewDocument)))).
{[],
 {[],
  [{html,{[{header,{[],
                    [{title,{[],[{&quot;Hello, World!&quot;,{[],[]}}]}}]}}],
          [{body,{[{p,{[],[{&quot;How are you, planet?&quot;,{[],[]}}]}},
                   {h1,{[],[{&quot;Hello, World!&quot;,{[],[]}}]}}],
                  [{ul,{[],
                        [{li,{[],[{&quot;Platypus&quot;,{[],[]}}]}},
                         {li,{[],[{&quot;Man&quot;,{[],...}}]}},
                         {li,{[],[{&quot;Na Na Na Na&quot;,{...}}]}}]}}]}}]}}]}}
&lt;/pre&gt;&lt;p&gt;DOM navigation is only one of the possible uses of zipper trees. As I mentioned earlier, undo trees or decision trees are also possible. In fact, this kind of zipper can be used to represent any undirected acyclic graph or &lt;em&gt;forest&lt;/em&gt;: this means (I believe) that many graph-based problems where no cycle exist can be represented and navigated with the above zipper, including concepts such as &lt;a href=&quot;http://en.wikipedia.org/wiki/Minimum_spanning_tree&quot;&gt;minimum spanning trees&lt;/a&gt;. This could be useful, if anyone ever needed to do that kind of stuff in Erlang I guess. Which brings me to my next point...&lt;/p&gt;&lt;h3&gt;Alternatives to Zippers&lt;/h3&gt;&lt;p&gt;Zippers can be pretty useful when you need a specific way to quickly update a datastructure as shown above. Depending on the use case, using &lt;a href=&quot;http://en.wikipedia.org/wiki/Adjacency_list&quot;&gt;adjacency lists&lt;/a&gt; (or something close to that) with dicts, gb_trees or ETS tables can prove to be practical: those would in fact allow shared access and modifications to the data structures, something that sounds conceptually harder to do with zippers.&lt;/p&gt;&lt;p&gt;Anyway, I hope this was an educative/entertaining/distracting or anything not negative read.&lt;/p&gt;&lt;/div&gt;</description>
	<pubDate>Fri, 13 Aug 2010 00:30:00 +0000</pubDate>
</item>
<item>
	<title>heeen: Day 5 - Santana Row</title>
	<guid>tag:heeen.de,2010:/blog//1.19</guid>
	<link>http://heeen.de/blog/2010/08/day-5---santana-row.html</link>
	<description>Wir besuchen einen weiteren Mall, genannt Santana Row Plaza. Ähnlich wie der erste ist er offen gebaut. Parken ist umsonst, man will die Leute ja entspannt Geld ausgeben lassen. Das ist mir auf jeden Fall lieber als dauernd auf die Uhr schauen zu müssen. Der Mall ist größer und in mehrere Blöcke aufgeteilt. Es gibt vom Optiker über Tierboutique bis zum Laden ausschließlich für Behältnisse (&quot;The Container Store&quot;) alles.&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4401.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4401.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Zwischen den Geschäften gibt es verschiedenste Lokale. Es ist üblich nach dem Einkaufen in eines der Restaurants oder Bars einzukehren. Ich kaufe ein paar Bücher und Mitbringsel und danach kehren wir in einem Irish Pub ein. Dort gibt es gute Küche aber ich begnüge mich mit einem Iced Tea. Der wird in Restaurants übrigens ungesüßt serviert.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4402.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4402.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 12 Aug 2010 06:24:56 +0000</pubDate>
</item>
<item>
	<title>heeen: Day 4 - Tierhandel</title>
	<guid>tag:heeen.de,2010:/blog//1.18</guid>
	<link>http://heeen.de/blog/2010/08/day-3---tierhandel.html</link>
	<description>Heute gehen wir in ein Italienisches Restaurant zu Mittag, wo ich mir eine Pizza genehmige. Auf dem Heimweg besuchen wir einige Handelsketten: Best Buy - dr Amerikanische Mediamarkt, sowie REI, einen Laden für alles was man unter freiem Himmel und beim Camping brauchen kann. Was das Camping angeht macht den Amerikanern niemand was vor, es gibt wirklich alles von Wasserdichten Schalen für Elektronik bis Kaffekonzentrat in Tüten: einfach in eine Tasse Wasser giessen, schon hat man überall einen Wachmacher.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Neben REI fanden wir noch einen Tierwarenladen. Hier konnte man neben allem was man auch bei uns im Freßnapf findet auch Tiere erwerben bzw. adoptieren. Unter anderem wurden Fische in kleinen Plastikbechern angeboten.&lt;/div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/assets_c/2010/08/Bild070-41.html&quot;&gt;&lt;img src=&quot;http://heeen.de/blog/assets_c/2010/08/Bild070-thumb-600x450-41.jpg&quot; width=&quot;600&quot; height=&quot;450&quot; alt=&quot;Bild070.jpg&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;Wie diese Fische gefüttert und mit Sauerstoff versorgt werden konnte ich nicht ausmachen - einige bewegten sich ejdenfalls nicht mehr.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ebenfalls in dem Laden befand sich eine Katzenadoptionsstation. Katzen die Augenscheinlich von den Tierfängern aufgesammelt wurden und kastriert und untersucht wurden, werden da hinter Schaufenstern zur Adoption feilgeboten. Was zunächst sehr deprimierend wirkt, ist wie ich finde jedoch eine Gute Sache™: Scheut man bei uns den Besuch im Tierheim doch eher oder geht dort nur selten absichtlich hin, werden hier die Tiere wesentlich näher an den Lebensmittelpunkt der Menschen gebracht. Ich konnte einen Kunden beobachten der augenscheinlich ein Bild einer Katze machte und an jemanden weiterschickte.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/assets_c/2010/08/Bild069-45.html&quot;&gt;&lt;img src=&quot;http://heeen.de/blog/assets_c/2010/08/Bild069-thumb-600x450-45.jpg&quot; width=&quot;600&quot; height=&quot;450&quot; alt=&quot;Bild069.jpg&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 10 Aug 2010 07:31:26 +0000</pubDate>
</item>
<item>
	<title>heeen: Day 2 - Erster Mall-Besuch</title>
	<guid>tag:heeen.de,2010:/blog//1.17</guid>
	<link>http://heeen.de/blog/2010/08/day-2---erster-mall-besuch.html</link>
	<description>Heute gibt es Mittags kostenlose Sandwiches von Subway, mit Senf und Mayo zum selbst dazustreichen. nach der Arbeit treten wir zum ersten Mall den weg zu einem Mall, also einem Einkaufszentrum an. Viele überdachte Einkaufszentren, wie man sie in Deutschland importiert hat, sind ausgestorben und rotten vor sich hin. Neue Einkaufszentren ähneln den Einkaufsstrassen europäischer Innenstädte: statt eines großen Gebäudes gibt es mehrere Blöcke in denen sich verschiedene Ketten und Läden befinden. Die Wege zwischen den Blöcken haben Bänke und Brunnen und sind mit Pflanzen bewachsenen Pergolas überdacht.&lt;div&gt;Im Stanford Mall gehen wir zuvor in Bubbles Diner, einem Amerikanischen Imbiss wie man ihn aus dem Film kennt, essen. Für mich gibt es ein roast beef sandwich und anschliessend cheesecake.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4387.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4387.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4388.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4388.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Noch konnte ich dem Kommerz widerstehen und habe nichts gekauft.&lt;/div&gt;&lt;div&gt;Wieder am Hotel angekommen wartet endlich mein Koffer auf mich und damit auch meine Badehose. Jetzt kann ich endlich den heißen Whirlpool und das Becken genießen.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4391.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4391.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 10 Aug 2010 07:09:19 +0000</pubDate>
</item>
<item>
	<title>Janin: Release: dbus-core 0.8.4</title>
	<guid>tag:ianen.org,2010:entry-3</guid>
	<link>http://hackage.haskell.org/package/dbus-core-0.8.4</link>
	<pubDate>Mon, 09 Aug 2010 00:43:26 +0000</pubDate>
</item>
<item>
	<title>stromdotcom: mentalBlock for iPad</title>
	<guid>http://www.stromcode.com/2010/06/01/mentalblock-for-ipad/</guid>
	<link>http://www.stromcode.com/2010/06/01/mentalblock-for-ipad/</link>
	<description>mentalBlock for iPad is now available in the app store.&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=hOLb5oH7UlU:IIVojz-qGek:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=hOLb5oH7UlU:IIVojz-qGek:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:l6gmwiTKsz0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=l6gmwiTKsz0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:gIN9vFwOqvQ&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=hOLb5oH7UlU:IIVojz-qGek:gIN9vFwOqvQ&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=hOLb5oH7UlU:IIVojz-qGek:TzevzKxY174&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=TzevzKxY174&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:22 +0000</pubDate>
</item>
<item>
	<title>stromdotcom: Windows Phone 7 Anticipation</title>
	<guid>http://www.stromcode.com/2010/04/03/windows-phone-7-anticipation/</guid>
	<link>http://www.stromcode.com/2010/04/03/windows-phone-7-anticipation/</link>
	<description>I am definitely looking forward to developing for Windows Phone 7.

After the absolute humiliation that comes with developing for the iPhone (or, more to the point, passing through Apple's brain dead review process), I almost gave up on mobile development.  That's a shame, because it isn't hard to see that ...&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=q2iU2Lt1zmw:_mVQk-Lqo50:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=q2iU2Lt1zmw:_mVQk-Lqo50:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:l6gmwiTKsz0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=l6gmwiTKsz0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:gIN9vFwOqvQ&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=q2iU2Lt1zmw:_mVQk-Lqo50:gIN9vFwOqvQ&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=q2iU2Lt1zmw:_mVQk-Lqo50:TzevzKxY174&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=TzevzKxY174&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:22 +0000</pubDate>
</item>
<item>
	<title>stromdotcom: Why I’m Developing for iPad</title>
	<guid>http://www.stromcode.com/2010/06/06/why-im-developing-for-ipad/</guid>
	<link>http://www.stromcode.com/2010/06/06/why-im-developing-for-ipad/</link>
	<description>I have been pretty vocal in the past about my issues with the app store, Apple, Apple's development tools, the app market, and so on.  Leading up to the release of the iPad, I goofed on it with everyone else, and scoffed at the idea of developing anything for it. ...&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=-KUbaGknNio:2aYCbWC7wdY:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=-KUbaGknNio:2aYCbWC7wdY:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:l6gmwiTKsz0&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=l6gmwiTKsz0&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:gIN9vFwOqvQ&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?i=-KUbaGknNio:2aYCbWC7wdY:gIN9vFwOqvQ&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/Stromcode?a=-KUbaGknNio:2aYCbWC7wdY:TzevzKxY174&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/Stromcode?d=TzevzKxY174&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:22 +0000</pubDate>
</item>
<item>
	<title>king_kllr: PyOhio Slides</title>
	<guid>http://alexgaynor.net/2010/aug/02/pyohio-slides/</guid>
	<link>http://alexgaynor.net/2010/aug/02/pyohio-slides/</link>
	<description>&lt;p&gt;I've (finally) uploaded the slides from my &lt;a class=&quot;reference external&quot; href=&quot;http://www.pyohio.org/&quot;&gt;PyOhio&lt;/a&gt; talk (I gave a similar talk at &lt;a class=&quot;reference external&quot; href=&quot;http://chipy.org/&quot;&gt;ChiPy&lt;/a&gt;).  You can get them &lt;a class=&quot;reference external&quot; href=&quot;http://www.scribd.com/doc/35240506/Pyohio-Fast-Python&quot;&gt;right here&lt;/a&gt;, I'll be putting all my slides on Scribd from here on out, they were much easier to upload to than SlideShare, plus HTML5 is awesome!&lt;/p&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:09 +0000</pubDate>
</item>
<item>
	<title>king_kllr: Testing Utilities in Django</title>
	<guid>http://alexgaynor.net/2010/jul/06/testing-utilities-django/</guid>
	<link>http://alexgaynor.net/2010/jul/06/testing-utilities-django/</link>
	<description>&lt;p&gt;Lately I've had the opportunity to do some &lt;a class=&quot;reference external&quot; href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;test-driven development&lt;/a&gt; with Django, which a) is awesome, I love testing, and b) means I've been working up a box full of testing utilities, and I figured I'd share them.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;convenient-get-and-post-methods&quot;&gt;
&lt;h1&gt;Convenient &lt;tt class=&quot;docutils literal&quot;&gt;get()&lt;/tt&gt; and &lt;tt class=&quot;docutils literal&quot;&gt;post()&lt;/tt&gt; methods&lt;/h1&gt;
&lt;p&gt;If you've done testing of views with Django you probably have some tests that look like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;test_my_view&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
    &lt;span&gt;response&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;self.client.get(reverse(&lt;/span&gt;&lt;span&gt;&amp;quot;my_url&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;kwargs={&lt;/span&gt;&lt;span&gt;&amp;quot;pk&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;}))&lt;/span&gt;

    &lt;span&gt;response&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;self.client.post(reverse(&lt;/span&gt;&lt;span&gt;&amp;quot;my_url&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;kwargs={&lt;/span&gt;&lt;span&gt;&amp;quot;pk&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;}),&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
        &lt;span&gt;&amp;quot;key&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
    &lt;span&gt;})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This was a tad too verbose for my tastes so I wrote:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;get&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;url_name,&lt;/span&gt; &lt;span&gt;*args,&lt;/span&gt; &lt;span&gt;**kwargs):&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;self.client.get(reverse(url_name,&lt;/span&gt; &lt;span&gt;args=args,&lt;/span&gt; &lt;span&gt;kwargs=kwargs))&lt;/span&gt;

&lt;span&gt;def&lt;/span&gt; &lt;span&gt;post&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;url_name,&lt;/span&gt; &lt;span&gt;*args,&lt;/span&gt; &lt;span&gt;**kwargs):&lt;/span&gt;
    &lt;span&gt;data&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;kwargs.pop(&lt;/span&gt;&lt;span&gt;&amp;quot;data&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;None)&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;self.client.post(reverse(url_name,&lt;/span&gt; &lt;span&gt;args=args,&lt;/span&gt; &lt;span&gt;kwargs=kwargs),&lt;/span&gt; &lt;span&gt;data)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which are used:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;test_my_view&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
    &lt;span&gt;response&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;self.get(&lt;/span&gt;&lt;span&gt;&amp;quot;my_url&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;pk=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;

    &lt;span&gt;response&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;self.post(&lt;/span&gt;&lt;span&gt;&amp;quot;my_url&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;pk=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;data={&lt;/span&gt;
        &lt;span&gt;&amp;quot;key&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
    &lt;span&gt;})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Much nicer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;login-wrapper&quot;&gt;
&lt;h1&gt;&lt;tt class=&quot;docutils literal&quot;&gt;login()&lt;/tt&gt; wrapper&lt;/h1&gt;
&lt;p&gt;The next big issue I had was logging in and out of multiple users was too verbose.  I often want to switch between users, either to check different permissions or to test some inter-user workflow.  That was solved with a simple context manager:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;login(object):&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;testcase,&lt;/span&gt; &lt;span&gt;user,&lt;/span&gt; &lt;span&gt;password):&lt;/span&gt;
        &lt;span&gt;self.testcase&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;testcase&lt;/span&gt;
        &lt;span&gt;success&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;testcase.client.login(username=user,&lt;/span&gt; &lt;span&gt;password=password)&lt;/span&gt;
        &lt;span&gt;self.testcase.assertTrue(&lt;/span&gt;
            &lt;span&gt;success,&lt;/span&gt;
            &lt;span&gt;&amp;quot;login with username=%r, password=%r failed&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;(user,&lt;/span&gt; &lt;span&gt;password)&lt;/span&gt;
        &lt;span&gt;)&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__enter__&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
        &lt;span&gt;pass&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__exit__&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;*args):&lt;/span&gt;
        &lt;span&gt;self.testcase.client.logout()&lt;/span&gt;

&lt;span&gt;def&lt;/span&gt; &lt;span&gt;login&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;user,&lt;/span&gt; &lt;span&gt;password):&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;login(self,&lt;/span&gt; &lt;span&gt;user,&lt;/span&gt; &lt;span&gt;password)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is used:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;test_my_view&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
    &lt;span&gt;with&lt;/span&gt; &lt;span&gt;self.login(&lt;/span&gt;&lt;span&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;
        &lt;span&gt;response&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;self.get(&lt;/span&gt;&lt;span&gt;&amp;quot;my_url&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;pk=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Again, a lot better.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;django-fixture-generator&quot;&gt;
&lt;h1&gt;django-fixture-generator&lt;/h1&gt;
&lt;p&gt;Not quite a testing utility, but my app &lt;a class=&quot;reference external&quot; href=&quot;http://github.com/alex/django-fixture-generator&quot;&gt;django-fixture-generator&lt;/a&gt; has made testing a lot easier for me.  Fixtures are useful in getting data to work wit, but maintaining them is often a pain, you've got random scripts to generate them, or you just checkin some JSON to your repository with no way to regenerate it sanely (say if you add a new field to your model).  django-fixture-generator gives you a clean way to manage the code for generating fixtures.&lt;/p&gt;
&lt;p&gt;In general I've found context managers are a pretty awesome tool for writing clean, readable, succinct tests.  I'm sure I'll have more utilities as I write more tests, hopefully someone finds these useful.&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:09 +0000</pubDate>
</item>
<item>
	<title>king_kllr: MultiMethods for Python</title>
	<guid>http://alexgaynor.net/2010/jun/26/multimethods-python/</guid>
	<link>http://alexgaynor.net/2010/jun/26/multimethods-python/</link>
	<description>&lt;p&gt;Every once and a while the topic of multimethods (also known as generic dispatch) comes up in the Python world (see &lt;a class=&quot;reference external&quot; href=&quot;http://www.python.org/dev/peps/pep-3124/&quot;&gt;here&lt;/a&gt;, &lt;a class=&quot;reference external&quot; href=&quot;http://mike.axiak.net/blog/2010/06/25/python-generic-dispatch/&quot;&gt;and here&lt;/a&gt;, &lt;a class=&quot;reference external&quot; href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=101605&quot;&gt;here too&lt;/a&gt;, &lt;a class=&quot;reference external&quot; href=&quot;http://twitter.com/gutworth/status/9750313767&quot;&gt;and finally here&lt;/a&gt;, and probably others).  For those of you who aren't familiar with the concept, the idea is that you declare a bunch of functions with the same name, but that take different arguments and the language routes your calls to that function to the correct implementation, based on what types you're calling it with.  For example here's a C++ example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;

&lt;span&gt;void&lt;/span&gt; &lt;span&gt;special(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;k)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;std::cout&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;&amp;quot;I AM THE ALLMIGHTY INTEGER &amp;quot;&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;k&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;std::endl;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;

&lt;span&gt;void&lt;/span&gt; &lt;span&gt;special(std::string&lt;/span&gt; &lt;span&gt;k)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;std::cout&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;&amp;quot;I AM THE ALLMIGHTY STRING &amp;quot;&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;k&lt;/span&gt; &lt;span&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span&gt;std::endl;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;

&lt;span&gt;int&lt;/span&gt; &lt;span&gt;main()&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;special(&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;
    &lt;span&gt;special(&lt;/span&gt;&lt;span&gt;&amp;quot;magic&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can probably guess this will print out:&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
I AM THE ALLMIGHTY INTEGER 3
I AM THE ALLMIGHTY STRING magic
&lt;/pre&gt;
&lt;p&gt;You, the insightful reader, are no doubt fuming in your seats now, &amp;quot;Alex, you idiot, Python functions don't have type signatures, how can we route our calls based on something that does not exist!&amp;quot;, and right you are.  However, don't tell me you've never written a function that looks like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;my_magic_function&lt;/span&gt;&lt;span&gt;(o):&lt;/span&gt;
    &lt;span&gt;if&lt;/span&gt; &lt;span&gt;isinstance(o,&lt;/span&gt; &lt;span&gt;basestring):&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;my_magic_function(int(o))&lt;/span&gt;
    &lt;span&gt;elif&lt;/span&gt; &lt;span&gt;isinstance(o,&lt;/span&gt; &lt;span&gt;(int,&lt;/span&gt; &lt;span&gt;long)):&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;cache[o]&lt;/span&gt;
    &lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;o&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or something like that, the point is you have one function that has a couple of different behaviors based on the type of it's parameter.  Perhaps it'd be nice to separate each of those behaviors into their own function (or not, I don't really care what you do).&lt;/p&gt;
&lt;p&gt;I was saying that a bunch of people have already implemented these, why am I?  Mostly for fun (that's still a valid reason, right?), but also because a bunch of the implementations make me sad.  Some of them use crazy hacks (reading up through stack frames), a few of them have global registrys, and all of them rely on the name of the function to identify a single &amp;quot;function&amp;quot; to be overloaded.  However, they also all have one good thing in common: decorators, yay!&lt;/p&gt;
&lt;p&gt;My implementation is pretty simple, so I'll present it, and it's test suite without explanation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;MultiMethod(object):&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
        &lt;span&gt;self._implementations&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;{}&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;_get_predicate&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;o):&lt;/span&gt;
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;isinstance(o,&lt;/span&gt; &lt;span&gt;type):&lt;/span&gt;
            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;lambda&lt;/span&gt; &lt;span&gt;x:&lt;/span&gt; &lt;span&gt;isinstance(x,&lt;/span&gt; &lt;span&gt;o)&lt;/span&gt;
        &lt;span&gt;assert&lt;/span&gt; &lt;span&gt;callable(o)&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;o&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;register&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;*args,&lt;/span&gt; &lt;span&gt;**kwargs):&lt;/span&gt;
        &lt;span&gt;def&lt;/span&gt; &lt;span&gt;inner&lt;/span&gt;&lt;span&gt;(f):&lt;/span&gt;
            &lt;span&gt;key&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;
                &lt;span&gt;args,&lt;/span&gt;
                &lt;span&gt;tuple(kwargs.items()),&lt;/span&gt;
            &lt;span&gt;)&lt;/span&gt;
            &lt;span&gt;if&lt;/span&gt; &lt;span&gt;key&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;self._implementations:&lt;/span&gt;
                &lt;span&gt;raise&lt;/span&gt; &lt;span&gt;TypeError(&lt;/span&gt;&lt;span&gt;&amp;quot;Duplicate registration for %r&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;key)&lt;/span&gt;
            &lt;span&gt;self._implementations[key]&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;f&lt;/span&gt;
            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;inner&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__call__&lt;/span&gt;&lt;span&gt;(self,&lt;/span&gt; &lt;span&gt;*args,&lt;/span&gt; &lt;span&gt;**kwargs):&lt;/span&gt;
        &lt;span&gt;for&lt;/span&gt; &lt;span&gt;spec,&lt;/span&gt; &lt;span&gt;func&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;self._implementations.iteritems():&lt;/span&gt;
            &lt;span&gt;arg_spec,&lt;/span&gt; &lt;span&gt;kwarg_spec&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;spec&lt;/span&gt;
            &lt;span&gt;kwarg_spec&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;dict(kwarg_spec)&lt;/span&gt;
            &lt;span&gt;if&lt;/span&gt; &lt;span&gt;len(args)&lt;/span&gt; &lt;span&gt;!=&lt;/span&gt; &lt;span&gt;len(arg_spec)&lt;/span&gt; &lt;span&gt;or&lt;/span&gt; &lt;span&gt;set(kwargs)&lt;/span&gt; &lt;span&gt;!=&lt;/span&gt; &lt;span&gt;set(kwarg_spec):&lt;/span&gt;
                &lt;span&gt;continue&lt;/span&gt;
            &lt;span&gt;if&lt;/span&gt; &lt;span&gt;(all(self._get_predicate(spec)(arg)&lt;/span&gt; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;spec,&lt;/span&gt; &lt;span&gt;arg&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;zip(arg_spec,&lt;/span&gt; &lt;span&gt;args))&lt;/span&gt; &lt;span&gt;and&lt;/span&gt;
                &lt;span&gt;all(self._get_predicate(spec)(kwargs[k])&lt;/span&gt; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;k,&lt;/span&gt; &lt;span&gt;spec&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;kwarg_spec.iteritems())):&lt;/span&gt;
                &lt;span&gt;return&lt;/span&gt; &lt;span&gt;func(*args,&lt;/span&gt; &lt;span&gt;**kwargs)&lt;/span&gt;
        &lt;span&gt;raise&lt;/span&gt; &lt;span&gt;TypeError(&lt;/span&gt;&lt;span&gt;&amp;quot;No implementation with a spec matching: %r, %r&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;
            &lt;span&gt;args,&lt;/span&gt; &lt;span&gt;kwargs))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the tests:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;import&lt;/span&gt; &lt;span&gt;unittest2&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; &lt;span&gt;unittest&lt;/span&gt;

&lt;span&gt;from&lt;/span&gt; &lt;span&gt;multimethod&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; &lt;span&gt;MultiMethod&lt;/span&gt;


&lt;span&gt;class&lt;/span&gt; &lt;span&gt;MultiMethodTestCase(unittest.TestCase):&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;test_basic&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
        &lt;span&gt;items&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;MultiMethod()&lt;/span&gt;

        &lt;span&gt;@items.register(list)&lt;/span&gt;
        &lt;span&gt;def&lt;/span&gt; &lt;span&gt;items&lt;/span&gt;&lt;span&gt;(l):&lt;/span&gt;
            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;l&lt;/span&gt;

        &lt;span&gt;@items.register(dict)&lt;/span&gt;
        &lt;span&gt;def&lt;/span&gt; &lt;span&gt;items&lt;/span&gt;&lt;span&gt;(d):&lt;/span&gt;
            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;d.items()&lt;/span&gt;

        &lt;span&gt;self.assertEqual(items([&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;3&lt;/span&gt;&lt;span&gt;]),&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;3&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;
        &lt;span&gt;# TODO: dict ordering dependent, 1 item dict?&lt;/span&gt;
        &lt;span&gt;self.assertEqual(items({&lt;/span&gt;&lt;span&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;}),&lt;/span&gt; &lt;span&gt;[(&lt;/span&gt;&lt;span&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;)])&lt;/span&gt;

        &lt;span&gt;with&lt;/span&gt; &lt;span&gt;self.assertRaises(TypeError):&lt;/span&gt;
            &lt;span&gt;items(xrange(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;

    &lt;span&gt;def&lt;/span&gt; &lt;span&gt;test_duplicate&lt;/span&gt;&lt;span&gt;(self):&lt;/span&gt;
        &lt;span&gt;m&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;MultiMethod()&lt;/span&gt;

        &lt;span&gt;@m.register(list)&lt;/span&gt;
        &lt;span&gt;def&lt;/span&gt; &lt;span&gt;m&lt;/span&gt;&lt;span&gt;(o):&lt;/span&gt;
            &lt;span&gt;return&lt;/span&gt; &lt;span&gt;o&lt;/span&gt;

        &lt;span&gt;with&lt;/span&gt; &lt;span&gt;self.assertRaises(TypeError):&lt;/span&gt;
            &lt;span&gt;@m.register(list)&lt;/span&gt;
            &lt;span&gt;def&lt;/span&gt; &lt;span&gt;m&lt;/span&gt;&lt;span&gt;(o):&lt;/span&gt;
                &lt;span&gt;return&lt;/span&gt; &lt;span&gt;o&lt;/span&gt;


&lt;span&gt;if&lt;/span&gt; &lt;span&gt;__name__&lt;/span&gt; &lt;span&gt;==&lt;/span&gt; &lt;span&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
    &lt;span&gt;unittest.main()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Bon appétit.&lt;/p&gt;</description>
	<pubDate>Sun, 08 Aug 2010 08:30:09 +0000</pubDate>
</item>
<item>
	<title>heeen: Day 1 - Weird Stuff</title>
	<guid>tag:heeen.de,2010:/blog//1.16</guid>
	<link>http://heeen.de/blog/2010/08/day-1---weird-stuff.html</link>
	<description>Montag - der erste Tag. Unsere Arbeitsplätze sind offene Tische im Erdgeschoss des Gebäude. Wir sitzen mit den Finnen an einer Reihe Schreibtische an der jeder sich einen Plaz suchen und seinen Laptop anstöpseln kann. Es gibt eine Cafeteria im Gebäude, die zwar nicht im regulären Betrieb ist, wo es jedoch Mittags kostenlose Snacks gibt. Heute gibt es Bagels mit verschiedenen Brotaufstrichen zum selbstbestreichen.&lt;div&gt;In der Mittagspause fahren wir mit unseren Finnischen Kollegen zu Weird Stuff - Merkwürdiges Zeug, einem Laden/Lagerhalle voller gebrauchter Computer und Elektronikteile. Ein finnischer Kollege hatte dort vorher schon einen alten Apple gekauft um ihn nach Finnland zu importieren - inklusive Gehäuse und Monitor.&lt;/div&gt;&lt;div&gt;Ich finde jedoch nichts was ich unbedingt haben müsste.&lt;/div&gt;&lt;div&gt;Im Umkreis des Ladens findet man viele bekannte Internet-Namen: wir sind an Gebäuden von Yahoo, Symantec und Verisign vorbeigefahren.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/assets_c/2010/08/Bild064-29.html&quot;&gt;&lt;img src=&quot;http://heeen.de/blog/assets_c/2010/08/Bild064-thumb-500x375-29.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;Bild064.jpg&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/assets_c/2010/08/Bild066-32.html&quot;&gt;&lt;img src=&quot;http://heeen.de/blog/assets_c/2010/08/Bild066-thumb-500x666-32.jpg&quot; width=&quot;500&quot; height=&quot;666&quot; alt=&quot;Bild066.jpg&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;Anschliessend essen wir bei &lt;a href=&quot;http://specialtys.com&quot;&gt;Specialtys&lt;/a&gt;&amp;nbsp;einer Bäckerei/Sandwich/Frühstücks/Mittagskette. Dort gibt es Salate und Sandwichs aller Art, sowie Cookies und andere Gebäcke. Man bestellt das Essen an einem Computer im Eingangsbereich und erhält ähnlich wie bei Vapiano einen Piepser der einem sagt wann die Bestellung fertig ist. Das Essen ist hochwertig und selbst hergestellt. Ich hole mir ein warmes BBQ Sandwich und einen kleinen Salat, eigentlich hätte mir aber das Sandwich gereicht.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;a href=&quot;http://heeen.de/blog/assets_c/2010/08/Bild067-35.html&quot;&gt;&lt;img src=&quot;http://heeen.de/blog/assets_c/2010/08/Bild067-thumb-500x375-35.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;Bild067.jpg&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;In Amerika trifft man in jeder besseren Gastronomiekette oder Restaurant auf Organic, also Bio-Produkte, es wird häufig auf Hormonfreies Fleisch und Gemüse von Örtlichen Farmern hingewiesen. Auch das Brot wird in jedem Laden der etwas auf sich hält im Haus gebacken. Auch auf Umweltfreundliche Verpackungen wird sich bemüht, im Bild sind die Teller und Servietten aus Recyclingmaterial. Überall kann man mit Kreditkarte bezahlen.&lt;/div&gt;</description>
	<pubDate>Sat, 07 Aug 2010 08:36:37 +0000</pubDate>
</item>
<item>
	<title>heeen: Day 0 - Anreise</title>
	<guid>tag:heeen.de,2010:/blog//1.15</guid>
	<link>http://heeen.de/blog/2010/08/day-0---anreise.html</link>
	<description>Ich versuche hier mal das nichtgeschäftliche meiner Mountain View Reise zu sammeln.&lt;div&gt;Es ist schon spät und ich bin müde deshalb nur Tag 0 heute.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4373.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4373.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Wir sind sehr früh aufgestanden - etwa halb fünf wenn ich mich richtig erinnere. Ich habe nur eine oder zwei Stunden geschlafen wenns hochkommt, war aber relativ fit.&lt;/div&gt;&lt;div&gt;Eingecheckt habe ich online, was mir ausser der Sitzplatzwahl für Amsterdam-San Francisco aber nichts gebracht hat - Gepäck musste ich trotzdem ja noch aufgeben. An der Security wurde die Kamera mit einem Schnelltest auf irgendwelche Substanzen untersucht.&lt;/div&gt;&lt;div&gt;Der Flug nach Amsterdam verlief ganz normal, zu essen gab es eine Art Rosinenbrot Sandwich belegt mit Schinken und Käse.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4374.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4374.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Angekommen in Amsterdam, hatte ich etwa 90 Minuten Aufenthalt. Bin durch die Flughafenläden flaniert, aber nichts hat mich zum kauf bewegt. Dann nochmal durch die Passkontrolle und dann nochmal an der Security abgetastet. Mit einer Stunde Verspätung dann nach SFO gestartet. Ich habe mir einen Platz am Gang ausgewählt, was den Vorteil hat, leichter mal aufstehen und sich die Beine vertreten zu können. Aus dem Fenster sieht man ja eh die meiste Zeit nur Wolken. Die junge Dame neben mir hat während des ganzen Fluges hauptsächlich Rotwein genossen - insgesamt 5 Flaschen in Flugzeuggröße, also über einen Liter. Es scheint ihr aber gut bekommen zu haben. Im Flugzeug die Zeit mit Film und Serien verbracht und etwa eine halbe oder ganze Stunde geschlafen.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;mt-enclosure mt-enclosure-image&quot;&gt;&lt;img alt=&quot;DSC_4382.jpg&quot; src=&quot;http://heeen.de/blog/mtview/DSC_4382.jpg&quot; width=&quot;600&quot; height=&quot;399&quot; class=&quot;mt-image-center&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Ankunft San Francisco International. An der Einlasskontrolle über eine Stunde, eher 1:30 Stunden angestanden. Alle Fingerabdrücke ein Bild und ein Zollformular abgegeben und zwei Sätze zum Aufenthalt erzählt, dann zum Gepäckband. Mein Koffer nirgends zu finden. Später wird mein Name ausgerufen und es wird mir gesagt, mein Koffer sei noch in Amsterdam. Also die Hotel&amp;nbsp;Adresse&amp;nbsp;angegeben und ohne Koffer weiter. Die Zollkontrolle winkt mich dann nur noch durch. Mit dem Air Train (Bild oben) zum Autoverleih gefahren wo mein Kollege Steffen die ganze Zeit auf mich wartet. Wir mieten einen weißen Chevrolet, Automatik ist in den Staten Standard. Ich muss mich sehr konzentrieren nicht mit dem Bremspedal Kuppeln und mit dem Automatik-hebel Schalten zu wollen, was zu abrupten Bremsmanövern und Auffahrunfällen führen könnte.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Angekommen am Hotel bin ich noch erstaunlich Fit. Die Kollegen sitzen am Pool, doch meine Badehose liegt im Koffer in Amsterdam. Ich gehe in den Supermarkt ein paar Notwendigkeiten einkaufen (Sonntags!) und später flanieren wir durch die Stadt auf der Suche nach einem Abendessen (Steak New York für mich)..&amp;nbsp;&lt;/div&gt;</description>
	<pubDate>Wed, 04 Aug 2010 07:11:22 +0000</pubDate>
</item>
<item>
	<title>LOLLERZ: The Modern Liberal Goal Part 2: Work as a game</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-4070984756651100341</guid>
	<link>http://blake8086.blogspot.com/2010/08/modern-liberal-goal-part-2-work-as-game.html</link>
	<description>&lt;span class=&quot;Apple-style-span&quot;&gt;So the question is:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;If the liberal goal [&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;everyone only has to work as much as they want to]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&amp;nbsp;is achieved, what is there to do for someone seeking to become wealthy?  What can we do with an army of people who don't ever &lt;/span&gt;&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;have&lt;/span&gt;&lt;/i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; to work for a living?&lt;/span&gt;&lt;/blockquote&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Now we've got two types of people in the world: those producing less than they consume, and those producing more.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;The government subsidizes people who are overconsuming, so they never have to work if they don't want to.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;So what's a future capitalist to do?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;We have to make them &lt;/span&gt;&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;want&lt;/span&gt;&lt;/i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; to work.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;We can do this in two ways: make work fun, or make work easy.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;How do we make work fun?&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Make it into a game!  People will put enormous effort into games voluntarily.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;We've already got some great business models for this:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Work hard for free!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Open source software and Wikipedia use this model.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Hey, give us tons of skilled labor and get no money in return!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;ok!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Work hard for social benefits!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Facebook, Twitter, LinkedIn, MySpace, and every social networking site ever.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Hey, give us tons of information to help target ads!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;ok!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Work hard to create value for paying users!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Zynga, Chinese MMOs (&lt;/span&gt;&lt;a href=&quot;http://www.slideshare.net/vgsummit/zhan-ye-what-us-game-developers-need-to-know-about-freetoplay-in-china-2408412&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;see slide 16 of this excellent presentation&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;).  We can make a free-to-play gameworld where our non-paying users add value for our paying users to take advantage of.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Pay for our game, you can kill noobs!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;noobs: &quot;noooo *adds value*&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;How do we make work easy?&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Bring it to them!  Who minds working from home?  Idiots, that's who.  All the cool people want to work from home.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;What have we got?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Use the massively parallel processor in your head to solve problems!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;a href=&quot;https://www.mturk.com/mturk/welcome&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Amazon's Mechanical Turk&lt;/span&gt;&lt;/a&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; lets you solve a single tiny task and get a single tiny amount of money.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Transcribe this for a quarter!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;ok!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Write an essay for $10!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Demand Studios will pay you to write essays for them, which they then spam all over the internet and place ads on.  It solves two problems: how do we fill the internet with more crap, and how do we get people to write more crap?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Write some crap!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;awesome!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Make some media and we'll sell it and give you a cut!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Infinite stock photography sites do this, as well as the Envato network for sounds, music, graphics, and other media.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;Make a song, we'll give you a few dollars per download!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&quot;groovy!&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Ok, that's enough examples!&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Yay!  I hope you're convinced that our brave new world of consumers is not necessarily a bleak dystopia.  Sure, the government will take a ton of our money, and redistribute it to the less worthy, but that doesn't mean we can't still extract some value from them!&lt;/span&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-4070984756651100341?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 03 Aug 2010 02:18:11 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>LOLLERZ: Amazon!</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-163197295853629998</guid>
	<link>http://blake8086.blogspot.com/2010/08/amazon.html</link>
	<description>&lt;span class=&quot;Apple-style-span&quot;&gt;Today I started at Amazon.&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Amazon is strangely a software company that sells retail products. &amp;nbsp;I'm not sure how that happened, but I assume Jeff Bezos is to thank for it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Thanks, Jeff Bezos.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;So now I am officially a Software Design Engineer - Gift Cards User Experience. &amp;nbsp;If you have any questions about being an SDEGCUE, feel free to ask me.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-163197295853629998?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 03 Aug 2010 01:17:58 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>LOLLERZ: The Modern Liberal Goal</title>
	<guid>tag:blogger.com,1999:blog-5195382480858168001.post-5525530237807772221</guid>
	<link>http://blake8086.blogspot.com/2010/08/modern-liberal-goal.html</link>
	<description>&lt;span class=&quot;Apple-style-span&quot;&gt;A while ago, I tried to answer a simple question as a thought experiment: “what is the goal of the ‘&lt;a href=&quot;http://en.wikipedia.org/wiki/Modern_liberalism_in_the_United_States&quot;&gt;modern liberal&lt;/a&gt;’ philosophy?”&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;I believe the answer is “everyone only has to work as much as they want to”.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;Why do I believe that?&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;In the United States, we have had a history of creating social welfare programs, and they tend to stick around.  &lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Welfare, Medicaid, WIC (the modern food stamps), unemployment, and disability are generally targeted at the poor and disadvantaged.  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Medicare and Social Security are targeted at the old, who often become poor as a combination of reduced earning ability and increasing health costs.  Unemployment, in particular, simply gives money to people who aren't earning any.  It's stated purpose is to help people &quot;get back on their feet&quot;, but for practical purposes, it can be collected for a year (at least in Texas) without having to do anything in particular.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;These welfare programs spring out of a philosophy of &quot;need&quot;.  I think there's a certain level of guilt that comes from rightfully earning the things we need, and continuing onward to earn things we want, while other people fail to even meet their own basic needs.  Governments then codify this guilt into programs to take money from those who've earned it and give it, in varying forms, to those who haven't.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;In a republic, these programs have a fair amount of stickiness due to taking money from a few voters and giving it to many voters.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt; &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;Why do I think it is likely to happen?&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Technology has given the most intelligent a massive lever with which to move the world and create value.  A rich person today wields more power than nations of the past.  Thanks to these forces, there is more marginal wealth per person at the top.  Bill Gates easily met his own needs many years and many dollars ago.  If we take 99% of his money, we can provide for probably tens or even hundreds of thousands of people.  I think there is social pressure to do this.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Along with amplifying the top tier's ability to create wealth, technology also lowers the bar for the poor to meet their basic needs.  Food is &lt;b&gt;cheap&lt;/b&gt; compared to any time in human history.  It becomes easier and easier for one person to meet their own needs.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span&gt;Marshall Brain's &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://www.marshallbrain.com/manna1.htm&quot;&gt;Manna&lt;/a&gt; provides in interesting guess as to two alternative futures, one ruled by the tyranny of the rich, who provide for the poor, but restrict their freedom to virtually nothing, and a more communist society where everyone is &quot;rich&quot; by pooling resources.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;If the liberal goal is achieved, what is there to do for someone seeking to become wealthy?  What can we do with an army of people who don't ever &lt;i&gt;have&lt;/i&gt; to work for a living?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;I'll tell you tomorrow.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5195382480858168001-5525530237807772221?l=blake8086.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Sun, 01 Aug 2010 21:42:57 +0000</pubDate>
	<author>noreply@blogger.com (Blake Householder)</author>
</item>
<item>
	<title>m0nk3yz: Miscellanea – Python Sprints, Nasuni, etc.</title>
	<guid>http://jessenoller.com/?p=783</guid>
	<link>http://feedproxy.google.com/~r/Jessenollercom/~3/VqqNvJJyvoA/</link>
	<description>&lt;p&gt;I&amp;#8217;ve obviously been quiet here on my personal blog &amp;#8211; as everyone who reads regularly knows I&amp;#8217;m neck-deep in a pretty exciting startup call Nasuni as well as doing other projects, like the PSF Sponsored sprints thing. That combined with twitter means my time for other additional long-form content is minimal. So here&amp;#8217;s a small roundup of interesting things:&lt;/p&gt;
&lt;h3&gt;Nasuni&lt;/h3&gt;
&lt;p&gt;Yup, still running Python and Django! We&amp;#8217;re actually pretty proud to be a sponsor for &lt;a href=&quot;http://djangocon.us/&quot;&gt;DjangoCon 2010&lt;/a&gt; coming up in September &amp;#8211; I&amp;#8217;ll be attending, so I hope to see all the familiar Django faces I know, and meet some new ones.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been blogging semi-regularly for the Nasuni blog itself &amp;#8211; my posts are focused on product-things more than anything else. Here&amp;#8217;s a small list of posts which I&amp;#8217;ve done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/the-road-to-release-feature-previews/&quot;&gt;The Road to Release &amp;#8211; Feature Previews&lt;/a&gt; &amp;#8211; this is actually my latest one, and the first in a series where I&amp;#8217;ll be showing off some of the new features we&amp;#8217;re adding in the latest release.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/looking-at-openstack-a-rackspace-and-nasa-initiative/&quot;&gt;Looking at OpenStack, a Rackspace and NASA initiative&lt;/a&gt; &amp;#8211; For those of you who don&amp;#8217;t know, Rackspace and NASA announced &lt;a href=&quot;http://openstack.org/&quot;&gt;OpenStack&lt;/a&gt; &amp;#8211; the awesome part? It&amp;#8217;s &lt;strong&gt;all python&lt;/strong&gt; &amp;#8211; I had the swift component (which powers Rackspace&amp;#8217;s cloudfiles system) of OpenStack running pretty quickly. I&amp;#8217;d recommend snagging the &lt;a href=&quot;https://launchpad.net/openstack/&quot;&gt;code from launchpad&lt;/a&gt; and taking a look. Swift (the storage component) uses eventlet &amp;#8211; and Nova (the compute part) uses Tornado and Twisted.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/storage-switzerland-test-drives-the-filer/&quot;&gt;Storage Switzerland Test Drives the Filer&lt;/a&gt; &amp;#8211; This is a response to an article written about the product &amp;#8211; I actually used it to preview some of the work going into the next release of the Filer.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/thanks-to-django/&quot;&gt;Thanks to Django&lt;/a&gt; &amp;#8211; This piece goes into some detail about our use of Django, it&amp;#8217;s one of our ways of saying thanks. I still need to rework it so we can send it over for the &lt;a href=&quot;http://code.djangoproject.com/wiki/DjangoSuccessStories&quot;&gt;Django Success Stories&lt;/a&gt; page.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/thanks-to-the-supporting-cast/&quot;&gt;Thanks to the Supporting Cast&lt;/a&gt; &amp;#8211; This is an earlier thank you post &amp;#8211; but to the other people who have helped out a ton, including Greg Newman, Lincoln Loop, and Revsys.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/the-donut-solution-nasunis-new-ui/&quot;&gt;The Donut Solution&lt;/a&gt; &amp;#8211; This was a fun one, mainly to show that yes &amp;#8211; we&amp;#8217;re listening hard to customer feedback, and we&amp;#8217;re improving/iterating quickly. Also, I get to show off UI improvements.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.nasuni.com/news/nasuni-blog/the-nasuni-blog-team/&quot;&gt;Finally &amp;#8211; The Nasuni Blog team&lt;/a&gt; &amp;#8211; this is the rosetta stone for the authors of the blog, describing who we are. I didn&amp;#8217;t write this piece, but it&amp;#8217;s good reading to figure out who is who.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;#8217;re interested in Nasuni &amp;#8211; or cloud storage in general &amp;#8211; I&amp;#8217;d encourage you to &lt;a href=&quot;http://feeds.nasuni.com/nasuni&quot;&gt;sign up for the RSS feed&lt;/a&gt;. We&amp;#8217;re trying to keep the information useful outside of &amp;#8220;just us&amp;#8221; (despite my urge and predilection to churning out completely product-related posts) &amp;#8211; and if you ever have feedback, drop us a line.&lt;/p&gt;
&lt;h3&gt;PSF Sponsored Sprints&lt;/h3&gt;
&lt;p&gt;The project continues on &amp;#8211; we&amp;#8217;ve funded two sprints so far, and have several more coming down the pike. We&amp;#8217;re always in need of volunteers to help us do things like the manuals and site maintenance/content authoring. Here&amp;#8217;s some highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://pythonsprints.com/2010/07/8/call-applications-now-open/&quot;&gt;The call for applications is open&lt;/a&gt; &amp;#8211; The call for applications is open &amp;#8211; and now I suspect we &lt;strong&gt;won&amp;#8217;t be closing it&lt;/strong&gt;. Originally, I thought we&amp;#8217;d have to do things in waves of apply-approve. As time has progressed, I no longer think this is the case.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pythonsprints.com/2010/07/10/montreal-python-packaging-sprint-wrapup/&quot;&gt;Montreal Python Packaging sprint wrap up&lt;/a&gt; &amp;#8211; the wrap up report for our first sprint!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pythonsprints.com/2010/07/27/europython-2010-core-sprint-report/&quot;&gt;Europython core sprint report &lt;/a&gt;- another wrap up report for the core sprint we provided funds to.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pythonsprints.com/2010/07/27/just-added-locations-page/&quot;&gt;Just added the locations page&lt;/a&gt; &amp;#8211; we now have people/companies offering up space for sprinters! Check it out!&lt;/li&gt;
&lt;li&gt;Finally - &lt;a href=&quot;http://pythonsprints.com/2010/07/29/sprints-pyohio/&quot;&gt;Sprints at PyOhio&lt;/a&gt; &amp;#8211; PyOhio is going on this weekend, if you&amp;#8217;re in the area you should really go check it out! Catherine has gone above and beyond with the entire &amp;#8220;become a contributor&amp;#8221; effort going on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please! If you&amp;#8217;re thinking about holding a sprint - &lt;strong&gt;send us an application&lt;/strong&gt;! Heck, even if we&amp;#8217;re not sponsoring it, we&amp;#8217;ll help promote you via the blog, and the sprint calendar we have up. A little fact? The sprints we&amp;#8217;ve funded so far, and that are on deck for funding are all &lt;strong&gt;outside&lt;/strong&gt; of the US, which is both awesome, and surprising!&lt;/p&gt;
&lt;h3&gt;PSF Board&lt;/h3&gt;
&lt;p&gt;Some of you probably know that I&amp;#8217;m currently on the board of directors for the PSF &amp;#8211; things progress well here, but I mainly wanted to call out the &lt;a href=&quot;http://pyfound.blogspot.com/&quot;&gt;excellent blog&lt;/a&gt; Doug Hellmann has been authoring for PSF news. You should &lt;strong&gt;really&lt;/strong&gt; be watching that because yes &amp;#8211; we do do things, and hopefully over the next year, we&amp;#8217;ll be doing more awesome things.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve actually got a bigger post in the works for what &lt;strong&gt;I think&lt;/strong&gt; the ultimate mission of the PSF is/should be as well as &amp;#8220;how do you get money from us&amp;#8221; as well. Must find the time!&lt;/p&gt;</description>
	<pubDate>Fri, 30 Jul 2010 17:34:19 +0000</pubDate>
</item>
<item>
	<title>Dietrich: Querying the 4 table structure.</title>
	<guid>tag:blogger.com,1999:blog-3702639791878600134.post-6665318616798695418</guid>
	<link>http://tomdietrich.blogspot.com/2010/07/querying-4-table-structure.html</link>
	<description>In my&amp;nbsp;&lt;a href=&quot;http://tomdietrich.blogspot.com/2010/07/bliss-and-four-table-structure.html&quot;&gt;previous post&lt;/a&gt;, I described how four physical tables can be thought of as a means to create infinite virtual tables. One natural question you may have about this technique is &quot;Ok, so how the heck do I query the virtual table?&quot;&amp;nbsp;It may seem a little challenging at first, but it is more than possible. Easy even.&lt;br /&gt;&lt;br /&gt;Take our customer-process virtual table for example.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://2.bp.blogspot.com/_8AWt_3xqhwM/TEBdMWXC02I/AAAAAAAAB48/M_aH_L-DiEM/s1600/4TableStructure3.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;117&quot; src=&quot;http://2.bp.blogspot.com/_8AWt_3xqhwM/TEBdMWXC02I/AAAAAAAAB48/M_aH_L-DiEM/s400/4TableStructure3.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;You need a query that will tell you every customer that has a max particle size over 1.5 inches. Remember that the table structure that drives this virtual table looks like this.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/_8AWt_3xqhwM/TEBa9FxsbJI/AAAAAAAAB40/wG8N5or8p80/s1600/4TableStructure2.png&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/_8AWt_3xqhwM/TEBa9FxsbJI/AAAAAAAAB40/wG8N5or8p80/s320/4TableStructure2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;What we'll want is all the customer-process data results where the value is &amp;gt; 1.5 and the process-info-detail is Cement-Mixing's Max Particle Size.&lt;br /&gt;&lt;br /&gt;That query simply looks like this :&lt;br /&gt;&lt;br /&gt;SELECT CPD.CustomerProcessID&lt;br /&gt;FROM Cust-Process-Data CPD&lt;br /&gt;INNER JOIN Process-Info-Detail PID ON CPD.ProcessInfoDetailID = PID.ProcessInfoDetailID&lt;br /&gt;INNER JOIN Process-Info PI ON PID.ProcessInfoID = PI.ProcessInfoID&lt;br /&gt;WHERE PI.Process = 'Cement Mixing' AND PID.ProcessInfo = 'Max Particle Size' AND CPD.Value &amp;gt; 1.5&lt;br /&gt;&lt;br /&gt;Or, to&amp;nbsp;genericise&amp;nbsp;it,&lt;br /&gt;&lt;br /&gt;SELECT RowHeaderID&lt;br /&gt;FROM CellData CD&lt;br /&gt;INNER JOIN ColumnHeader CH ON CD.ColumnID = CH.ColumnID&lt;br /&gt;INNER JOIN Table T ON CH.TableID = T.TableID&lt;br /&gt;WHERE T.TableName = '{Desired Table}' AND CH.ColumnName = '{Desired Column}' AND CD.Value {ValueClause}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What I'll typically do with this clause is throw it in a sub select and join against the result. Pretend the above SQL format is abbreviated as Query in the following examples.&lt;br /&gt;&lt;br /&gt;SELECT CustomerID&lt;br /&gt;FROM CustomerProcess CP&lt;br /&gt;INNER JOIN (Query) Q1 ON CP.CustomerProcessID = Q1.CustomerProcessID&lt;br /&gt;&lt;br /&gt;And BAM we've got our results. This query structure is flexible enough to mimic 'and' and 'or' clauses against the underlying virtual tables. To get an and, you simply need to inner join the different subselect queries- the result set will only include rows that meet all the provided criteria - like so.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;SELECT CustomerID&amp;nbsp;&lt;/div&gt;&lt;div&gt;FROM CustomerProcess CP&amp;nbsp;&lt;/div&gt;&lt;div&gt;INNER JOIN (Query) Q1 ON CP.CustomerProcessID = Q1.CustomerProcessID&lt;/div&gt;&lt;div&gt;INNER JOIN (Query2) Q2 ON Q1.CustomerProcessID = Q2.CustomerProcessID&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And to mimic an 'Or' clause, you can simply union the sub selects. Cool, huh?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/3702639791878600134-6665318616798695418?l=tomdietrich.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 29 Jul 2010 10:04:32 +0000</pubDate>
	<author>noreply@blogger.com (Dietrich)</author>
</item>
<item>
	<title>ShadowHawk: Running Internet Explorer 6 and 7 in Wine</title>
	<guid>http://yokozar.org/blog/?p=236</guid>
	<link>http://yokozar.org/blog/archives/236</link>
	<description>&lt;p&gt;Recently I ran into &lt;a title=&quot;Brian Behlendorf on Wikipedia&quot; href=&quot;http://en.wikipedia.org/wiki/Brian_Behlendorf&quot;&gt;Brian Behlendorf&lt;/a&gt; (from Apache) at a conference on medical record systems.  Brian was there demoing a new open source protocol for medical record systems to securely send eachother patient records (&lt;a title=&quot;NHIN Direct website&quot; href=&quot;http://nhindirect.org/&quot;&gt;NHIN Direct&lt;/a&gt;).  Combined, we were the only two who weren&amp;#8217;t doctors, vendors, bureaucrats, or hotel staff at the conference.&lt;/p&gt;
&lt;p&gt;I introduced myself, and Brian quickly recognized that I could probably help him with a Wine problem.  He needed to run Internet Explorer 6 for the most benevolent reason of all: to prove to a client it didn&amp;#8217;t work and that they shouldn&amp;#8217;t bother trying to support it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Internet Explorer in Wine&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The good news is these days it&amp;#8217;s very simple on the terminal.  On Ubuntu:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add the Wine Team PPA:&lt;em&gt;&lt;br /&gt;
sudo add-apt-repository ppa:ubuntu-wine/ppa&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Install the wine1.2 and winetricks packages:&lt;em&gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install wine1.2 winetricks&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Run winetricks:&lt;br /&gt;
&lt;em&gt;winetricks ie6 &lt;/em&gt;&lt;strong&gt;or&lt;/strong&gt;&lt;em&gt; winetricks ie7&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Run IE:&lt;em&gt;&lt;br /&gt;
wine iexplore&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Using the WINEPREFIX environment variable:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note that, just like in Windows, you cannot have both ie6 and ie7 at the same time, at least not in the same virtual C: drive.  Fortunately, it is easy to set up multiple wine folders (&amp;#8221;prefixes&amp;#8221;) for your version of IE to run.  We do this with the &lt;em&gt;WINEPREFIX&lt;/em&gt; environment variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;WINEPREFIX=~/.wine-ie6 winetricks ie6&lt;/em&gt;&lt;/strong&gt; to install ie6 into its own virtual C: drive&lt;strong&gt;&lt;br /&gt;
&lt;em&gt;WINEPREFIX=~/.wine-ie7 winetricks ie7&lt;/em&gt;&lt;/strong&gt; to install ie7 into its own virtual C: drive&lt;br /&gt;
&lt;strong&gt;&lt;em&gt;WINEPREFIX=~/.wine-ie6 wine iexplore&lt;/em&gt;&lt;/strong&gt; to run ie6&lt;br /&gt;
&lt;strong&gt;&lt;em&gt;WINEPREFIX=~/.wine-ie7 wine iexplore&lt;/em&gt;&lt;/strong&gt; to run ie7&lt;/p&gt;
&lt;p&gt;As an aside, Internet Explorer 8 doesn&amp;#8217;t currently work in Wine, however once it does there will also be a winetricks ie8 for you to test with.&lt;/p&gt;</description>
	<pubDate>Wed, 28 Jul 2010 11:30:12 +0000</pubDate>
</item>

</channel>
</rss>
