scratch/output/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/index.html
Yann Esposito (Yogsototh) f19c2a270a Regen
2012-01-20 14:41:44 +01:00

465 lines
No EOL
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="XML, Perl, programming, tree, theory, mathematics, regexp, script">
<link rel="shortcut icon" type="image/x-icon" href="/Scratch/img/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/Scratch/assets/css/main.css" />
<link rel="stylesheet" type="text/css" href="/Scratch/css/twilight.css" />
<link rel="stylesheet" type="text/css" href="/Scratch/css/idc.css" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="http://feeds.feedburner.com/yannespositocomen"/>
<link rel="alternate" lang="fr" xml:lang="fr" title="Arbres ; Pragmatisme et Formalisme" type="text/html" hreflang="fr" href="/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/" />
<link rel="alternate" lang="en" xml:lang="en" title="Trees; Pragmatism and Formalism" type="text/html" hreflang="en" href="/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/" />
<script type="text/javascript" src="/Scratch/js/jquery-1.3.1.min.js"></script>
<script type="text/javascript" src="/Scratch/js/jquery.cookie.js"></script>
<script type="text/javascript" src="/Scratch/js/index.js"></script>
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<title>Trees; Pragmatism and Formalism</title>
</head>
<body lang="en" class="article">
<script type="text/javascript">// <![CDATA[
document.write('<div id="blackpage"><img src="/Scratch/img/loading.gif" alt="loading..."/></div>');
// ]]>
</script>
<div id="content">
<div id="choix">
<div class="return"><a href="#entete">&darr; Menu &darr;</a></div>
<div id="choixlang">
<a href="/Scratch/fr/blog/2010-05-24-Trees--Pragmatism-and-Formalism/" onclick="setLanguage('fr')">en Français</a>
</div>
<div class="flush"></div>
</div>
<div id="titre">
<h1>
Trees; Pragmatism and Formalism
</h1>
<h2>
When theory is more efficient than practice
</h2>
</div>
<div class="flush"></div>
<div class="flush"></div>
<div id="afterheader">
<div class="corps">
<div class="intro">
<p><abbr title="Too Long; Don't Read"><span class="sc">tl;dr</span></abbr>: </p>
<ul>
<li>I tried to program a simple filter</li>
<li>Was blocked 2 days</li>
<li>Then stopped working like an engineer monkey</li>
<li>Used a pen and a sheet of paper</li>
<li>Made some math.</li>
<li>Crushed the problem in 10 minutes</li>
<li>Conclusion: The pragmatism shouldnt mean “never use theory”.</li>
</ul>
</div>
<h2 id="abstract-longer-than-abbr-titletoo-long-dont-readsctldrscabbr">Abstract (longer than <abbr title="Too Long; Don't Read"><span class="sc">tl;dr</span></abbr>)</h2>
<p>For my job, I needed to resolve a problem. It first seems not too hard.
Then I started working directly on my program.
I entered in the <em>infernal</em>: <em>try &amp; repair loop</em>.
Each step was like:</p>
<blockquote>
<p> Just this thing to repair and that should be done.<br />
OK, now that should just work.<br />
Yeah!!!<br />
Oops! I forgotten that…<br />
<code>repeat until death</code></p>
</blockquote>
<p>After two days of this <a href="http://fr.wikipedia.org/wiki/Sisyphe">Sisyphus</a> work, I finally just stopped to rethink the problem.
I took a pen, a sheet of paper. I simplified the problem, reminded what I learned during my Ph.D. about trees.
Finally, the problem was crushed in less than 20 minutes.</p>
<p>I believe the important lesson is to remember that the most efficient methodology to resolve this <em>pragmatic</em> problem was the <em>theoretical</em> one.
And therefore, argues opposing science, theory to pragmatism and efficiency are fallacies.</p>
</div>
<div class="corps">
<h1 class="first" id="first-my-experience">First: my experience</h1>
<p>Apparently 90% of programmer are unable to program a binary search without bug.
The algorithm is well known and easy to understand.
However it is difficult to program it without any flaw.
I participated to <a href="http://reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/">this contest</a>.
And you can see the <a href="http://reprog.wordpress.com/2010/04/21/binary-search-redux-part-1/">results here</a><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.
I had to face a problem of the same kind at my job. The problem was simple to the start. Simply transform an <span class="sc">xml</span> from one format to another.</p>
<p>The source <span class="sc">xml</span> was in the following general format:</p>
<pre class="twilight">
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">rubrique</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">contenu</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">tag1</span><span class="MetaTagAll">&gt;</span></span>value1<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">tag1</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">tag2</span><span class="MetaTagAll">&gt;</span></span>value2<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">tag2</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">contenu</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">enfant</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">rubrique</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">rubrique</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">rubrique</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">rubrique</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">enfant</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">menu</span><span class="MetaTagAll">&gt;</span></span>
</pre>
<p>and the destination format was in the following general format:</p>
<pre class="twilight">
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">item</span> <span class="MetaTagAll">name</span>=<span class="String"><span class="String">&quot;</span>Menu0<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">item</span> <span class="MetaTagAll">name</span>=<span class="String"><span class="String">&quot;</span>menu<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">item</span> <span class="MetaTagAll">name</span>=<span class="String"><span class="String">&quot;</span>tag1<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>value1<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">item</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">item</span> <span class="MetaTagAll">name</span>=<span class="String"><span class="String">&quot;</span>tag2<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>value2<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">item</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">item</span> <span class="MetaTagAll">name</span>=<span class="String"><span class="String">&quot;</span>menu<span class="String">&quot;</span></span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
...
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">item</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">item</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">value</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">item</span><span class="MetaTagAll">&gt;</span></span>
</pre>
<p>At first sight I believed it will be easy. I was so certain it will be easy that I fixed to myself the following rules:</p>
<ol>
<li>do not use <span class="sc">xslt</span></li>
<li>avoid the use of an <span class="sc">xml</span> parser</li>
<li>resolve the problem using a simple perl script[^2]</li>
</ol>
<p>You can try if you want. If you attack the problem directly opening an editor, I assure you, it will certainly be not so simple.
I can tell that, because its what Ive done. And I must say I lost almost a complete day at work trying to resolve this. There was also, many small problems around that make me lose more than two days for this problem.</p>
<p>Why after two days did I was unable to resolve this problem which seems so simple?</p>
<p>What was my behaviour (workflow)?</p>
<ol>
<li>Think</li>
<li>Write the program</li>
<li>Try the program </li>
<li>Verify the result</li>
<li>Found a bug</li>
<li>Resolve the bug</li>
<li>Go to step 3.</li>
</ol>
<p>This was a <em>standard</em> workflow for computer engineer. The flaw came from the first step.
I thought about how to resolve the problem but with the eyes of a <em>pragmatic engineer</em>. I was saying:</p>
<blockquote>
<p>That should be a simple perl search and replace program.<br />
Lets begin to write code</p>
</blockquote>
<p>This is the second sentence that was plainly wrong. I started in the wrong direction. And the workflow did not work from this entry point.</p>
<h2 id="think">Think</h2>
<p>After some times, I just stopped to work. Tell myself <em>“it is enough, now, I must finish it!”</em>.
I took a sheet of paper, a pen and began to draw some trees.</p>
<p>I began by make by removing most of the verbosity.
I first renamed <code>&lt;item name="Menu"&gt;</code> by simpler name <code>M</code> for example.
I obtained something like:</p>
<p><img alt="The source tree" src="/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/graph/The_source_tree.png" /></p>
<p>and</p>
<p><img alt="The destination tree" src="/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/graph/The_destination_tree.png" /></p>
<p>Then I made myself the following reflexion:</p>
<p>Considering Tree Edit Distance, each unitary transformation of tree correspond to a simple search and replace on my <span class="sc">xml</span> source<sup id="fnref:nb"><a href="#fn:nb" rel="footnote">2</a></sup>.
We consider three atomic transformations on trees:</p>
<ul>
<li><em>substitution</em>: renaming a node</li>
<li><em>insertion</em>: adding a node</li>
<li><em>deletion</em>: remove a node</li>
</ul>
<p>One of the particularity of atomic transformations on trees, is&nbsp;; if you remove a node, all children of this node, became children of its father.</p>
<p>An example:</p>
<pre class="twilight">
r - x - a
\ \
\ b
y - c
</pre>
<p>If you delete the <code>x</code> node, you obtain</p>
<pre class="twilight">
a
/
r - b
\
y - c
</pre>
<p>And look at what it implies when you write it in <span class="sc">xml</span>:</p>
<pre class="twilight">
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">r</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">x</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">a</span><span class="MetaTagAll">&gt;</span></span>value for a<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">a</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">b</span><span class="MetaTagAll">&gt;</span></span>value for b<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">b</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">x</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">y</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">c</span><span class="MetaTagAll">&gt;</span></span>value for c<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">c</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">y</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;/</span><span class="MetaTagAll">r</span><span class="MetaTagAll">&gt;</span></span>
</pre>
<p>Then deleting all <code>x</code> nodes is equivalent to pass the <span class="sc">xml</span> via the following search and replace script:</p>
<pre class="twilight">
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>&lt;<span class="StringRegexpSpecial">\/</span>?x&gt;</span><span class="StringRegexp"><span class="StringRegexp">/</span><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
</pre>
<p>Therefore, if there exists a one state deterministic transducer which transform my trees&nbsp;;
I can transform the <span class="sc">xml</span> from one format to another with just a simple list of search and replace directives.</p>
<h1 id="solution">Solution</h1>
<p>Transform this tree:</p>
<pre class="twilight">
R - C - tag1
\ \
\ tag2
E -- R - C - tag1
\ \ \
\ \ tag2
\ E ...
R - C - tag1
\ \
\ tag2
E ...
</pre>
<p>to this tree:</p>
<pre class="twilight">
tag1
/
M - V - M - V - tag2 tag1
\ /
M --- V - tag2
\ \
\ M
\ tag1
\ /
V - tag2
\
M
</pre>
<p>can be done using the following one state deterministic tree transducer:</p>
<blockquote>
<p>C &rarr; ε<br />
E &rarr; M<br />
R &rarr; V </p>
</blockquote>
<p>Wich can be traduced by the following simple search and replace directives: </p>
<pre class="twilight">
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>C</span><span class="StringRegexp"><span class="StringRegexp">/</span><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>E</span><span class="StringRegexp"><span class="StringRegexp">/</span>M<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>R</span><span class="StringRegexp"><span class="StringRegexp">/</span>V<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
</pre>
<p>Once adapted to <span class="sc">xml</span> it becomes:</p>
<pre class="twilight">
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>%</span>&lt;/?contenu&gt;</span><span class="StringRegexp"><span class="StringRegexp">%</span><span class="StringRegexp">%</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>%</span>&lt;enfant&gt;</span><span class="StringRegexp"><span class="StringRegexp">%</span>&lt;item name=&quot;menu&quot;&gt;<span class="StringRegexp">%</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>%</span>&lt;/enfant&gt;</span><span class="StringRegexp"><span class="StringRegexp">%</span>&lt;/item&gt;<span class="StringRegexp">%</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>%</span>&lt;rubrique&gt;</span><span class="StringRegexp"><span class="StringRegexp">%</span>&lt;value&gt;<span class="StringRegexp">%</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>%</span>&lt;/rubrique&gt;</span><span class="StringRegexp"><span class="StringRegexp">%</span>&lt;/value&gt;<span class="StringRegexp">%</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
</pre>
<p>That is all.</p>
<h1 id="conclusion">Conclusion</h1>
<p>It should seems a bit paradoxal, but sometimes the most efficient approach to a pragmatic problem is to use the theoretical methodology.</p>
<hr/><div class="footnotes">
<ol>
<li id="fn:1">
<p>Hopefully I am in the 10% who had given a bug free implementation.<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>
<li id="fn:nb">
<p>I did a program which generate automatically the weight in a matrix of each edit distance from data.<a href="#fnref:nb" rev="footnote">&#8617;</a></p>
</li>
</ol>
</div>
</div>
<div id="choixrss">
<a id="rss" href="http://feeds.feedburner.com/yannespositocomen">
Subscribe
</a>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#comment').hide();
$('#clickcomment').click(showComments);
});
function showComments() {
$('#comment').show();
$('#clickcomment').fadeOut();
}
document.write('<div id="clickcomment">Comments</div>');
</script>
<div class="flush"></div>
<div class="corps" id="comment">
<h2 class="first">comments</h2>
<noscript>
You must enable javascript to comment.
</noscript>
<script type="text/javascript">
var idcomments_acct = 'a307f0044511ff1b5cfca573fc0a52e7';
var idcomments_post_id = '/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/';
var idcomments_post_url = 'http://yannesposito.com/Scratch/en/blog/2010-05-24-Trees--Pragmatism-and-Formalism/';
</script>
<span id="IDCommentsPostTitle" style="display:none"></span>
<script type='text/javascript' src='/Scratch/js/genericCommentWrapperV2.js'></script>
</div>
<div id="entete" class="corps_spaced">
<div id="liens">
<ul><li><a href="/Scratch/en/">Home</a></li>
<li><a href="/Scratch/en/blog/">Blog</a></li>
<li><a href="/Scratch/en/softwares/">Softwares</a></li>
<li><a href="/Scratch/en/about/">About</a></li></ul>
</div>
<div class="flush"></div>
<hr/>
<div id="next_before_articles">
<div id="previous_articles">
previous entries
<div class="previous_article">
<a href="/Scratch/en/blog/2010-05-19-How-to-cut-HTML-and-repair-it/"><span class="nicer">«</span>&nbsp;How to repair a cutted XML?</a>
</div>
<div class="previous_article">
<a href="/Scratch/en/blog/2010-05-17-at-least-this-blog-revive/"><span class="nicer">«</span>&nbsp;I live again!</a>
</div>
<div class="previous_article">
<a href="/Scratch/en/blog/2010-03-23-Encapsulate-git/"><span class="nicer">«</span>&nbsp;Encapsulate git</a>
</div>
</div>
<div id="next_articles">
next entries
<div class="next_article">
<a href="/Scratch/en/blog/2010-06-14-multi-language-choices/">multi language choices&nbsp;<span class="nicer">»</span></a>
</div>
<div class="next_article">
<a href="/Scratch/en/blog/2010-06-15-Get-my-blog-engine/">Get my blog engine&nbsp;<span class="nicer">»</span></a>
</div>
<div class="next_article">
<a href="/Scratch/en/blog/2010-06-17-track-events-with-google-analytics/">Track Events with Google Analytics&nbsp;<span class="nicer">»</span></a>
</div>
</div>
<div class="flush"></div>
</div>
</div>
<div id="bottom">
<div>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Copyright ©, Yann Esposito</a>
</div>
<div id="lastmod">
Created: 05/24/2010
Modified: 12/07/2011
</div>
<div>
Entirely done with
<a href="http://www.vim.org">Vim</a>
and
<a href="http://nanoc.stoneship.org">nanoc</a>
</div>
<div>
<a href="/Scratch/en/validation/">Validation</a>
<a href="http://validator.w3.org/check?uri=referer"> [xhtml] </a>
.
<a href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3"> [css] </a>
.
<a href="http://validator.w3.org/feed/check.cgi?url=http%3A//yannesposito.com/Scratch/en/blog/feed/feed.xml">[rss]</a>
</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>