<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.wordaligned.org/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.wordaligned.org/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
<title>Word Aligned</title>
<link>http://wordaligned.org</link>
<description>tales from the code face</description>
<dc:creator>tag@wordaligned.org</dc:creator>
<language>en-gb</language>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.wordaligned.org/wordaligned" type="application/rss+xml" /><item>
<title>Fixing header file dependencies</title>
<description>&lt;h3&gt;DEPENDS&lt;/h3&gt;
&lt;img src="http://wordaligned.org/images/dependencies.png" alt="Dependencies"/&gt;

&lt;p&gt;Without care C++ header files can &lt;a href="http://yosefk.com/c++fqa/defective.html#defect-3" title="Have you read the C++ FQA yet?"&gt;deteriorate&lt;/a&gt;, so I was interested to find some sensible advice in the &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#names_and_Order_of_Includes" title="Google style guide advice on dependencies"&gt;Google C++ Style Guide&lt;/a&gt;.
&lt;/p&gt;
&lt;blockquote&gt;&lt;h4&gt;Names and Orders of Includes&lt;/h4&gt;&lt;p&gt;Use standard order for readability and to avoid hidden dependencies: C library, C++ library, other libraries&amp;#8217; &lt;code&gt;.h&lt;/code&gt;, your project&amp;#8217;s &lt;code&gt;.h&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&amp;#8230;&lt;/p&gt;&lt;p&gt;The preferred ordering reduces hidden dependencies. We want every header file to be compilable on its own. The easiest way to achieve this is to make sure that every one of them is the first &lt;code&gt;.h&lt;/code&gt; file #included in some &lt;code&gt;.cc&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I agree, hidden dependencies are bad, and I&amp;#8217;m not about to quibble with the &amp;#8220;standard order&amp;#8221; defined by the &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml"&gt;guide&lt;/a&gt;, even if I&amp;#8217;m used to a slightly different ordering. Certainly headers should be compilable on their own; but I suggest the easiest way to achieve this is, well, &lt;strong&gt;to compile them on their own&lt;/strong&gt;. 
&lt;/p&gt;
&lt;span id="continue-reading"/&gt;


&lt;h3&gt;README&lt;/h3&gt;
&lt;p&gt;You don&amp;#8217;t need a project file or even a makefile if you want to compile something. It&amp;#8217;s easy to create a script which confirms a header has no hidden dependencies by including and compiling it&lt;a id="fn1link" href="http://wordaligned.org/articles/fixing-header-file-dependencies#fn1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;. Create a file called &lt;code&gt;check-header&lt;/code&gt; and paste in the following:
&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;check-header&lt;/div&gt;

&lt;pre class="prettyprint"&gt;#!/bin/bash
cat &amp;lt;&amp;lt;EOF &amp;gt;tmp.cc &amp;amp;&amp;amp; g++ $CPPFLAGS tmp.cc
#include "$1"
int main() { return 0; }
EOF

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make sure &lt;code&gt;check-header&lt;/code&gt; is executable. Put it somewhere on your &lt;code&gt;PATH&lt;/code&gt;. Export suitable &lt;code&gt;CPPFLAGS&lt;/code&gt; for your codebase (here, I&amp;#8217;m choosing to treat warnings as errors).
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ chmod a+x check-header
$ mv check-header ~/bin
$ export CPPFLAGS="-Wall -Werror"

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Given a header file, &lt;code&gt;check-header&lt;/code&gt; redirects a &lt;a href="http://www.gnu.org/software/bash/manual/bashref.html#Redirections"&gt;here document&lt;/a&gt; into a temporary source file. The source file contains a minimal C++ program which does nothing more than include the header. &lt;code&gt;Check-header&lt;/code&gt; compiles that program. Compilation diagnostics, if any, appear on standard error. The exit status will be 0 if the header compiles cleanly, non-zero otherwise.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ check-header standalone.h
$ echo $?
0
$ cat &amp;gt; depends_on_x.h
void f(X x);
$ check-header depends_on_x.h
depends_on_x.h:1: error: variable or field 'f' declared void
depends_on_x.h:1: error: 'X' was not declared in this scope
$ echo $?
1

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;INSTALL&lt;/h3&gt;
&lt;p&gt;It gets tiresome to run this command on one header at a time. Happily we can use it in a compound command to check all the headers in the current directory&lt;a id="fn2link" href="http://wordaligned.org/articles/fixing-header-file-dependencies#fn2"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ for header in *.h; do check-header $header; done

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or on all headers beneath the current directory: 
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ find . -name "*.h" | xargs -L 1 check-header

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(The &lt;code&gt;-L 1&lt;/code&gt; is required because &lt;code&gt;check-header&lt;/code&gt; can only handle one file at a time.)
&lt;/p&gt;
&lt;p&gt;Make this part of your overnight build, and you&amp;#8217;ve got an easy way to monitor dependencies in header files.
&lt;/p&gt;

&lt;h3&gt;BUGS&lt;/h3&gt;
&lt;p&gt;The script shown here is about the simplest thing which could possibly work. Just a single compiler is used, the temporary file name is hard-wired, no clean-up is done, there&amp;#8217;s a dependency on the shell environment, diagnostics are limited, there isn&amp;#8217;t even any command-line help. A grubby header can sneak past this script by using preprocessor defines for conditional compilation, and different (versions of) compilers will disagree on what&amp;#8217;s clean. 
&lt;/p&gt;
&lt;p&gt;The truth is that I usually recreate this script and variants of it as and when required. My real intention is to demonstrate the rather obvious idea that we should &lt;a class="excerpt" href="http://wordaligned.org/excerpts" title="More excerpts" &gt;use the compiler to detect compilation problems.&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;TODO&lt;/h3&gt;
&lt;p&gt;Once your headers include all they depend on, maybe you&amp;#8217;d like to tackle the flip side of the problem, of determining which includes they don&amp;#8217;t or shouldn&amp;#8217;t depend on. 
&lt;/p&gt;
&lt;p&gt;Can another &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Header_File_Dependencies" title="Google Style Guide rule on dependency reduction"&gt;tip&lt;/a&gt; from the Google Style Guide be automated?
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Use forward declarations to minimize use of &lt;code&gt;#include&lt;/code&gt; in &lt;code&gt;.h&lt;/code&gt; files.
&lt;/p&gt;
&lt;p&gt;&amp;#8230;
&lt;/p&gt;
&lt;p&gt; You can significantly minimize the number of header files you need to include in your own header files by using forward declarations. For example, if your header file uses the &lt;code&gt;File&lt;/code&gt; class in ways that do not require access to the declaration of the &lt;code&gt;File&lt;/code&gt; class, your header file can just forward declare &lt;code&gt;class File;&lt;/code&gt; instead of having to &lt;code&gt;#include "file/base/file.h"&lt;/code&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;div class="amazon"&gt;&lt;a href="http://www.amazon.com/gp/product/0321113586?ie=UTF8&amp;amp;tag=wordalig-20"&gt;&lt;img  src="http://wordaligned.org/images/books/cpp-coding-standards.jpg" alt="Book cover"/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;I don&amp;#8217;t think many of us would dispute this advice, though &lt;a href="http://wordaligned.org/articles/retro-fitting-coding-standards#tocask-the-experts"&gt;I&amp;#8217;m not sure it belongs in a style guide&lt;/a&gt; &amp;#8212; it&amp;#8217;s just good C++ practice, the stuff you should be getting &lt;a href="http://www.amazon.com/gp/product/0321113586?ie=UTF8&amp;amp;tag=wordalig-20" title="Amazon affiliates link to C++ Coding Standards by Sutter and Alexandrescu"&gt;from a book&lt;/a&gt;. What I&amp;#8217;d like is a refactoring tool which does it for me, something like Eclipse&amp;#8217;s &lt;a href="http://help.eclipse.org/ganymede/index.jsp?topic=/org.eclipse.jdt.doc.user/gettingStarted/qs-OrganizeImports.htm"&gt;&amp;#8220;organize imports&amp;#8221;&lt;/a&gt;. A script might be able to do some of this, but it will have to be considerably more complex than &lt;code&gt;check-header&lt;/code&gt;, and without access to the compiler internals it will be limited in power.
&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;a id="fn1" href="http://wordaligned.org/articles/fixing-header-file-dependencies#fn1link"&gt;[1]&lt;/a&gt; While writing this article I discovered &lt;a href="http://gcc.gnu.org/"&gt;GCC&lt;/a&gt; allows you to precompile header files, reducing the need to create even a minimal script like &lt;code&gt;check-header&lt;/code&gt;. Running &lt;code&gt;gcc $CPPFLAGS header.h&lt;/code&gt; generates &lt;code&gt;header.gch&lt;/code&gt; for a valid and self-contained header file, and compiler diagnostics otherwise. As the &lt;a href="http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html"&gt;documentation&lt;/a&gt; says:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;There are many other possibilities, limited only by your imagination, good sense, and the constraints of your build system.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a id="fn2" href="http://wordaligned.org/articles/fixing-header-file-dependencies#fn2link"&gt;[2]&lt;/a&gt; It would be better to tweak &lt;code&gt;check-header&lt;/code&gt; to work on a list of input files.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=hfhYQj"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=hfhYQj" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=ZkcR4j"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=ZkcR4j" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=B5kxQj"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=B5kxQj" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=YbUAPJ"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=YbUAPJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/325175217" height="1" width="1"/&gt;</description>
<dc:date>2008-07-02</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/fixing-header-file-dependencies</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/325175217/fixing-header-file-dependencies</link>
<category>C++</category>
<category>C</category>
<category>Shell</category>
<feedburner:origLink>http://wordaligned.org/articles/fixing-header-file-dependencies</feedburner:origLink></item>

<item>
<title>Running Sums in Python</title>
<description>&lt;p&gt;Suppose we want to generate the running sum series &lt;code&gt;r&lt;/code&gt; formed by sums of &lt;code&gt;n&lt;/code&gt; consecutive elements taken from a series &lt;code&gt;s&lt;/code&gt;. For example, to sum consecutive pairs taken from the first 6 integers:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; n = 2
&amp;gt;&amp;gt;&amp;gt; s = 0, 1, 2, 3, 4, 5
&amp;gt;&amp;gt;&amp;gt; running_sum(s, 2)
[1, 3, 5, 7, 9]

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;One approach would be to combine the &lt;code&gt;sum&lt;/code&gt; built-in function with list slices and comprehensions&lt;a id="fn1link" href="http://wordaligned.org/articles/running-sums-in-python#fn1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; def running_sum(s, n):
... 	return [sum(s[lo:lo + n]) for lo in range(len(s) - n + 1)]
... 
&amp;gt;&amp;gt;&amp;gt; running_sum([0, 1, 2, 3, 4, 5], 2)
[1, 3, 5, 7, 9]

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is fine if:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     &lt;code&gt;s&lt;/code&gt; is finite
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;s&lt;/code&gt; supports slice access (i.e. &lt;code&gt;s[lo:hi]&lt;/code&gt; doesn&amp;#8217;t raise a &lt;code&gt;TypeError&lt;/code&gt;)
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;n&lt;/code&gt; isn&amp;#8217;t too big
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With just a little extra thought we can address all these issues.
&lt;/p&gt;
&lt;span id="continue-reading"/&gt;

&lt;p&gt;To deal with the first two points we return to the specification. What exactly do we require of &lt;code&gt;s&lt;/code&gt; in order to generate &lt;code&gt;r&lt;/code&gt;? Well, all that&amp;#8217;s really needed is for &lt;code&gt;s&lt;/code&gt; to be iterable &amp;#8212; which is to say we can advance along it &amp;#8212; then our running sum function can arrange to buffer &lt;code&gt;n&lt;/code&gt; items from &lt;code&gt;s&lt;/code&gt; and yield their sums. For maximum flexibility the result series &lt;code&gt;r&lt;/code&gt; should also be iterable, allowing clients to choose how to consume it&lt;a id="fn2link" href="http://wordaligned.org/articles/running-sums-in-python#fn2"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;In Python an object, &lt;code&gt;o&lt;/code&gt;, becomes iterable by implementing the &lt;a href="http://docs.python.org/lib/typeiter.html"&gt;iterator protocol&lt;/a&gt;: &lt;code&gt;o.__iter__()&lt;/code&gt; should return an iterator, &lt;code&gt;i&lt;/code&gt;, over the container, which &lt;code&gt;i.next()&lt;/code&gt; advances, raising a &lt;code&gt;StopIteration&lt;/code&gt; exception when done.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; r = [1, 2, 3]
&amp;gt;&amp;gt;&amp;gt; i = r.__iter__()
&amp;gt;&amp;gt;&amp;gt; i.next()
1
&amp;gt;&amp;gt;&amp;gt; i.next()
2
&amp;gt;&amp;gt;&amp;gt; i.next()
3
&amp;gt;&amp;gt;&amp;gt; i.next()
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
StopIteration

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python programs typically don&amp;#8217;t expose this protocol directly since we can build more convenient looping constructs on top of it. By using the &lt;a href="http://docs.python.org/ref/yield.html"&gt;yield statement&lt;/a&gt; our running sum filter needn&amp;#8217;t implement the iterator protocol directly either. Here&amp;#8217;s a generator function which uses &lt;code&gt;itertools.islice&lt;/code&gt; in place of the original list slices.
&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;Running sum for infinite series&lt;/div&gt;

&lt;pre class="prettyprint"&gt;import itertools

def running_sum(s, n):
    while True:
        r, s = itertools.tee(s)
        yield sum(itertools.islice(r, n))
        s.next()

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, objects returned by this function implement the iterator protocol.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;# Running sum of pairs from 0, 1, 2, 3, ...
&amp;gt;&amp;gt;&amp;gt; rs = running_sum(itertools.count(), 2)
&amp;gt;&amp;gt;&amp;gt; i = rs.__iter__()
&amp;gt;&amp;gt;&amp;gt; i.next()
1
&amp;gt;&amp;gt;&amp;gt; i.next()
3
&amp;gt;&amp;gt;&amp;gt; for s in rs: print s
... 
5
7
9
11
13
....
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
KeyboardInterrupt

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We have to kill the for loop by interrupting it since &lt;code&gt;rs&lt;/code&gt;, being infinite (in this particular case), never raises a &lt;code&gt;StopIteration&lt;/code&gt;. In fact, this particular version of &lt;code&gt;running_sum()&lt;/code&gt; fails badly on finite inputs for reasons we&amp;#8217;ll touch on later.
&lt;/p&gt;
&lt;p&gt;I won&amp;#8217;t dwell on this flawed variant of &lt;code&gt;running_sum()&lt;/code&gt;, except to note in passing that the built-in sum function doesn&amp;#8217;t buffer &lt;code&gt;n&lt;/code&gt; items from its input stream &amp;#8212; it&amp;#8217;s a lazy function which accumulates these items one at a time. There&amp;#8217;s no magic here, though: behind the scenes, as the teed iterators &lt;code&gt;r&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; diverge, the in-between values must be stored somewhere!
&lt;/p&gt;
&lt;p&gt;Each slice of items from &lt;code&gt;s&lt;/code&gt; overlaps the one before: if we visualise the sliced range sliding along the series, at each stage an element gets pushed in at the top and an element gets popped out from the bottom. Rather than repeatedly summing all the elements of these slices, we can calculate a single sum at the start of the series then adjust it as we progress&lt;a id="fn3link" href="http://wordaligned.org/articles/running-sums-in-python#fn3"&gt;&lt;sup&gt;[3]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;def running_sum(s, n):
    lo, hi = itertools.tee(s)
    rs = sum(itertools.islice(hi, n))
    while True:
        yield rs
        rs += hi.next() - lo.next()

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before we sign this function off, there&amp;#8217;s a bug to fix. What if &lt;code&gt;n&lt;/code&gt; is larger than the length of the input series? We&amp;#8217;d expect the output series to be empty, but:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; list(running_sum([1, 2, 3], 4))
[6]

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Oops! The problem here is in passing an &lt;code&gt;itertools.islice&lt;/code&gt; series to &lt;code&gt;sum()&lt;/code&gt;, which happily swallows the &lt;code&gt;StopIteration&lt;/code&gt; exception without knowing if the sliced stream reached its end or if we reached the end of the slice, or indeed both.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; i = itertools.islice([1, 2, 3], 4)
&amp;gt;&amp;gt;&amp;gt; i.next(), i.next(), i.next()
(1, 2, 3)
&amp;gt;&amp;gt;&amp;gt; i.next()
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
StopIteration

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A fix is to pass &lt;code&gt;sum&lt;/code&gt; a list comprehension. If &lt;code&gt;n&lt;/code&gt; is too big a &lt;code&gt;StopIteration&lt;/code&gt; exception gets raised before &lt;code&gt;sum&lt;/code&gt; ever sees this list.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;def running_sum(s, n):
    lo, hi = itertools.tee(s)
    rs = sum([hi.next() for _ in range(n)])
    while True:
        yield rs
        rs += hi.next() - lo.next()

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As a final tweak, we can make &lt;code&gt;lo&lt;/code&gt; and &lt;code&gt;hi&lt;/code&gt; iterator.next functions rather than iterators, which saves a few attribute access calls.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;def running_sum(s, n):
    '''Generate the series of running sums of n elements of s.
    
    &amp;gt;&amp;gt;&amp;gt; list(running_sum([1, 2, 3, 4], 2))
    [3, 5, 7]
    &amp;gt;&amp;gt;&amp;gt; rs = running_sum(itertools.count(), 3)
    &amp;gt;&amp;gt;&amp;gt; rs.next(), rs.next(), rs.next()
    (3, 6, 9)
    &amp;gt;&amp;gt;&amp;gt; list(running_sum([1, 2], 3))
    []
    '''
    lo, hi = [i.next for i in itertools.tee(s)]
    rs = sum([hi() for _ in range(n)])
    while True:
        yield rs
        rs += hi() - lo()

&lt;/pre&gt;

&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a id="fn1" href="http://wordaligned.org/articles/running-sums-in-python#fn1link"&gt;[1]&lt;/a&gt;: Thanks to &lt;a href="http://www.reddit.com/r/programming/info/6otfp/comments/"&gt;doubtingthomas&lt;/a&gt; for pointing out an off-by-one error in the original version of this.
&lt;/p&gt;
&lt;p&gt;&lt;a id="fn2" href="http://wordaligned.org/articles/running-sums-in-python#fn2link"&gt;[2]&lt;/a&gt; In a recent &lt;a href="http://geekrant.wordpress.com/2008/06/23/misconceptions/"&gt;post on his blog&lt;/a&gt;, Jake clears up some misconceptions about &lt;a href="http://haskell.org"&gt;Haskell&lt;/a&gt;. In doing so he analyses the difference between lazy and strict types with clarity and insight. Recommended reading!
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;This parallel indicates pretty clearly that recursively operating on each element of a stream is an infinite loop. &lt;code&gt;Stream&lt;/code&gt; is a &lt;em&gt;control structure&lt;/em&gt;. It doesn&amp;#8217;t exist to persist data across many parts of a program. It exists to feed data into a function one element at a time. In contrast, a &lt;code&gt;Vector&lt;/code&gt; exists to persist an intermediate or final &lt;em&gt;result&lt;/em&gt; of some 3-dimensional computation. In short, &lt;code&gt;Stream&lt;/code&gt; is for &lt;em&gt;controlling computation&lt;/em&gt;, and &lt;code&gt;Vector&lt;/code&gt; is for &lt;em&gt;storing data&lt;/em&gt;. This generalizes to lazy and strict types, respectively.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a id="fn3" href="http://wordaligned.org/articles/running-sums-in-python#fn3link"&gt;[3]&lt;/a&gt; There may be situations where we really want each running sum to be generated directly from &lt;code&gt;n&lt;/code&gt; consecutive elements of the source stream: for example, if we are dealing with a series of floating point numbers, then addition is not exact and we must take care to avoid accumulated errors.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=v1NQ6i"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=v1NQ6i" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=ORbgVi"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=ORbgVi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=D0ge6i"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=D0ge6i" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=oysONI"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=oysONI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/319131090" height="1" width="1"/&gt;</description>
<dc:date>2008-06-24</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/running-sums-in-python</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/319131090/running-sums-in-python</link>
<category>Python</category>
<category>Streams</category>
<category>Algorithms</category>
<feedburner:origLink>http://wordaligned.org/articles/running-sums-in-python</feedburner:origLink></item>

<item>
<title>Eurovision 2008 charts</title>
<description>&lt;p&gt;Last time I visited the &lt;a href="http://code.google.com/apis/chart/"&gt;Google chart API&lt;/a&gt; I discovered &lt;a href="http://code.google.com/apis/chart/#maps" title="Google chart API, map section"&gt;maps had been added&lt;/a&gt;. Since then I&amp;#8217;ve been itching to use them. &lt;a href="http://www.eurovision.tv/"&gt;Eurovision 2008&lt;/a&gt; got me scratching that itch.
&lt;/p&gt;
&lt;img title="Serbia scored 160 points" src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGEMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:jAKAAAo9AZoeAAZAeA99yAyjAAFUjUKAZAFUFePA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=440x220" alt="Votes for Serbia"/&gt;

&lt;span id="continue-reading"/&gt;

&lt;p&gt;As ever the &lt;a href="http://code.google.com/apis/chart/"&gt;API&lt;/a&gt; is a delight to use, if somewhat restricted. You&amp;#8217;re limited to selecting a geographical area from a small set, but happily this set includes Europe. Chart data is supplied as a string of concatenated &lt;a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm"&gt;ISO 3166-1 alpha-2&lt;/a&gt; country codes (e.g. &amp;#8220;TV&amp;#8221; for &amp;#8220;Tuvalu&amp;#8221;), and the chart value for each data point (i.e. country) maps to a colour gradient. Your palette is limited: water masses get a fill colour; a pair of colours provides the gradient used for countries in the chart data string; and omitted countries get a default colour.
&lt;/p&gt;
&lt;p&gt;To depict &lt;a href="http://www.eurovision.tv/"&gt;Eurovision&lt;/a&gt; results I chose suitably lurid colours. The results for Serbia, who hosted the event in 2008, are shown at the top of this page. Serbia appears in yellowy-orange, and the mauvey-bluey colours show who voted for Serbia &amp;#8212; the darker the shade, the higher the vote&lt;a id="fn1link" href="http://wordaligned.org/articles/eurovision-2008-charts#fn1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;The Maps&lt;/h3&gt;
&lt;p&gt;Here are the maps in order of &lt;a href="http://www.eurovision.tv/page/the-final-2008"&gt;Eurovision 2008 scores&lt;/a&gt;. Hover your mouse over them to see the country and the score. If you&amp;#8217;re wondering why you can&amp;#8217;t see Israel, it&amp;#8217;s because Israel isn&amp;#8217;t in Europe.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLROAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:FZAZAAjAPoFAZ9jeZyjUe9ey99oeyo9eZ9eyj9oyoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Russia scored 272 points" alt="Votes for Russia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AeZjZjAAFeAAoye9APKPjUUeyeyyPoyoeyjjoZyeUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Ukraine scored 230 points" alt="Votes for Ukraine"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:PUAP9P9Zo9eFjZAAAejZFPoAAKP9PeK9oKyUZoUoe9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Greece scored 218 points" alt="Votes for Greece"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:9AFyAAeA9y9Kyo9AAAZeAAFAAAA9U9AjKAjoK99ZFoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Armenia scored 199 points" alt="Votes for Armenia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AjyejyAAKAU9KjKK9AKFoAUeUPoZZZejFZFZAjZUAjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Norway scored 182 points" alt="Votes for Norway"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGEMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:jAKAAAo9AZoeAAZAeA99yAyjAAFUjUKAZAFUFePA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Serbia scored 160 points" alt="Votes for Serbia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSEILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:yAAAoUyeyAyAAAAKUAoAAjZAAAAoK9UyAPZAAAeAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Turkey scored 138 points" alt="Votes for Turkey"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAAAAAFAjAKA9PPAAAFAAAo9UjAjKyyAjoPoyAjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Azerbaijan scored 132 points" alt="Votes for Azerbaijan"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:eAAAAAPFZKPAAFAPoPZKAAPAPAZeejZUAUKeAePjZyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Israel scored 124 points" alt="Votes for Israel"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:KKAAAKZjAAjyeAAAyey9AZAAAAAAAPAAAAAAFAA9yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Bosnia and Herzegovina scored 110 points" alt="Votes for Bosnia and Herzegovina"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:A9UKyeAAAAAPAAAoAAAAUjAAyjAAAAAAKAAAPAKAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Latvia scored 83 points" alt="Votes for Latvia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMCSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAAAAAAAAjAAUKUFAAAAAZAAoZZAAjUoAAeAPUyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Georgia scored 83 points" alt="Votes for Georgia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:oAeoAAUyeAZAAAAAAAAPAAAAAAAAAAPAyAAAAAAFAZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Portugal scored 69 points" alt="Votes for Portugal"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAUe9AAAAAoAUAjojAAAAAAKAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Iceland scored 64 points" alt="Votes for Iceland"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AF9APAAAAAZAAAZ9AAAAPAKjKUAAAAAAAAAAKAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Denmark scored 60 points" alt="Votes for Denmark"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAAAAAAoAAAAFAyAAAUFoA9AAAAAAAFAAAAAAAAAjPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Albania scored 55 points" alt="Votes for Albania"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:ZAAFFAUUUAAPAoyAFAAAAAAAAAAAAAAF9AAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Spain scored 55 points" alt="Votes for Spain"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLTRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAPFAoAAAFAAFAAjZAAAKAFAF9AAAAAPAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Sweden scored 47 points" alt="Votes for Sweden"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=IEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AoAKZAAAAAUAAAAFKAAAeAAPoAFAAAAAPAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="France scored 47 points" alt="Votes for France"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:UPA9AAAAAPAAAeAUAAAAAAAAAAAAAAAAAAA9AAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Romania scored 45 points" alt="Votes for Romania"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAEEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAAAAAKPAAAAAAAPAAoyAKAZAAAFFAFAAAAAAKFPKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Croatia scored 44 points" alt="Votes for Croatia"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOSIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAjAAAAAAAAjAAAAUAAAyAAFAAKAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Finland scored 35 points" alt="Votes for Finland"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="United Kingdom scored 14 points" alt="Votes for United Kingdom"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKCHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTPLRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Germany scored 14 points" alt="Votes for Germany"/&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=t&amp;amp;chtm=europe&amp;amp;chld=FRIEISESGBDKDECHBECYNLSETRILGRPTNOFISIBAHREEMKHULVLTMTRORUAZUAALADBYBGMDCZAMGECSMESMBDWFBFBBBLBMBNBOJPBIBJBTJMBVBWWSBRBSJEBZRWRELULRLSGWGUGTGSGQGPBHGYGGGFGDGAGNGMGLKWGIGHOMJOHTSVHKHNHMPRPSPWKRPYIQSHPFPGPEPKPHPNPMZMEHEGZAECVNSBETZWSAERMGMFMAMCUZMMMLMOMNMHUSUMMWMVMQMPMSMRAUUGMYMXMZAWAFFJFKFMFONINAVUNCNENFNGNZNPNRNUCKCICOCNCMCLCCCALBCGCFCDCXCRCVCUSZSYKGKESRKIKHKNKMSTSKSJKPSOSNSLSCKZKYSGSDDODMDJYEDZUYYTMUTZLCLATVTWTTLKLITNTOTLTMTJTKTHTFTGTDTCLYVAVCAEVEAGVGAIVIIRITAOANAQASARIMATIOINAXIDPAQA&amp;amp;chd=s:AyAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&amp;amp;chco=FFCC00,FFFFFF,000066&amp;amp;chf=bg,s,00FFCC&amp;amp;chs=250x125" title="Poland scored 14 points" alt="Votes for Poland"/&gt;
&lt;/p&gt;

&lt;h3&gt;The Script&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s the script I used to generate the pictures. It&amp;#8217;s hacky, sub-optimal and packed with workarounds to get the job done. As &lt;a href="http://blog.plover.com/prog/perl/lines.html"&gt;Mark Dominus&lt;/a&gt; puts it:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Not everything we do is a brilliant, diamond-like jewel, polished to a luminous gloss with pages torn from one of Donald Knuth&amp;#8217;s books.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I do think the code also shows how adept Python is at working with XML (XHTML in this case) and text processing, and why every programmer should know at least one scripting language.
&lt;/p&gt;
&lt;p&gt;As input it needs:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     the Wikipedia Eurovision 2008 &lt;a href="http://en.wikipedia.org/wiki/Eurovision_Song_Contest_2008"&gt;page&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     the official list of &lt;a href="http://www.iso.org/iso/list-en1-semic-2.txt"&gt;ISO-3166 alpha-2 codes&lt;/a&gt;
 &lt;/li&gt;
&lt;/ul&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;Eurovision charts&lt;/div&gt;

&lt;pre class="prettyprint"&gt;'''Generate Eurovision charts using Google chart API.

Method:
* get a mapping between country names and country codes
* find the final results table in the Wikipedia Eurovision page
* extract voting information from this table
* munge all this information into google chart URLs
'''
import string
import xml.dom

def internal_co_name(co_name):
    '''Convert a country name into a form used internally.
    
    We remove punctuation and convert to uppercase. This helps map
    between the official country names and the less standard ones used
    on the Wikipedia page.
    '''
    ascii = string.ascii_letters
    return ''.join(c.upper() for c in co_name if c in ascii)

def country_codes_dict(iso_3166_fp):
    '''Return a dict mapping country names to 3166-1-alpha-2 codes.
    
    We get these from the ISO website in a ISO-8859 encoded text file
    which contains a header followed by records of the form
    AFGHANISTAN;AF
    '''
    import re
    import codecs
    ccode_match = re.compile(r"^([^;]+);(\w\w)", re.UNICODE).match
    lines = codecs.iterdecode(iso_3166_fp, "iso-8859-1")
    co_codes = dict((internal_co_name(m.group(1)), m.group(2))
                    for m in map(ccode_match, lines) if m)
    # Add some shortened forms
    co_codes.update(dict(MACEDONIA="MK", BOSNIA="BA", RUSSIA="RU", MOLDOVA="MD"))
    # Hack! Serbia should be SR but, as at 2008-05-28, the google
    # chart api seems to want the country code for the former Serbian
    # and Montenegro.  This line can be removed once the chart api
    # matches its documentation.
    co_codes["SERBIA"] = "CS"
    return co_codes

def tree_walk(node):
    '''Recursively walk the nodes in a tree.'''
    yield node
    for node1 in node.childNodes:
        for node2 in tree_walk(node1):
            yield node2

def tree_find(root, pred):
    '''Return the first node for which the predicate holds, or None.''' 
    for node in tree_walk(root):
        if pred(node):
            return node

def next_sibling_find(node, pred):
    '''Return the first next-sibling node for which the predicate holds.'''
    while node.nextSibling:
        node = node.nextSibling
        if pred(node):
            return node

def children(node, name):
    '''Return (tag-)named child elements of a node.'''
    return node.getElementsByTagName(name)

def is_text(node):
    return node.nodeType == xml.dom.Node.TEXT_NODE

def is_element(node):
    return node.nodeType == xml.dom.Node.ELEMENT_NODE

def text(node):
    '''Return text from a node of the general form &amp;lt;td&amp;gt;&amp;lt;b&amp;gt;12&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt; or &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;'''
    while not is_text(node) and node.childNodes:
        node = node.childNodes[0]
    return node.data if is_text(node) else None

def country_votes(tr):
    '''Convert a row from the results table.
    
    Returns country name, score and votes for that country.
    '''
    td = children(tr, 'td')
    co_name, score = text(td[0]), int(text(td[1]))
    votes = [int(text(cell)) for cell in td[2:] if text(cell)]
    return co_name, score, votes

def results(wiki_table, co_code_dict):
    '''Extract the results from the Wikipedia results table.
    
    Returns the column headings country codes and a list of votes.
    '''
    import operator
    second = operator.itemgetter(1)
    trs = children(wiki_table, 'tr')
    ths = children(trs[1], 'th')[1:]
    # The title of each column header 'a' element looks like "ESCFranceJ.svg"
    # The [3:-5] slice converts this to "France", and we then look up
    # the 3166 alpha-2 code
    ICN = internal_co_name
    cols = [co_code_dict[ICN(children(th, 'a')[0].getAttribute('title')[3:-5])]
            for th in ths]
    votes = sorted((country_votes(tr) for tr in trs[2:]), 
                   key=second, reverse=True)
    return cols, votes

def results_table(wiki_page):
    '''Return the results table from the Wikipedia Eurovision results.
    
    By inspection, this is the first table after the "Final_2" node.
    '''
    import xml.dom.minidom
    def final_2(n):
        return is_element(n) and n.getAttribute('id') == 'Final_2'
    def htm_table(n):
        return is_element(n) and n.tagName == 'table'
    doc = xml.dom.minidom.parse(wiki_page)
    node = tree_find(children(doc, 'body')[0], final_2)
    return next_sibling_find(node.parentNode, htm_table)

def eurovision_vote_map(co_name, co_codes, scores, hi_score, missing):
    '''Return the URL of a map showing Eurovision votes for a country.
    '''
    # Use simple text encoding
    simple = string.uppercase + string.lowercase + string.digits
    simple_hi_ix = len(simple) - 1
    mapurl = (
        'http://chart.apis.google.com/chart?'
        'cht=t&amp;amp;chtm=europe&amp;amp;'  # Map of Europe
        'chld=%(countries)s&amp;amp;' # String of country codes
        'chd=s:%(values)s&amp;amp;'   # Values for these countries, simple encoding
        'chco=%(def_colour)s,%(lo_colour)s,%(hi_colour)s&amp;amp;'
        'chf=bg,s,%(sea_colour)s&amp;amp;'
        'chs=%(width)dx%(height)d')
    # Use a hack here to highlight the country being voted for.  Don't
    # include this country in the chart data, then it will get the
    # default colour. Assign all missing entries and zero scoring
    # entries the 'lo_colour'.
    omit = internal_co_name(co_name)
    values = ''.join(simple[simple_hi_ix * score // hi_score] for
                     score in scores) + 'A' * (len(missing)//2)
    countries = ''.join(c for c in co_codes if c != omit) + missing
    width, height = 250, 125 # The maximum map size is 440, 220
    def_colour, sea_colour = 'FFCC00', '00FFCC'
    lo_colour, hi_colour = 'FFFFFF', '000066'  
    return mapurl % locals()

def get_map_urls(wiki_results_fp, ccodes_fp):
    '''Return the URLs for Eurovision results charts, ordered by score.
    '''
    wiki_table = results_table(wiki_results_fp)
    co_codes = country_codes_dict(ccodes_fp)
    cols, votes = results(wiki_table, co_codes)
    # We only really need the countries which 1) weren't part of
    # Eurovision and 2) which appear in the Google chart of Europe, but
    # I don't have a definitive list of these. So just treat every
    # country in the world not in Eurovision as missing.
    missing = ''.join(set(co_codes.values()) - set(cols))
    hi_score = max(v for _, _, vv  in votes for v in vv)
    return "\n".join(eurovision_vote_map(co_name, cols, vv, hi_score, missing)
                    for co_name, score, vv in votes)

if __name__ == '__main__':
    # Download from: 
    # http://en.wikipedia.org/wiki/Eurovision_Song_Contest_2008
    # http://www.iso.org/iso/list-en1-semic-2.txt
    # (or use urllib.urlopen on these urls).
    print get_map_urls(open('Eurovision_Song_Contest_2008'),
                       open('list-en1-semic-2.txt'))

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;Serbia and Montenegro?&lt;/h3&gt;
&lt;p&gt;My program produced bizarre output at first: something was wrong with Serbia, and I assumed I&amp;#8217;d made an &lt;a href="http://wordaligned.org/articles/joined-output-and-the-fencepost-problem"&gt;off-by-one error&lt;/a&gt;. As I write this (2008-05-29) there &lt;a href="http://groups.google.com/group/google-chart-api/browse_thread/thread/2e821469f810241e"&gt;seems to be a problem&lt;/a&gt; with the way the google chart API handles the country code for Serbia, &amp;#8220;RS&amp;#8221;. That&amp;#8217;s why I&amp;#8217;ve substituted &amp;#8220;CS&amp;#8221;, the old code for Serbia and Montenegro &amp;#8212; a country which ceased to exist in 2006. I&amp;#8217;ll have to adjust the code as the situation (&lt;a href="http://www.google.co.uk/search?q=3166+serbia+and+montenegro"&gt;both politically and googley&lt;/a&gt;) develops, since the maps which appear on this page are served live by google.
&lt;/p&gt;

&lt;h3&gt;Terry Wogan&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m not going to draw any conclusions from these charts except to say that I never thought I&amp;#8217;d mention Wogan on this site, let alone link to the &lt;a href="http://www.telegraph.co.uk/opinion/main.jhtml?xml=/opinion/2008/05/26/do2603.xml"&gt;Telegraph&lt;/a&gt;. Eurovision voting is clearly a &lt;a href="http://www.theregister.co.uk/2008/05/06/eurovision_outrage/"&gt;sensitive topic&lt;/a&gt;. I recommend a visit to &lt;a href="http://successfulsoftware.net/2008/05/26/is-the-eurovision-song-contest-rigged/"&gt;this Andy Brice article&lt;/a&gt;, where he uses software similar to his &lt;a href="http://www.perfecttableplan.com/html/visualise_your_plan.html"&gt;wedding table planner&lt;/a&gt; to render some more detailed voting maps. The analogy of all these countries having to sit next to each other for a musical event, like grumpy inlaws at a wedding, made me laugh.
&lt;/p&gt;
&lt;p&gt;Andy Brice&amp;#8217;s pictures were produced with C++ and Qt following the same QA procedure that I used with the code for this article:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I wrote some throwaway code to generate these images in C++ and Qt over a few hours on a wet bank holiday Sunday. QA amounted to &amp;#8216;that looks about right&amp;#8217;.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;hr /&gt;

&lt;p&gt;&lt;a id="fn1" href="http://wordaligned.org/articles/eurovision-2008-charts#fn1link"&gt;[1]&lt;/a&gt; Yes, I am colour-blind!
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=LfyOmh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=LfyOmh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=BfOzwh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=BfOzwh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=Xn6Vxh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=Xn6Vxh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=uFMkJH"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=uFMkJH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/300552045" height="1" width="1"/&gt;</description>
<dc:date>2008-05-29</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/eurovision-2008-charts</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/300552045/eurovision-2008-charts</link>
<category>Python</category>
<category>Google</category>
<category>Charts</category>
<feedburner:origLink>http://wordaligned.org/articles/eurovision-2008-charts</feedburner:origLink></item>

<item>
<title>Curling for web sites</title>
<description>&lt;p&gt;I wanted information about ISO 3166-1 alpha-2 country codes. Google found me the definitive link (&lt;a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm" title="ISO 3166 country code lists"&gt;http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm&lt;/a&gt;) but clicking on it showed the ISO website to be temporarily down for maintenance.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.iso.org/error/sitedown.html" title="ISO site down page"&gt;&lt;img style="border: 2px solid orange;" src="http://wordaligned.org/images/iso-down.png" alt="ISO website out of action" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Rather than check back again every few minutes or hunt for stale information in the google cache, I got &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;bash&lt;/code&gt; to notify me when the site went live.
&lt;/p&gt;
&lt;pre&gt;
$ url=http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm
$ curl -I $url
HTTP/1.1 302 Found
Date: Tue, 27 May 2008 08:00:44 GMT
Server: BIG-IP
Location: http://www.iso.org/error/sitedown.html
Via: 1.1 www.iso.org
Connection: close
Content-Type: text/html
&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Curl -I&lt;/code&gt; fetches the page header only, which in this case uses a &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;302 status code&lt;/a&gt; to temporarily redirect clients to the &lt;code&gt;sitedown.html&lt;/code&gt; page. Using this information I wrote a simple while loop to ping the site every minute and determine when this status changed.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ http_status() { curl -I -s $1 | head -1 | cut -d " " -f 2; }
$ while [ $(http_status $url) == 302 ]; do sleep 60; done; open $url

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Open&lt;/code&gt; is an OS X thing: when the loop completes &lt;code&gt;open&lt;/code&gt; just opens the web page in a browser tab.
&lt;/p&gt;
&lt;p&gt;To run this command in the background, &lt;code&gt;&amp;amp;&lt;/code&gt; it.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ (while [ $(http_status $url) == 302 ]; do sleep 60; done; open $url)&amp;amp;
[1] 808

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, the job has a handle of &lt;code&gt;1&lt;/code&gt; and a process id of &lt;code&gt;808&lt;/code&gt;. You can recover this information using &lt;code&gt;jobs&lt;/code&gt;.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;$ jobs
[1]+  Running                 ( while [ $(http_status $url) == 302 ]; do
    sleep 300;
done; open $url ) &amp;amp;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you need to kill the job, &lt;code&gt;kill %1&lt;/code&gt; does the trick.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=HeE8Lh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=HeE8Lh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=suF6nh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=suF6nh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=7uooPh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=7uooPh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=4CuXXH"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=4CuXXH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/299358698" height="1" width="1"/&gt;</description>
<dc:date>2008-05-27</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/curling-for-web-sites</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/299358698/curling-for-web-sites</link>
<category>Shell</category>
<category>Curl</category>
<feedburner:origLink>http://wordaligned.org/articles/curling-for-web-sites</feedburner:origLink></item>

<item>
<title>Fixing Compiler Warnings the Hard Way</title>
<description>&lt;h3&gt;GCC makes a suggestion&lt;/h3&gt;
&lt;p&gt;The build server &lt;a href="http://wordaligned.org/articles/antisocial-build-orders"&gt;CC&amp;#8217;d me on an ASBO email&lt;/a&gt;. Good old GCC, grumbling about operator precedence again. But Hey! &amp;#8212; at least it had a positive suggestion to make.
&lt;/p&gt;
&lt;pre style="border: 2px solid red; background: white; font-size: 150%;"&gt;
&lt;b&gt;From:&lt;/b&gt; buildmaster@example.com
&lt;b&gt;To:&lt;/b&gt; lem.e.tweakit@example.com
&lt;b&gt;Cc:&lt;/b&gt; developers@example.com
&lt;b&gt;Subject:&lt;/b&gt; Broken build
------------------------------------
&lt;span style="font-weight: 900; font-variant: small-caps; font-size: 36px;"&gt;Anti Social Build Order&lt;/span&gt;
&lt;b&gt;Version:&lt;/b&gt; svn://svnserver/trunk@999
&lt;b&gt;Platform:&lt;/b&gt; Linux, GCC 4.0.1
&lt;b&gt;Build Log:&lt;/b&gt; 
....
Warning: suggest parentheses around arithmetic
in operand of ^
&lt;/pre&gt;

&lt;p&gt;I looked at the code. Here&amp;#8217;s a much simplified version which generates the same warning.
&lt;/p&gt;
&lt;span id="continue-reading"/&gt;

&lt;pre&gt;
void
unpack(unsigned char const * bits, int n_bits,
       unsigned char * buf)
{
    unsigned char bit, byte, pos;
    int b;
    
    for (b = 0; b != n_bits; ++b)
    {
        byte = bits[b / 8];
        pos = 7 - (b % 8);
        &lt;strong&gt;bit = byte &amp;amp; 2^pos;&lt;/strong&gt;
        buf[b] = bit == 0 ? 0 : 255;
    }
}
&lt;/pre&gt;

&lt;p&gt;When compiling this function GCC warns about the line in bold type:
&lt;/p&gt;
&lt;pre&gt;
$ gcc -Wall -c unpack_bits.c 
unpack_bits.c: In function `unpack':
unpack_bits.c:12: warning: suggest parentheses around 
             arithmetic in operand of ^
&lt;/pre&gt;


&lt;h3&gt;Setting a precedent&lt;/h3&gt;
&lt;p&gt;Needless to say, the actual offending code was buried in a longer function, indented more deeply, and with a few more &lt;a href="http://c2.com/cgi/wiki?ThreeStarProgrammer"&gt;indirections&lt;/a&gt; &amp;#8212; so it was indeed tempting to take GCC&amp;#8217;s advice and whack in a couple of brackets. Clearly the author &lt;strong&gt;meant&lt;/strong&gt; to write:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;bit = byte &amp;amp; (2^pos);

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Why else omit spaces around the &lt;code&gt;^&lt;/code&gt;?
&lt;/p&gt;
&lt;p&gt;Fortunately I live by my own rule, to &lt;a href="http://wordaligned.org/articles/brackets-off"&gt;avoid unnecessary parentheses&lt;/a&gt;, so I wasn&amp;#8217;t about to add any here without asking why. Worse than my stubborn principles, &lt;code&gt;^&lt;/code&gt;, the exclusive or operator, has &lt;strong&gt;lower&lt;/strong&gt; precedence than bitwise and, &lt;code&gt;&amp;amp;&lt;/code&gt;, so to keep GCC happy and retain the original behaviour we&amp;#8217;d have to write:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;bit = (byte &amp;amp; 2) ^ pos;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This last expression looks very bizarre. Had it ever been exercised?
&lt;/p&gt;
&lt;p&gt;GCC was right, the code was wrong, but its diagnostic showed the wrong way to right things. On this occasion GCC should have been proscriptive, not prescriptive, and left the fix in the hands of the programmer&lt;a id="fn1link" href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#footnote1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;Don&amp;#8217;t mix bits and arithmetic&lt;/h3&gt;
&lt;pre style="color:#00cc00;background:#000;float:right;margin-left:4px;"&gt;0000 0000 5589 e58b 5508 89d0 d1e8 2555
5555 5529 c289 d0c1 e802 2533 3333 3381
e233 3333 3301 d089 c2c1 ea04 01d0 250f
0f0f 0f89 c2c1 ea08 01d0 25ff 00ff 0089
c2c1 ea10 01d0 25ff ff00 005d c300 0000
5555 5555 3333 3333 0f0f 0f0f ff00 ff00&lt;/pre&gt;

&lt;p&gt;My personal rule of thumb is to avoid mixing bitwise and arithmetic operations. Although integral types support both kinds of operation, it generally feels like a type-mismatch to combine them in a single expression. An array of bits isn&amp;#8217;t the same as a number, and vice-versa.
&lt;/p&gt;
&lt;p&gt;Of course there are some treasured &lt;a href="http://graphics.stanford.edu/~seander/bithacks.html"&gt;bit-twiddling tricks&lt;/a&gt; which exploit the mapping between binary arithmetic and machine level register operations. So we can, for example, calculate &lt;code&gt;2&lt;/code&gt; raised to the power of &lt;code&gt;19&lt;/code&gt; with a simple left-shift, &lt;code&gt;1 &amp;lt;&amp;lt; 19&lt;/code&gt;, or test if &lt;code&gt;v&lt;/code&gt; is a power of &lt;code&gt;2&lt;/code&gt; with &lt;code&gt;!(v &amp;amp; (v - 1)) &amp;amp;&amp;amp; v&lt;/code&gt;. I&amp;#8217;m not suggesting we blacklist these ingenious hacks &amp;#8212; in fact, anyone off to an interview for a programming job with an embedded systems company might do well to study them &amp;#8212; but I would say their use requires thorough documentation.
&lt;/p&gt;
&lt;p&gt;On occasion, then, bitwise operations may legitimately be used for fast arithmetic; but using arithmetic to pack bits is rarely necessary. This line of code is probably wrong&lt;a id="fn2link" href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#footnote2"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;r = h &amp;lt;&amp;lt; 4 + 1;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The programmer probably intended the (bitwise) shift to happen before the (arithmetic) addition, like this.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;r = (h &amp;lt;&amp;lt; 4) + 1;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If we stick to bitwise operations, things become clear. I&amp;#8217;ve written the 1 in hexadecimal as a hint it&amp;#8217;s being used as a bit pattern &amp;#8212; sadly there&amp;#8217;s no way of writing a binary literal directly in C.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;r = h &amp;lt;&amp;lt; 4 | 0x1;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Anyway, the problem line in &lt;code&gt;unpack()&lt;/code&gt; adheres to my rule of thumb: &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;^&lt;/code&gt; are indeed both bitwise operations. But after some puzzling I realised the author of the code intended &lt;code&gt;2^pos&lt;/code&gt; to mean &lt;code&gt;2&lt;/code&gt; to the power of &lt;code&gt;pos&lt;/code&gt;, &lt;strong&gt;not for its arithmetic value, but for its bit pattern&lt;/strong&gt; &amp;#8212; which, as every programmer knows, is a &lt;code&gt;1&lt;/code&gt; followed by pos &lt;code&gt;0&lt;/code&gt;s. That is, a &lt;code&gt;1&lt;/code&gt; left shifted &lt;code&gt;pos&lt;/code&gt; times.
&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what I thought the fix should be. Note, incidentally, that I&amp;#8217;ve used &lt;code&gt;~0&lt;/code&gt; rather than &lt;code&gt;255&lt;/code&gt;, because it clearly says &amp;#8220;set every bit&amp;#8221;. I&amp;#8217;m also using unsigned integers throughout &amp;#8212; always a good idea when working with bits. Some programmers might prefer to parenthesise the expression &lt;code&gt;byte &amp;amp; 1 &amp;lt;&amp;lt; pos&lt;/code&gt;, &lt;a href="http://wordaligned.org/articles/brackets-off"&gt;but I prefer the form shown&lt;/a&gt;: it&amp;#8217;s easy enough to remember that &lt;code&gt;&amp;amp;&lt;/code&gt; groups with the logical operators and &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; with the (higher precedence) arithmetic ones.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;void
unpack(unsigned char const * bits, unsigned n_bits,
       unsigned char * buf)
{
    unsigned char bit, byte;
    unsigned b, pos;
    
    for (b = 0; b != n_bits; ++b)
    {
        byte = bits[b / 8];
        pos = 7 - b % 8;
        bit = byte &amp;amp; 1 &amp;lt;&amp;lt; pos;
        buf[b] = bit == 0 ? 0 : ~0;
    }
}

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Despite the absence of documentation, this is now at least a coherent function. It&amp;#8217;s a &amp;#8220;biterator&amp;#8221; which steps through a collection of bits (packed into bytes, the smallest memory units C offers). Each time it encounters a set/clear bit, it sets/clears all the bits in the next byte in the output buffer. That is, it expands each bit value to fill a whole byte.
&lt;/p&gt;
&lt;p&gt;This is exactly the kind of function which is surprisingly fiddly to write but simple to unit test. As already mentioned, though, the function didn&amp;#8217;t actually exist in the form shown, and the tests were all at the module level. The responsible way for me to proceed was to create a module test which exposed the defect, then make my candidate fix, confirm it did indeed fix the defect, then check the change in.
&lt;/p&gt;

&lt;h3&gt;Unit Test&lt;/h3&gt;
&lt;p&gt;Here&amp;#8217;s how simple a unit test for &lt;code&gt;unpack()&lt;/code&gt; could be. It may be longer than the function it&amp;#8217;s testing, but it&amp;#8217;s less complex. And with just a couple of test cases, it manages to cover several interesting corners of the functionality. Better still, it passes&lt;a id="fn3link" href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#footnote3"&gt;&lt;sup&gt;[3]&lt;/sup&gt;&lt;/a&gt;!
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;void
test_unpack()
{
    // Start with a varied bit-pattern.
    // Ensure each byte differs from its reversed self.
    unsigned char const bits[2] = 
    {
        1 &amp;lt;&amp;lt; 7 | 1 &amp;lt;&amp;lt; 5 | 1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 0, // 10110001 binary
        1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5 | 1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 0, // 01101001 binary
    };
    // The expected output expands bits to bytes (0 =&amp;gt; 0, 1 =&amp;gt; ~0)
    unsigned char expected[2 * 8] = 
    {
        ~0, 0, ~0, ~0, 0, 0, 0, ~0,
        0, ~0, ~0, 0, ~0, 0, 0, ~0
    };
    unsigned char buf[3 * 8] = { 0 };
    unsigned char buf_copy[3 * 8] = { 0 };
    
    size_t const buf_size = sizeof(buf);
    
    // Fill the buffer with a pattern of 1s and 0s.
    // Unpack nothing and check nothing changes.
    memset(buf, 0xa5, buf_size);
    memcpy(buf_copy, buf, buf_size);
    unpack(bits, 0, buf);
    assert(memcmp(buf, buf_copy, buf_size) == 0);
    
    // Unpack some of the bits and check the results.
    // Also check the remainder of the buffer is undamaged.
    unpack(bits, 13, buf);
    assert(memcmp(buf, expected, 13) == 0);
    assert(memcmp(buf + 13, buf_copy + 13, buf_size - 13) == 0);
}

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is white-box testing: the test knows enough about the implementation of &lt;code&gt;unpack()&lt;/code&gt; to expose potential problems. In this case, there&amp;#8217;s something unusual about the way the &lt;code&gt;pos&lt;/code&gt; counter goes down as the bit counter &lt;code&gt;b&lt;/code&gt; goes up, so we make sure that the bits we&amp;#8217;re unpacking form asymmetric patterns.
&lt;/p&gt;

&lt;h3&gt;Refactoring&lt;/h3&gt;
&lt;p&gt;Should we extract this tested &lt;code&gt;unpack()&lt;/code&gt; function from its surrounding, larger, more complex function? Is it safe to do so? Have we time to spend making changes with no externally visible results? Should we tweak &lt;code&gt;unpack()&lt;/code&gt; for efficiency (after all, it doesn&amp;#8217;t need to use the division and modulus operators each time round the loop)?
&lt;/p&gt;
&lt;div class="amazon"&gt;&lt;a href="http://www.amazon.com/gp/product/0131177052?ie=UTF8&amp;amp;tag=wordalig-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0131177052"&gt;&lt;img src="http://wordaligned.org/images/working-effectively-with-legacy-code.jpg" alt="Working Effectively with Legacy Code cover"/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;These are important questions. eXtreme Programmers &lt;a href="http://www.extremeprogramming.org/rules/refactor.html"&gt;refactor mercilessly&lt;/a&gt;, confident their extensive test frameworks will provide a safety net. Java programmers select the code block in their IDE then click the &amp;#8220;extract method&amp;#8221; button. C and C++ programmers have less advanced tools, but Michael Feathers&amp;#8217; &lt;a href="http://www.amazon.com/gp/product/0131177052?ie=UTF8&amp;amp;amp;tag=wordalig-20&amp;amp;amp;linkCode=as2&amp;amp;amp;camp=1789&amp;amp;amp;creative=9325&amp;amp;amp;creativeASIN=0131177052"&gt;&amp;#8220;Working Effectively with Legacy Code&amp;#8221;&lt;/a&gt; offers practical advice on how to transform code safely &amp;#8212; that is, how to put it under test.
&lt;/p&gt;
&lt;p&gt;In the real world, we judge each case on merit. A &lt;a href="http://wordaligned.org/articles/antisocial-build-orders"&gt;nag email&lt;/a&gt; from the build server shouldn&amp;#8217;t trigger mass refactoring, even if the test infrastructure is in place. I think Feathers is right though, that poorly tested code is on its way to becoming legacy code: hard to adapt, unpleasant to work with, and a drag on continuing development.
&lt;/p&gt;

&lt;h3&gt;Lessons&lt;/h3&gt;
&lt;p&gt;This new story repeats the same old lessons, and I think they bear repeating:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Set up a build server. Listen to it.
 &lt;/li&gt;

 &lt;li&gt;
     Compile on multiple platforms.
 &lt;/li&gt;

 &lt;li&gt;
     Think! Compilers are concerned with syntax, not semantics. A C compiler reads your code in order to rewrite it for the machine&amp;#8217;s benefit; understanding the code is your job.
 &lt;/li&gt;

 &lt;li&gt;
     Write small functions. Unit test them. 
 &lt;/li&gt;

 &lt;li&gt;
     Integers and bit arrays are different.
 &lt;/li&gt;

 &lt;li&gt;
     Take care when using bitwise operations as arithmetic shortcuts.
 &lt;/li&gt;

 &lt;li&gt;
     Avoid using arithmetic for bit packing.
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oh, and in C, don&amp;#8217;t mistake &lt;code&gt;^&lt;/code&gt; for exponentiation!
&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;a href="http://accu.org" title="ACCU: professionalism in programming"&gt;&lt;img src="http://accu.org/content/images/buttonl_88x31.gif" style="float:right" width="88" height="31" alt="ACCU: professionalism in programming"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;This article was originally published in &lt;a href="http://accu.org/index.php/aboutus/aboutjournals"&gt;CVu&lt;/a&gt;, a print journal for ACCU members, and I would like to thank all at CVu for their help with it.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#fn1link" id="footnote1"&gt;[1]&lt;/a&gt; I&amp;#8217;m not complaining about GCC which did an outstanding job of flagging a genuine problem in perfectly well-defined and valid code. The other compiler frequently used on this project, MSVC V8.0, compiles this cleanly, at the same time warning standard C string functions are unsafe and &lt;strong&gt;deprecated&lt;/strong&gt;!
&lt;/p&gt;
&lt;div class="amazon"&gt;&lt;a href="http://www.amazon.com/gp/product/0201179288?ie=UTF8&amp;amp;tag=wordalig-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0201179288"&gt;&lt;img  src="http://wordaligned.org/images/books/c-traps-and-pitfalls.jpg" alt="Book cover"/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#fn2link" id="footnote2"&gt;[2]&lt;/a&gt; I&amp;#8217;ve taken this example directly from Andrew Koenig&amp;#8217;s &lt;a href="http://www.amazon.com/gp/product/0201179288?ie=UTF8&amp;amp;amp;tag=wordalig-20&amp;amp;amp;linkCode=as2&amp;amp;amp;camp=1789&amp;amp;amp;creative=9325&amp;amp;amp;creativeASIN=0201179288"&gt;&amp;#8220;C Traps and Pitfalls&amp;#8221;&lt;/a&gt;. This is a nice little book which expands on the ideas presented in a &lt;a href="http://www.literateprogramming.com/ctraps.pdf"&gt;paper of the same name [PDF]&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way#fn3link" id="footnote3"&gt;[3]&lt;/a&gt; One thing I recommend, though, is to temporarily reverse the logic in the assertions and check they then fail. Unit test frameworks often provide hooks to do this reversed-result test, which confirms the test cases are actually being run.
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=9Gy2th"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=9Gy2th" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=Ermj3h"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=Ermj3h" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=tpMhSh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=tpMhSh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=SxbndH"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=SxbndH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/294503989" height="1" width="1"/&gt;</description>
<dc:date>2008-05-20</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/294503989/fixing-compiler-warnings-the-hard-way</link>
<category>C</category>
<category>Build</category>
<category>ACCU</category>
<feedburner:origLink>http://wordaligned.org/articles/fixing-compiler-warnings-the-hard-way</feedburner:origLink></item>

<item>
<title>Accidental Emacs</title>
<description>&lt;div class="toc"&gt;
&lt;h2&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocemacs-the-operating-system" name="toc0" id="toc0"&gt;Emacs the Operating System&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocwindow-management" name="toc1" id="toc1"&gt;Window Management&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocremote-editing" name="toc2" id="toc2"&gt;Remote Editing&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocbinary-editing" name="toc3" id="toc3"&gt;Binary Editing&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocarchive-editing" name="toc4" id="toc4"&gt;Archive Editing&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocdired-mode" name="toc5" id="toc5"&gt;Dired Mode&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tockeyboard-macros" name="toc6" id="toc6"&gt;Keyboard Macros&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocan-ide-for-dynamic-languages" name="toc7" id="toc7"&gt;An IDE for Dynamic Languages&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toccode-completion-for-cheats" name="toc8" id="toc8"&gt;Code completion for cheats&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocemail-surfing-media-editing" name="toc9" id="toc9"&gt;Email, Surfing, Media Editing&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#tocnotes" name="toc10" id="toc10"&gt;Notes&lt;/a&gt;
 &lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href="http://homepage.mac.com/zenitani/emacs-e.html" title="Carbon Emacs for Mac OS X page"&gt;&lt;img style="float:left;" src="http://wordaligned.org/images/carbon-emacs-doc.png" alt="Carbon Emacs"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Nice to see Emacs &lt;a href="http://www.informit.com/articles/article.aspx?p=1193856" title="After pencil and paper, Donald Knuth likes Emacs"&gt;getting&lt;/a&gt; a &lt;a href="http://wrds.wordpress.com/2007/05/18/ten-mostly-false-ideas-about-emacs/" title="Alexandru Laz&amp;#259;r on Emacs misconceptions"&gt;bit&lt;/a&gt; of &lt;a href="http://steve-yegge.blogspot.com/2008/03/js2-mode-new-javascript-mode-for-emacs.html" title="Steve Yegge writes elisp enabling Emacs customisation using JavaScript."&gt;press&lt;/a&gt; &lt;a href="http://www.johndcook.com/blog/2008/04/27/one-program-to-rule-them-all/" title="John D. Cook discusses life in a software application"&gt;recently&lt;/a&gt;. I&amp;#8217;ve used it for almost 20 years now and it dominates my time at the keyboard. It isn&amp;#8217;t perfect and I&amp;#8217;m reluctant to recommend it but I wouldn&amp;#8217;t want to be without it. Let me explain.
&lt;/p&gt;
&lt;p&gt;The best thing about &lt;a href="http://www.gnu.org/software/emacs/"&gt;Emacs&lt;/a&gt; is that it can do &lt;strong&gt;everything&lt;/strong&gt; (including the things it can&amp;#8217;t do yet). The worst thing about Emacs is finding out how it does &lt;strong&gt;anything&lt;/strong&gt;. I wouldn&amp;#8217;t call it discoverable. In fact, on several occasions, I&amp;#8217;ve learned about Emacs by accident: you press the wrong key combination (easy to do when you&amp;#8217;re holding down a couple of keys and stretching for a third) and, look, something interesting happens!
&lt;/p&gt;
&lt;p&gt;The rest of this article describes a few of these happy accidents: modes I never knew about and tricks I wish I&amp;#8217;d learned earlier.
&lt;/p&gt;
&lt;span id="continue-reading"/&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc0" name="tocemacs-the-operating-system" id="tocemacs-the-operating-system"&gt;Emacs the Operating System&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://wordaligned.org/images/welcome-to-emacs.png" title="Emacs splash screen"&gt;&lt;img style="float:right;padding-left:10px;" src="http://wordaligned.org/images/welcome-to-emacs.jpg" alt="Emacs splash screen"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Whenever I see the Emacs splash screen (click on the graphic for a close-up) I&amp;#8217;m amazed anyone ever gets past it. Computer users want instant gratification and a familiar interface &amp;#8212; thus the encouraging tip:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;You can do basic editing with the menu bar and scroll bar using the mouse.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Unhappily the rest of the screen discredits this friendly proposition. Where are the menu and scroll bars&lt;a id="fn1link" href="http://wordaligned.org/articles/accidental-emacs#fn1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;, and what&amp;#8217;s with all the &lt;code&gt;Control&lt;/code&gt; this and &lt;code&gt;Meta&lt;/code&gt; that? If the scratchy artwork and bizarre mix of font styles don&amp;#8217;t put new users off, the remaining content surely will, with its dark warnings about sessions crashing and how to recover&lt;a id="fn2link" href="http://wordaligned.org/articles/accidental-emacs#fn2"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Best of all, though, is the opening proposition:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;GNU Emacs is one component of the GNU operating system
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;which I read as a straight-faced rebuttal of the old gag:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;It is a common joke, both among fans and detractors of Emacs, to describe it as an operating system masquerading as an editor&lt;a id="fn3link" href="http://wordaligned.org/articles/accidental-emacs#fn3"&gt;&lt;sup&gt;[3]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;GNU hasn&amp;#8217;t quite become an operating system but it does supply most of the standard Unix tools and Emacs works beautifully with them &amp;#8212; even on (Cyg-)Windows. &lt;code&gt;META-!&lt;/code&gt; executes a single shell command, for example. &lt;code&gt;META-|&lt;/code&gt; executes a shell command on the current region and puts the output in a temporary buffer. &lt;code&gt;META-X grep&lt;/code&gt; and &lt;code&gt;META-X grep-find&lt;/code&gt; build search on top of &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt;. &lt;code&gt;META-X shell&lt;/code&gt; opens up a shell window within Emacs, meaning you can run shell commands and process their output using the standard editor commands. Emacs info is a better man page browser than info. And on on.
&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;OS integration examples&lt;/div&gt;

&lt;pre class="prettyprint"&gt;META-!
META-|
META-X grep
META-X grep-find
META-X shell

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When Emacs shells out to external tools their execution is never hidden from you, so you lose none of the power of these tools. The converse of this also holds: if you don&amp;#8217;t know how to use &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt;, even basic search commands in Emacs will seem &lt;a href="http://wordaligned.org/articles/ignoring-svn-directories"&gt;cryptic and hard to customise&lt;/a&gt;. Emacs is, above all else, customisable. In fact, most of Emacs is customisation, and you&amp;#8217;ll soon give up on it if you can&amp;#8217;t accept this&lt;a id="fn4link" href="http://wordaligned.org/articles/accidental-emacs#fn4"&gt;&lt;sup&gt;[4]&lt;/sup&gt;&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc1" name="tocwindow-management" id="tocwindow-management"&gt;Window Management&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Over at Coding Horror, Jeff Atwood talks about &lt;a href="http://www.codinghorror.com/blog/archives/000928.html"&gt;&amp;#8220;large display paradox&amp;#8221;&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;One of the &lt;i&gt;advantages&lt;/i&gt; of small monitors, ironically, is that &lt;b&gt;because they&amp;#8217;re small, they nudge users into a simpler, windowless method of working&lt;/b&gt;. Instead of wasting time sizing, moving, and z-ordering windows, users only need to deal with one maximized window at a time. They can flip between maximized applications in much the same way they change channels on the television. But once your display gets to 1600 x 1200 or beyond, this easy one-app-per-display model isn&amp;#8217;t feasible any more &amp;#8230;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s the &lt;b&gt;large display paradox&lt;/b&gt;. Having all that space can make you &lt;i&gt;less&lt;/i&gt; productive due to all the window manipulation excise you have to deal with to make effective use of it.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Well, I reckon Emacs has this problem cracked. On a small screen you can use a single maximised window: &lt;code&gt;CTRL-X B&lt;/code&gt; switches editor buffers (a bit like tabbed browsing) and &lt;code&gt;CTRl-X CTRL-B&lt;/code&gt; gets you a buffer management window. On a large screen &lt;code&gt;CTRL-X 3&lt;/code&gt; splits the enclosing window vertically, and &lt;code&gt;CTRL-X 2&lt;/code&gt; splits it horizontally. Repeat these commands to slice up your work space. &lt;code&gt;CTRL-X 1&lt;/code&gt; gets you back to a single window. The same commands work when you haven&amp;#8217;t got a proper windowing environment &amp;#8212; on a stripped down server for example, or one which hasn&amp;#8217;t booted properly. Very handy! 
&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;Buffer and window management&lt;/div&gt;

&lt;pre class="prettyprint"&gt;CTRL-X B
CTRl-X CTRL-B
CTRL-X 3
CTRL-X 2
CTRL-X 1

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc2" name="tocremote-editing" id="tocremote-editing"&gt;Remote Editing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If, for example, the stripped down server discussed in the previous section allows SSH access or similar, you don&amp;#8217;t need to install or run Emacs natively. Just use &lt;a href="http://www.gnu.org/software/tramp"&gt;tramp mode&lt;/a&gt; (&lt;strong&gt;T&lt;/strong&gt;ransparent &lt;strong&gt;R&lt;/strong&gt;emote file &lt;strong&gt;A&lt;/strong&gt;ccess, &lt;strong&gt;M&lt;/strong&gt;ultiple &lt;strong&gt;P&lt;/strong&gt;rotocol). Quoting from the &lt;a href="http://www.gnu.org/software/tramp"&gt;manual&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;To access the file &lt;code&gt;localname&lt;/code&gt; on the remote machine &lt;code&gt;machine&lt;/code&gt; you would specify the filename /machine:localname.
   &amp;#8230;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;You can specify protocol (ftp, rsh, smb etc.) and user name too:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;So, to connect to the machine &lt;code&gt;melancholia&lt;/code&gt; as &lt;code&gt;daniel&lt;/code&gt;, using the &lt;code&gt;ssh&lt;/code&gt; method to transfer files, and edit &lt;code&gt;.emacs&lt;/code&gt; in my home directory I would specify the filename &lt;code&gt;/ssh:daniel@melancholia:.emacs&lt;/code&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;As usual, there are plenty of configuration options. I haven&amp;#8217;t touched any of them. Tramp mode just works: if I can access a remote machine, I can edit files on it and transfer files to and from it just as if it were local.
&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;Remote editing example&lt;/div&gt;

&lt;pre class="prettyprint"&gt;Find file: /ssh:daniel@melancholia:.emacs

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc3" name="tocbinary-editing" id="tocbinary-editing"&gt;Binary Editing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Programmers often need to view the raw bytes packed into a file, and occasionally to edit these byte values. That&amp;#8217;s what &lt;a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Editing-Binary-Files.html"&gt;Hexl mode&lt;/a&gt; is for. &lt;code&gt;META-X hexl-find-file&lt;/code&gt; opens a file in this mode and &lt;code&gt;META-X hexl-mode&lt;/code&gt; switches a buffer to this mode.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;META-X hexl-find-file
META-X hexl-mode

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc4" name="tocarchive-editing" id="tocarchive-editing"&gt;Archive Editing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Did you know that Emacs can work on &lt;code&gt;.zip&lt;/code&gt;, &lt;code&gt;.tar&lt;/code&gt;, &lt;code&gt;.tgz&lt;/code&gt; etc archives directly? I found out when I opened one by accident: Emacs presents you with a view of the archive and you can browse files, edit them, rename them, remove them from the archive, and save the modified archive without ever having to manually extract it. No special knowledge required: it just works, a bit like &lt;code&gt;dired-mode&lt;/code&gt;.
&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc5" name="tocdired-mode" id="tocdired-mode"&gt;Dired Mode&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you open a directory with Emacs it puts you in &lt;a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html"&gt;dired-mode&lt;/a&gt;, the Emacs take on Windows Explorer, OS X Finder and so on. Many of the Emacs users I know don&amp;#8217;t use this mode, preferring either the native system file manager or plain old terminal windows for file operations (copy, move, list, &amp;#8230;) but I use it all the time and it&amp;#8217;s led to many happy Emacs accidents.
&lt;/p&gt;
&lt;p&gt;As an example, suppose you have a directory full of files with &lt;code&gt;names-like-this&lt;/code&gt;, and you want to rename all the files to use &lt;code&gt;names_like_this&lt;/code&gt; instead. Just switch to editable dired mode, run a standard search and replace to swap hyphens for underscores, then save the directory.
&lt;/p&gt;
&lt;p&gt;As a second example, suppose you want to view thumbnails of all the .png files in a directory. Use a pattern match &lt;code&gt;% m png&lt;/code&gt; to &amp;#8220;mark&amp;#8221; them (i.e. select them) then &lt;code&gt;CTRL-t d&lt;/code&gt; to display them. Now you can visit the thumbnails, removing, renaming, copying the associated files.
&lt;/p&gt;
&lt;p&gt;Cryptic, yes, but powerful, and no mouse required &amp;#8212; handy for laptops.
&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc6" name="tockeyboard-macros" id="tockeyboard-macros"&gt;Keyboard Macros&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can hear when someone sitting nearby doesn&amp;#8217;t know about editor macros or is using an editor which doesn&amp;#8217;t support them. The tedious repetition of the same sequence of keystrokes grows audible.
&lt;/p&gt;
&lt;p&gt;In Emacs you start recording a &lt;a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/Keyboard-Macros.html"&gt;keyboard macro&lt;/a&gt; with &lt;code&gt;CTRL-X (&lt;/code&gt; and finish recording with &lt;code&gt;CTRL-X )&lt;/code&gt;. Everything typed between these bracketed commands has been recorded as a keyboard macro which &lt;code&gt;CTRL-X e&lt;/code&gt; executes and then &lt;code&gt;e&lt;/code&gt; repeats. If typing all those &lt;code&gt;eeeeee&lt;/code&gt;&amp;#8217;s is repetitive, supply a repeat count. A repeat count of 0 processes the whole buffer, and is often what&amp;#8217;s wanted.
&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s far more to keyboard macros but this basic use alone will save your fingers and your sanity.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;CTRL-X (
CTRL-X )
CTRL-X e

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc7" name="tocan-ide-for-dynamic-languages" id="tocan-ide-for-dynamic-languages"&gt;An IDE for Dynamic Languages&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Emacs has a proven architecture: a compact, stable core which is dynamically configured by a huge library of scripts. These scripts are written in elisp. You can edit, reload and add to them at any point, without the need to &lt;a href="http://steve-yegge.blogspot.com/2007/01/pinocchio-problem.html"&gt;reboot the main application&lt;/a&gt;. Rebooting wouldn&amp;#8217;t be such a big thing, though &amp;#8212; Emacs starts up in less than a couple of seconds &amp;#8212; what&amp;#8217;s important is that Emacs is dynamic to the core.
&lt;/p&gt;
&lt;p&gt;So it&amp;#8217;s not surprising Emacs has great modes for dynamic languages like Python, Ruby, Scheme. Here&amp;#8217;s how to develop Python code using Emacs:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Pull up a full-screen window
 &lt;/li&gt;

 &lt;li&gt;
     Split the window vertically
 &lt;/li&gt;

 &lt;li&gt;
     Use one side for the code you&amp;#8217;re working on
 &lt;/li&gt;

 &lt;li&gt;
     Use the other side to run an interpreted session
 &lt;/li&gt;

 &lt;li&gt;
     Switch sides as desired
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You continually select regions of code to execute. You step
   into the interpreter and use the Python &lt;code&gt;help&lt;/code&gt; command to get help on
   modules and functions &amp;#8212; including the ones you&amp;#8217;re creating right now.
   You rework a function in one window then exercise it in the other. You
   sketch experimental code, run it, rub it out.
&lt;/p&gt;
&lt;p&gt;The same technique works for Scheme and Ruby, and is likely to work for any other dynamic language. The gap between writing and running code disappears.
&lt;/p&gt;
&lt;p&gt;As computers grow more powerful, specialised programmers&amp;#8217; IDEs do what they can to support this style of working for compiled languages. I understand Eclipse parses, compiles, and executes Java code as you write it, and it&amp;#8217;s certainly an impressive piece of software. I&amp;#8217;d be interested to know how it fares with C++.
&lt;/p&gt;
&lt;p&gt;Emacs also works well enough with compiled languages. I&amp;#8217;ve heard Make described as &lt;a href="http://en.wikipedia.org/wiki/REPL"&gt;REPL&lt;/a&gt; for compiled languages, and &lt;code&gt;make -k&lt;/code&gt; is the default Emacs compile command. The usual IDE things are available. For more interactive probing of a compiled executable, &lt;code&gt;META-X gdb&lt;/code&gt; is about as good an interface to GDB as I&amp;#8217;ve seen. But I can&amp;#8217;t (for example) imagine Emacs persuading anyone to dispense with Visual Studio for .Net development.
&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc8" name="toccode-completion-for-cheats" id="toccode-completion-for-cheats"&gt;Code completion for cheats&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This article cherry-picks a few Emacs modes you may not have discovered which I find invaluable. I haven&amp;#8217;t bothered listing the basics of how to open or close files, without which you won&amp;#8217;t get anywhere. One basic command I &lt;strong&gt;do&lt;/strong&gt; want to mention is &lt;code&gt;META-/&lt;/code&gt;, which dynamically expands whatever you&amp;#8217;re typing whatever mode you&amp;#8217;re in. I think of it as code completion for cheats, since it doesn&amp;#8217;t parse any source code and it works equally well on any type of file type. It&amp;#8217;s as useful as shell TAB-completion and I discovered it by accident.
&lt;/p&gt;

&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc9" name="tocemail-surfing-media-editing" id="tocemail-surfing-media-editing"&gt;Email, Surfing, Media Editing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can&amp;#8217;t edit photo, video or audio content in Emacs (perhaps I should say I don&amp;#8217;t know of an Emacs mode for doing so&lt;a id="fn5link" href="http://wordaligned.org/articles/accidental-emacs#fn5"&gt;&lt;sup&gt;[5]&lt;/sup&gt;&lt;/a&gt;). I don&amp;#8217;t use Emacs for spreadsheets or other &amp;#8220;office&amp;#8221; documents. You can use Emacs for ascii-art (&lt;a href="http://www.cinsk.org/emacs/emacs-artist.html"&gt;and here&amp;#8217;s a great flash animation showing someone do just that&lt;/a&gt;) but ascii-art doesn&amp;#8217;t look much good outside source code.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://homepage.mac.com/zenitani/emacs-e.html" title="Carbon Emacs for Mac OS X page"&gt;&lt;img style="float:left;" src="http://wordaligned.org/images/carbon-emacs.png" alt="Carbon Emacs"/&gt;&lt;/a&gt;
   &lt;a href="http://www.mozilla.com/firefox/" title="Firefox home page"&gt;&lt;img style="float:right;" src="http://wordaligned.org/images/firefox.png" alt="Firefox logo"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Hardcore Emacs users swear by their editor as an email client and even use it as a web browser. I prefer the comfort of my second most used application, &lt;a href="http://www.mozilla.com/firefox/"&gt;Firefox&lt;/a&gt;. Come to think of it, Firefox adopts a lot of what&amp;#8217;s good about Emacs: the tabbed window, for example, which reinvents multiple buffers for the web browser; the clean, simple look&lt;a id="fn6link" href="http://wordaligned.org/articles/accidental-emacs#fn6"&gt;&lt;sup&gt;[6]&lt;/sup&gt;&lt;/a&gt;; the extensible architecture.
&lt;/p&gt;
&lt;p&gt;Funnily enough, you &lt;strong&gt;can&lt;/strong&gt; work with photo, video and audio using Firefox; and boring old online office suites have been news for a long while. Amazingly, you can continue to edit your rich media content even if you switch to Internet Explorer, without the need to relearn anything; a transition which puts the &lt;a href="http://en.wikipedia.org/wiki/Editor_war"&gt;Vi/Emacs wars&lt;/a&gt; into perspective. Could the web browser be the one true editor of the future?
&lt;/p&gt;
&lt;hr /&gt;


&lt;h3&gt;&lt;a href="http://wordaligned.org/articles/accidental-emacs#toc10" name="tocnotes" id="tocnotes"&gt;Notes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My thanks to &lt;a href="http://www.iwebthereforeiam.com/"&gt;Hugh Brown&lt;/a&gt; for pointing out a couple of errors with the original version of this article.
&lt;/p&gt;
&lt;p&gt;&lt;a id="fn1" href="http://wordaligned.org/articles/accidental-emacs#fn1link"&gt;[1]&lt;/a&gt; OK, so my &lt;code&gt;.emacs&lt;/code&gt; disables the scroll bar and menu bar before this splash screen appears, but telling people what their mouse is for hardly seems necessary.
&lt;/p&gt;
&lt;p&gt;&lt;a id="fn2" href="http://wordaligned.org/articles/accidental-emacs#fn2link"&gt;[2]&lt;/a&gt; I can&amp;#8217;t remember when Emacs last crashed on me. It&amp;#8217;s one of the three applications I auto-start on login and I usually leave it running until I shutdown. On occasion I&amp;#8217;ve forced it to quit but this has always been down to my own error, for example coding and executing (within Emacs) a tight loop.
&lt;/p&gt;
&lt;div class="amazon"&gt;&lt;a href="http://www.amazon.com/gp/product/0131429019?ie=UTF8&amp;amp;tag=wordalig-20"&gt;&lt;img src="http://wordaligned.org/images/books/taoup.jpg" alt="The Art of Unix Programming"/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;a id="fn3" href="http://wordaligned.org/articles/accidental-emacs#fn3link"&gt;[3]&lt;/a&gt; &lt;a href="http://catb.org/~esr/writings/taoup/html/ch13s02.html#emacs_editing"&gt;Quoted&lt;/a&gt; from Eric S. Raymond&amp;#8217;s excellent book &lt;a href="http://catb.org/~esr/writings/taoup/"&gt;&amp;#8220;The Art of Unix Programming&amp;#8221;&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;&lt;a id="fn4" href="http://wordaligned.org/articles/accidental-emacs#fn4link"&gt;[4]&lt;/a&gt; In &lt;a href="http://catb.org/~esr/writings/taoup/"&gt;&amp;#8220;The Art of Unix Programming&amp;#8221;&lt;/a&gt; Eric S. Raymond discusses the question: &lt;a href="http://catb.org/~esr/writings/taoup/html/ch13s03.html#id2967765"&gt;&amp;#8220;Is Emacs an Argument against the Unix Tradition?&amp;#8221;&lt;/a&gt;. This is a rather long quotation to include here, I know, but I&amp;#8217;m sure the author wouldn&amp;#8217;t want me to alter his words in any way. I highly recommend the book and suggest you &lt;a href="http://www.amazon.com/gp/product/0131429019?ie=UTF8&amp;amp;tag=wordalig-20"&gt;buy a copy&lt;/a&gt; to read in full.
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The central tension in the Unix tradition has always been between doing more with less and doing more with more.  It recurs in a
lot of different contexts, often as a struggle between designs that
have the quality of clean minimalism and others that choose expressive
range and power even at the cost of high complexity.  For both sides,
the arguments for or against Emacs have
exemplified this tension since it was first ported to Unix in the
early 1980s.&lt;/p&gt;&lt;p&gt;Programs that are both as useful and as large as
Emacs make Unix programmers uncomfortable
precisely because they force us to face the tension.  They suggest
that old-school Unix minimalism is valuable as a discipline, but
that we may have fallen into the error of dogmatism.&lt;/p&gt;&lt;p&gt;There are two ways Unix programmers can address this problem.
One is to deny that large is actually large. The other is to develop
a way of thinking about complexity that is not a dogma.&lt;/p&gt;&lt;p&gt;Our thought experiment with replacing Lisp and the extension
libraries gives us a new perspective on the oft-heard charge that
Emacs is bloated because its extension
library is so large.  Perhaps this is as unfair as charging that
&lt;code&gt;/bin/sh&lt;/code&gt; is bloated because the collection
of all shellscripts on a system is large.
Emacs could be considered a virtual machine
or framework around a collection of small, sharp tools (the modes)
that happen to be written in Lisp&lt;/p&gt;&lt;p&gt;On this view, the main difference between the shell and
Emacs is that Unix distributors don&amp;#8217;t ship
all the world&amp;#8217;s shellscripts along with the shell.  Objecting to
Emacs because having a general-purpose
language in it feels like bloat is approximately as silly as refusing
to use shellscripts because shell has conditionals and for loops.
Just as one doesn&amp;#8217;t have to learn shell to use shellscripts, one
doesn&amp;#8217;t have to learn Lisp to use Emacs.  If
Emacs has a design problem, it&amp;#8217;s not so
much the Lisp interpreter (the framework part) as the fact that the
mode library is an untidy heap of historical accretions &amp;#8212; but
that&amp;#8217;s a source of complexity users can ignore, because they won&amp;#8217;t be
affected by what they don&amp;#8217;t use.&lt;/p&gt;&lt;p&gt;This mode of argument is very comforting.  It can be applied to
other tool-integration frameworks, such as the (uncomfortably large)
GNOME and KDE desktop projects.  There is some force to it.
And yet, we should be suspicious of any &amp;#8216;perspective&amp;#8217; that
offers to resolve all our doubts so neatly; it might be a
rationalization, not a rationale.&lt;/p&gt;&lt;p&gt;Therefore, let&amp;#8217;s avoid the possibility of falling into denial
and accept that Emacs is both useful
and large &amp;#8212; that it &lt;span class="emphasis"&gt;&lt;em&gt;is&lt;/em&gt;&lt;/span&gt; an argument against
Unix minimalism.  What does our analysis of the kinds of complexity in
it, and the motives for it, suggest beyond that?  And is there reason
to believe that those lessons generalize?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a id="fn5" href="http://wordaligned.org/articles/accidental-emacs#fn5link"&gt;[5]&lt;/a&gt; So now I know better! In a &lt;a href="http://www.haloscan.com/comments/wordaligned/accidental_emacs/#19336"&gt;comment&lt;/a&gt; on this site, Johan Lindstrom says you can edit video using Emacs, &lt;a href="http://1010.co.uk/gneve.html"&gt;http://1010.co.uk/gneve.html&lt;/a&gt;, and in an email Arnold M&amp;#xe1;ty&amp;#xe1;si pointed me at this &lt;a href="http://www.youtube.com/watch?v=0vumR5Hcz7s"&gt;YouTube GNEVE demo&lt;/a&gt;, while over at reddit another &lt;a href="http://reddit.com/r/programming/info/6igup/comments/"&gt;comment&lt;/a&gt; mentions an audio editing mode, &lt;a href="http://delysid.org/emacs/ecasound-el.html"&gt;http://delysid.org/emacs/ecasound-el.html&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;a id="fn6" href="http://wordaligned.org/articles/accidental-emacs#fn6link"&gt;[6]&lt;/a&gt; Splash screen excluded!
&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=zHRXch"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=zHRXch" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=FHuogh"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=FHuogh" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=I4zB1h"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=I4zB1h" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=mRoKVH"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=mRoKVH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/284935795" height="1" width="1"/&gt;</description>
<dc:date>2008-05-06</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/accidental-emacs</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/284935795/accidental-emacs</link>
<category>Emacs</category>
<category>Self</category>
<feedburner:origLink>http://wordaligned.org/articles/accidental-emacs</feedburner:origLink></item>

<item>
<title>Scatter pictures with Google Charts</title>
<description>&lt;p&gt;In a recent &lt;a href="http://www.mattcutts.com/blog/pacman-graph-in-google-chart-api/"&gt;post on his blog&lt;/a&gt; Matt Cutts asks:
&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I almost wanted to call this post &amp;#8220;Stupid Google Tricks&amp;#8221; :-) What fun diagrams can you imagine making with the &lt;a href="http://code.google.com/apis/chart/"&gt;Google Charts Service&lt;/a&gt;?
&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Here&amp;#8217;s a stupid trick: you can use the &lt;a href="http://www.pythonware.com/library/pil/handbook/"&gt;Python Imaging Library&lt;/a&gt; to convert a picture into a URL which &lt;a href="http://code.google.com/apis/chart/"&gt;Google charts&lt;/a&gt; will render as the original picture.
&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the original picture:
&lt;/p&gt;
&lt;img src="http://wordaligned.org/images/buttons/spider-bw-61.png" alt="Spider"/&gt;

&lt;p&gt;here&amp;#8217;s the version served up by Google charts:
&lt;/p&gt;
&lt;img src="http://chart.apis.google.com/chart?cht=s&amp;amp;chd=s:DDEEEEEEEEEEEEEFFFFFFFFFFFFFFGGGGGGGGGGGGHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJKKKKKKKKKKLLLLLLLMMMMMMMMNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeefffffffffffffffffffgggggggggggggggghhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkklllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnoooooooooooooooooppppppppppppppppppqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrssssssssssssssssssssttttttttttttttttuuuuuuuuuuuuuuuuvvvvvvvvvvvvvwwwwwwwxxxxxxxyyyyyyyyzzzzzzzzzzzzzzz00000000000000111111111111111122222222222222333333333333444444444555556666777,YWaZYXWVUTSRQPObaZYXWVUTSRQPOsdcbaZUTSRQPutsrqplkjidcbavutsrqponmlkjiedcwvuqponmlkjihdcxwvonjihdcxwjihdcyxjihdcRzjihdcTSRQPNJHihgdcbaZYUTSRQPONMLKJIHGFtsrjihgfedcbaZYXWVUTSONMLKJIHGFEDvutsrqihgfedcbaZYXWVUTKIHGFEDCvutqpmlihgfedcWVUTSwvponmlkjihgfedVUTSRvqponmlkjihedcTSRQrqponmlkjihedSRQPsrqponmlkjedRQPOLysrqponmlkjdcRQPONMLKyxtsrqponmlkdcSRQPONMLKJyxtsrqponmldcbUTSRQPONMLKJyxtsrqponmlihgfedcbaZWVUTSPONMKJIyxwtsrqponmljihgfedcbaZYXWVUTPONJIHxwvutsrqponmkjihgfedcbaZYXWVUONMJIHGvusrqponmlkjifedcbZXONIHGFsrqponmlkjedcONMHGFE65432rqponmlkjedcONMGFED3210qponmlkjiedcONE10nmlkjigfedPONM0zonmlkjihgfedYXVPON0zonmjihgfeZYXWVUTPON0zqponmlihgfaZYXWVUTSRQPO0zyrqpnmlbaZYVUTSRQPOzytsrqpmlkcbaZTSRQPzyxwvutsrqmlkjcbaTSRQyxwvutsnmlkjicbUTSRQponmlkjihdcbWVUTSqponjihgdcbZYXWVUTrqponjihgfedcbaZYXWVsrqpjihgfedcbaZYXsrqjifedcbaZYXTSRQPOsrkjYXWVUTSRQPONsrkjYXWVUTSQPONMsrqkjXWVUONMLsrqkjihsrqkjihsrqjihgVsrqihgfZYXWVUTSsrqhgfeaZYXWVUsrqpogfedcbaZYXWsrqponfedcbaZYrqponmedcbaZonmlkedcbmlkdclkjijih&amp;amp;chm=s,000000,1,2.0,3.0,0&amp;amp;chs=186x186" alt="Google Chart Spider"/&gt;

&lt;p&gt;here&amp;#8217;s the code:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;import Image
import string

def scatter_pixels(img_file):
    """Return the URL of a scatter plot of the supplied image
    
    The image will be rendered square and black on white. Adapt the
    code if you want something else.
    """
    # Use simple chart encoding. To make things really simple
    # use a square image where each X or Y position corresponds
    # to a single encode value.
    simple = string.uppercase + string.lowercase + string.digits
    rsimple = simple[::-1] # Google charts Y reverses PIL Y
    w = len(simple)
    W = w * 3
    img = Image.open(img_file).resize((w, w)).convert("1")
    pels = img.load()
    black_pels = [(x, y) for x in range(w) for y in range(w)
                  if pels[x, y] == 0]
    xs = "".join(simple[x] for x, _ in black_pels)
    ys = "".join(rsimple[y] for _, y in black_pels)
    sqside = 3.0
    return (
        "http://chart.apis.google.com/chart?"
        "cht=s&amp;amp;"                          # Draw a scatter graph
        "chd=s:%(xs)s,%(ys)s&amp;amp;"            # using simple encoding and
        "chm=s,000000,1,2.0,%(sqside)r,0&amp;amp;"# square black markers
        "chs=%(W)rx%(W)r"                 # at this size.
        ) % locals()

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and here&amp;#8217;s the url it generates:
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://chart.apis.google.com/chart?cht=s&amp;amp;chd=s:DDEEEEEEEEEEEEEFFFFFFFFFFFFFFGGGGGGGGGGGGHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJKKKKKKKKKKLLLLLLLMMMMMMMMNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRRSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeefffffffffffffffffffgggggggggggggggghhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkklllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnoooooooooooooooooppppppppppppppppppqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrssssssssssssssssssssttttttttttttttttuuuuuuuuuuuuuuuuvvvvvvvvvvvvvwwwwwwwxxxxxxxyyyyyyyyzzzzzzzzzzzzzzz00000000000000111111111111111122222222222222333333333333444444444555556666777,YWaZYXWVUTSRQPObaZYXWVUTSRQPOsdcbaZUTSRQPutsrqplkjidcbavutsrqponmlkjiedcwvuqponmlkjihdcxwvonjihdcxwjihdcyxjihdcRzjihdcTSRQPNJHihgdcbaZYUTSRQPONMLKJIHGFtsrjihgfedcbaZYXWVUTSONMLKJIHGFEDvutsrqihgfedcbaZYXWVUTKIHGFEDCvutqpmlihgfedcWVUTSwvponmlkjihgfedVUTSRvqponmlkjihedcTSRQrqponmlkjihedSRQPsrqponmlkjedRQPOLysrqponmlkjdcRQPONMLKyxtsrqponmlkdcSRQPONMLKJyxtsrqponmldcbUTSRQPONMLKJyxtsrqponmlihgfedcbaZWVUTSPONMKJIyxwtsrqponmljihgfedcbaZYXWVUTPONJIHxwvutsrqponmkjihgfedcbaZYXWVUONMJIHGvusrqponmlkjifedcbZXONIHGFsrqponmlkjedcONMHGFE65432rqponmlkjedcONMGFED3210qponmlkjiedcONE10nmlkjigfedPONM0zonmlkjihgfedYXVPON0zonmjihgfeZYXWVUTPON0zqponmlihgfaZYXWVUTSRQPO0zyrqpnmlbaZYVUTSRQPOzytsrqpmlkcbaZTSRQPzyxwvutsrqmlkjcbaTSRQyxwvutsnmlkjicbUTSRQponmlkjihdcbWVUTSqponjihgdcbZYXWVUTrqponjihgfedcbaZYXWVsrqpjihgfedcbaZYXsrqjifedcbaZYXTSRQPOsrkjYXWVUTSRQPONsrkjYXWVUTSQPONMsrqkjXWVUONMLsrqkjihsrqkjihsrqjihgVsrqihgfZYXWVUTSsrqhgfeaZYXWVUsrqpogfedcbaZYXWsrqponfedcbaZYrqponmedcbaZonmlkedcbmlkdclkjijih&amp;amp;chm=s,000000,1,2.0,3.0,0&amp;amp;chs=186x186"&gt;http://chart.apis.google.com/chart?cht=s&amp;amp;chd=s:DDEEEEEEE&amp;#8230;&amp;amp;chs=186x186&lt;/a&gt;
&lt;/p&gt;
&lt;hr /&gt;

&lt;p style="font-size:75%"&gt;&lt;strong&gt;Smallprint&lt;/strong&gt;. Google charts may return a 400 error for an image with a long URL (meaning lots of black pixels in this case). The upper limit on URL length doesn&amp;#8217;t seem to be &lt;a href="http://code.google.com/apis/chart/"&gt;documented&lt;/a&gt; but a quick &lt;a href="http://groups.google.com/group/google-chart-api/search?group=google-chart-api&amp;amp;q=url+length&amp;amp;qt_g=Search+this+group"&gt;trawl through topics on the google charts group&lt;/a&gt; suggests others have bumped into it too. Connoisseurs of whacky pictures should pay &lt;a href="http://www.romancortes.com/blog/homer-css/"&gt;CSS Homer Simpson&lt;/a&gt; a visit.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=dDSk7i"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=dDSk7i" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=tXcoTi"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=tXcoTi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=GuJRWi"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=GuJRWi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.wordaligned.org/~f/wordaligned?a=zKAexI"&gt;&lt;img src="http://feeds.wordaligned.org/~f/wordaligned?i=zKAexI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.wordaligned.org/~r/wordaligned/~4/277716865" height="1" width="1"/&gt;</description>
<dc:date>2008-04-25</dc:date>
<guid isPermaLink="false">http://wordaligned.org/articles/scatter-pictures-with-google-charts</guid>
<author>tag@wordaligned.org (Thomas Guest)</author>
<link>http://feeds.wordaligned.org/~r/wordaligned/~3/277716865/scatter-pictures-with-google-charts</link>
<category>PIL</category>
<category>Google</category>
<category>Drawing</category>
<category>Python</category>
<category>Charts</category>
<feedburner:origLink>http://wordaligned.org/articles/scatter-pictures-with-google-charts</feedburner:origLink></item>

<item>
<title>Takewhile drops one</title>
<description>&lt;p&gt;Here&amp;#8217;s some naughty code.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;from itertools import takewhile
    
def take_some(pred, xs):
    while True:
        for x in takewhile(pred, xs):
            yield x

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This code abuses the &amp;#8220;iterator building block&amp;#8221; foundations of Python&amp;#8217;s &lt;a href="http://docs.python.org/lib/module-itertools.html"&gt;itertools module&lt;/a&gt;. Once you&amp;#8217;ve chopped a stream&amp;#8217;s head off using &lt;code&gt;takewhile&lt;/code&gt; you can&amp;#8217;t resume processing its tail &amp;#8230; Or can you?
&lt;/p&gt;
&lt;span id="continue-reading"/&gt;

&lt;p&gt;A casual inspection of this function &lt;em&gt;suggests&lt;/em&gt; it does little more than heat up the machine: we return elements, &lt;code&gt;x&lt;/code&gt;, from a stream, &lt;code&gt;xs&lt;/code&gt;, for which &lt;code&gt;pred(x)&lt;/code&gt; holds, then we spin at the first element for which the predicate does not hold.
&lt;/p&gt;
&lt;p&gt;When we actually run the code, things turn out rather differently:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; from itertools import count, islice
&amp;gt;&amp;gt;&amp;gt; def is_even(x):
... 	return x % 2 == 0
... 
&amp;gt;&amp;gt;&amp;gt; xs = take_some(is_even, count())
&amp;gt;&amp;gt;&amp;gt; xs.next()
0
&amp;gt;&amp;gt;&amp;gt; xs.next()
2
&amp;gt;&amp;gt;&amp;gt; xs.next()
4
&amp;gt;&amp;gt;&amp;gt; list(islice(xs, 10))
[6, 8, 10, 12, 14, 16, 18, 20, 22, 24]

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;Dropwhile, ifilter, izip&lt;/h3&gt;
&lt;p&gt;Nothing overheats. In fact &lt;code&gt;take_some&lt;/code&gt; behaves suspiciously like &lt;code&gt;ifilter&lt;/code&gt;. Let&amp;#8217;s explore that hypothesis by zipping together an &lt;code&gt;ifilter&lt;/code&gt; stream and a &lt;code&gt;take_some&lt;/code&gt; stream and seeing if they diverge.
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; from itertools import dropwhile, ifilter, izip
&amp;gt;&amp;gt;&amp;gt; xs = take_some(is_even, count())
&amp;gt;&amp;gt;&amp;gt; ys = ifilter(is_even, count())
&amp;gt;&amp;gt;&amp;gt; diverge = dropwhile(lambda xy: xy[0] == xy[1], izip(xs, ys))
&amp;gt;&amp;gt;&amp;gt; diverge.next()
  C-c C-cTraceback (most recent call last):
  ...
KeyboardInterrupt
&amp;gt;&amp;gt;&amp;gt;

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here &lt;code&gt;itertools.dropwhile&lt;/code&gt; iterates through the zipped stream yielding items as soon as it detects a difference in the first and second element of a pair. This time, as you can see, we &lt;em&gt;do&lt;/em&gt; start spinning, and we have to interrupt execution to regain control.
&lt;/p&gt;

&lt;h3&gt;Small print&lt;/h3&gt;
&lt;p&gt;Our casual interpretation of &lt;code&gt;take_some&lt;/code&gt; was wrong. The actual documentation for &lt;code&gt;itertools.takewhile&lt;/code&gt; reads:
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;takewhile&lt;/b&gt;(&lt;i&gt;predicate, iterable&lt;/i&gt;)&lt;/p&gt;
&lt;p&gt;Make an iterator that returns elements from the iterable as long as the predicate is true. Equivalent to:&lt;/p&gt;
&lt;pre&gt;
     def takewhile(predicate, iterable):
         for x in iterable:
             if predicate(x):
                 yield x
             else:
                 break
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;There you have it! Once a stream returned by &lt;code&gt;takewhile&lt;/code&gt; has run its course, the original &lt;code&gt;iterable&lt;/code&gt; is poised to yield the element immediately after the first element for which the predicate fails. That is, we drop the first element for which the predicate fails. So repeatedly applying &lt;code&gt;takewhile&lt;/code&gt; to a stream drops the elements for which the predicate doesn&amp;#8217;t hold, which is to say it generates the elements for which the predicate holds, which is of course &lt;code&gt;ifilter&lt;/code&gt;.
&lt;/p&gt;

&lt;h3&gt;Bug fixes&lt;/h3&gt;
&lt;p&gt;Yes, kind of. I could point out a couple of bugs in &lt;code&gt;take_some&lt;/code&gt;. First, it doesn&amp;#8217;t work for lists. Give it a list and each application of &lt;code&gt;takewhile&lt;/code&gt; resumes iteration from the beginning of the list, meaning &lt;code&gt;take_some&lt;/code&gt; either repeats the first element of the list forever, or it spins without yielding anything:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;&amp;gt;&amp;gt;&amp;gt; ys = take_some(is_even, [1, 2, 3, 4])
&amp;gt;&amp;gt;&amp;gt; ys.next()
 ...
KeyboardInterrupt
&amp;gt;&amp;gt;&amp;gt; ys = take_some(is_even, [0, 1, 2, 3])
&amp;gt;&amp;gt;&amp;gt; ys.next()
0
&amp;gt;&amp;gt;&amp;gt; ys.next()
0
&amp;gt;&amp;gt;&amp;gt; set(islice(ys, 1000000))
set([0])

&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can fix that defect easily by applying &lt;code&gt;iter&lt;/code&gt; to the input iterable, but that exposes the second bug, that &lt;code&gt;take_some&lt;/code&gt; only works for infinite streams. Once we bang into the end of an iterable, we stay there, stuck in the while loop. To fix both defects we might end up with something like:
&lt;/p&gt;
&lt;div class="typocode"&gt;

&lt;pre class="prettyprint"&gt;from itertools import takewhile, tee
    
def take_some(pred, xs):
    while True:
        xs, ys = tee(xs)
        try:
            ys.next()
        except StopIteration:
            return
        for x in takewhile(pred, xs):
            yield x

&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;The real bug fix&lt;/h3&gt;
&lt;p&gt;Actually, the real bug, which I admitted to at the outset, is in our thinking. This code abuses the iterator-building-blocks paradigm at the heart of the &lt;a href="http://docs.python.org/lib/module-itertools.html"&gt;itertools module&lt;/a&gt;. &lt;code&gt;Takewhile&lt;/code&gt; converts one stream into another stream; the original stream has gone and if we wanted it we should have teed it first.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wordaligned.org/tag/shell" title="Articles about shell"&gt;&lt;img style="float:right;" src="http://wordaligned.org/images/buttons/crab.jpg" alt="Pictur