<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>El Tramo &#187; Programming</title>
	<atom:link href="http://el-tramo.be/blog/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://el-tramo.be</link>
	<description>Remko Tronçon&#039;s Homepage</description>
	<lastBuildDate>Fri, 11 Jun 2010 19:08:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>“XMPP: The Definitive Guide” Code Examples</title>
		<link>http://el-tramo.be/blog/xmpp-tdg-code</link>
		<comments>http://el-tramo.be/blog/xmpp-tdg-code#comments</comments>
		<pubDate>Mon, 13 Jul 2009 17:06:01 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Jabber]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SleekXMPP]]></category>
		<category><![CDATA[XMPP]]></category>
		<category><![CDATA[XMPP-TDG]]></category>

		<guid isPermaLink="false">/?p=473</guid>
		<description><![CDATA[Although the primary focus of XMPP: The Definitive Guide is explaning the XMPP protocol and all its extensions through text and illustrations, we also included a few Python code examples to help people get started with implementing their own ideas. In fact, we devoted a whole chapter to building an XMPP application, starting out with [...]]]></description>
			<content:encoded><![CDATA[<p>Although the primary focus of <a href="http://oreilly.com/catalog/9780596521264/"><em>XMPP: The Definitive Guide</em></a> is explaning the XMPP protocol and all its extensions through text and illustrations, we also included a few Python code examples to help people get started with implementing their own ideas. In fact, we devoted a whole chapter to building an XMPP application, starting out with a simple bot implementation, but gradually extending the application into a full server component. For people who want to try this out for themselves, we’re releasing the <a href="/git/xmpp-tdg/snapshot/xmpp-tdg-master.zip">source code of all code examples</a>, including a <a href="/git/xmpp-tdg/tree/code/EchoBot">simple echo bot</a>, and different variants of the <a href="/git/xmpp-tdg/tree/code/CheshiR">CheshiR microblogging platform XMPP interface</a>.</p>
<p><span id="more-473"></span></p>
<p>All examples are built using the lightweight <a href="http://code.google.com/p/sleekxmpp/">SleekXMPP</a> Python XMPP library. In fact, SleekXMPP is so lightweight that we included a version in the source bundle, making it even easier to get started implementing your own bots and components.</p>
<p>Do bear in mind that these examples only serve illustrative purposes for the book, so don’t expect very robust code. Although making this code fail-safe is not really our primary goal (since that would involve a lot of code that would only distract the reader), we <em>do</em> welcome bug reports or fixes.</p>
<p>The code examples are available as a <a href="/git/xmpp-tdg/snapshot/xmpp-tdg-master.zip">source package</a>, or directly from the <a href="/git/xmpp-tdg">Git repository</a> (mirrored on <a href="http://github.com/remko/xmpp-tdg">GitHub</a>). We will soon put a link to the package on <a href="http://oreilly.com/catalog/9780596521264/">the book’s webpage</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/xmpp-tdg-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mixing Cocoa and Qt</title>
		<link>http://el-tramo.be/blog/mixing-cocoa-and-qt</link>
		<comments>http://el-tramo.be/blog/mixing-cocoa-and-qt#comments</comments>
		<pubDate>Sat, 16 Aug 2008 11:47:20 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Sparkle]]></category>

		<guid isPermaLink="false">http://el-tramo.be/?p=155</guid>
		<description><![CDATA[Qt does a great job at abstracting out platform-specific features into platform-independent C++ APIs. However, sometimes you still need to write platform-specific code for features that are not in Qt (e.g. to access the platform&#8217;s address book),  or to access platform-specific applications (e.g. iTunes) or libraries (e.g. Sparkle). On Mac OS X, almost all interfaces [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://trolltech.com/products/qt/index">Qt</a> does a great job at abstracting out platform-specific features into platform-independent C++ APIs. However, sometimes you still need to write platform-specific code for features that are not in Qt (e.g. to access the platform&#8217;s address book),  or to access platform-specific applications (e.g. iTunes) or libraries (e.g. <a href="http://sparkle.andymatuschak.org/">Sparkle</a>). On Mac OS X, almost all interfaces are offered through the <a href="http://developer.apple.com/cocoa/">Cocoa</a> Objective-C interface, and the interfaces that are written in C++ have been deprecated and will disappear soon in favor of Cocoa. Although the language of Cocoa is different from Qt&#8217;s, Qt and <a href="http://gcc.gnu.org">GCC</a> make it very easy to call these interfaces from within your application. In this post, I will show how this can be done by making an auto-updating application using Sparkle.</p>
<p><span id="more-155"></span></p>
<p>To create our auto-updating application, we first lay down the auto-updater interface in a (pure) virtual class:</p>
<blockquote>
<pre>class AutoUpdater {
  public:
    virtual void checkForUpdates() = 0;
};</pre>
</blockquote>
<p>The Sparkle implementation of this interface has the following C++ header:</p>
<blockquote>
<pre>class SparkleAutoUpdater : public AutoUpdater {
  public:
    SparkleAutoUpdater(const QString&amp; url);
    ~SparkleAutoUpdater();
    virtual void checkForUpdates();
  private:
    class Private;
    Private* d;
};</pre>
</blockquote>
<p>Note that I am using the <a href="http://c2.com/cgi/wiki?PimplIdiom">Pimpl</a> idiom to hide Cocoa-specific internals from the API into a private internal class.</p>
<p>The actual impementation of the <code>SparkleUpdater</code> needs to call Sparkle&#8217;s Objective-C API. However, we cannot write the implementation in Objective-C, since the header for our updater (which will be included from within our application) is written in C++. Luckily, GCC&#8217;s Objective-C++ extension allows you to mix Objective-C with C++ without any problem. So, we create an Objective-C++ implementation of our updater, and put it in a <code>.mm</code> file:</p>
<blockquote>
<pre>class SparkleAutoUpdater::Private {
  public:
    SUUpdater* updater;
};

SparkleAutoUpdater::SparkleAutoUpdater(const QString&amp; aUrl) {
  d = new Private;
  d-&gt;updater = [[SUUpdater sharedUpdater] retain];
  NSURL* url = [NSURL URLWithString:
      [NSString stringWithUTF8String: aUrl.toUtf8().data()]];
  [d-&gt;updater setFeedURL: url];
}

SparkleAutoUpdater::~SparkleAutoUpdater() {
  [d-&gt;updater release];
  delete d;
}

void SparkleAutoUpdater::checkForUpdates() {
  [d-&gt;updater checkForUpdatesInBackground];
}</pre>
</blockquote>
<p>All we do here is create an <code>SUUpdater</code> (Sparkle&#8217;s updater class), set it up, and activate it in our <code>checkForUpdates()</code> method.</p>
<p>To integrate Objective-C++ classes into a Qt project, <code>qmake</code> provides the <code>OBJECTIVE_SOURCES</code> variable. Knowing this, we add our new classes to our <code>qmake</code> project file:</p>
<blockquote>
<pre>HEADERS += AutoUpdater.h
SOURCES += AutoUpdater.cpp
mac {
  HEADERS += SparkleAutoUpdater.h
  OBJECTIVE_SOURCES += SparkleAutoUpdater.mm
  LIBS += -framework Sparkle
}</pre>
</blockquote>
<p>Before we integrate the updater into our application, there is still one detail we have to take care of: if you write Objective-C code that creates objects, you need to instantiate an <code>NSAutoReleasePool</code> to enable Cocoa&#8217;s memory management. Although we could do this in <code>SparkleAutoUpdater</code>, we&#8217;re going to put this in a separate initializer class, so we can share this with other Objective-C++ implementations in our application. The body of this class looks as follows:</p>
<blockquote>
<pre>class CocoaInitializer::Private {
  public:
    NSAutoreleasePool* autoReleasePool;
};

CocoaInitializer::CocoaInitializer() {
  d = new CocoaInitializer::Private();
  NSApplicationLoad();
  d-&gt;autoReleasePool = [[NSAutoreleasePool alloc] init];
}

CocoaInitializer::~CocoaInitializer() {
  [d-&gt;autoReleasePool release];
  delete d;
}</pre>
</blockquote>
<p>Now all that&#8217;s left to do is integrate all this into our application:</p>
<blockquote><p><code> </code></p>
<pre>int main(int argc, char* argv[]) {
  ...
  AutoUpdater* updater = 0;
#ifdef Q_WS_MAC
  CocoaInitializer cocoaInitiarizer;
  updater = new SparkleUpdater("http://el-tramo.be/myapp/appcast.xml");
#endif
  ...
  if (updater) {
    updater-&gt;checkForUpdates();
  }
  ...
}</pre>
</blockquote>
<p>That&#8217;s it! If you want to try this out yourself, just download the <a href="http://el-tramo.be/files/blog/mixing-cocoa-and-qt/mixing-cocoa-and-qt.zip">sources</a> of this mini-project, build them, and off you go. Don&#8217;t forget to remove <code>~/Library/Preferences/be.el-tramo.mixing-cocoa-and-qt.plist</code> to clear Sparkle&#8217;s state cache.</p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/mixing-cocoa-and-qt/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Basic Music Theory in Haskell</title>
		<link>http://el-tramo.be/blog/basic-music-theory-in-haskell</link>
		<comments>http://el-tramo.be/blog/basic-music-theory-in-haskell#comments</comments>
		<pubDate>Thu, 19 Jun 2008 21:06:00 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://el-tramo.be/?p=90</guid>
		<description><![CDATA[While doing some spring cleaning around my hard disk, I found a little Haskell program I wrote several years ago in an attempt to learn the basics of music theory. Now, I&#8217;m not a pro at writing Haskell, and I know even less about music theory, but I&#8217;m hoping that what I wrote down back [...]]]></description>
			<content:encoded><![CDATA[<p>While doing some spring cleaning around my hard disk, I found a <a href="/git/haskell/tree/MusicTheoryBasics.hs">little Haskell program</a> I wrote several years ago in an attempt to learn the basics of music theory. Now, I&#8217;m not a pro at writing Haskell, and I know even less about music theory, but I&#8217;m hoping that what I wrote down back then is a bit accurate. The program seems to summarize the basics quite consisely: by just having a glance at the program, I&#8217;m rediscovering some things I totally forgot about scales and chords.</p>
<p><span id="more-90"></span></p>
<p>For example, this is what it says about the <em>sus4</em> chord:</p>
<blockquote><p>chordNotes Five = [(ScaleNote Major 1), (ScaleNote Major 5)]<br />
chordNotes Sus4 = (chordNotes Five) ++ [(ScaleNote Major 4)]</p></blockquote>
<p>So, <em>sus4</em> is a power (<em>5</em>) chord (consisting of the first and the fifth of the major scale), added with the 4th note of the major scale. So, for <em>Esus4</em>, the program tells me:</p>
<blockquote><p>Main&gt; scale2notes $ Scale (read &#8220;E&#8221;) Major<br />
[E,F#,G#,A,B,C#,D#]</p>
<div>Main&gt; chord2notes $ Chord (read &#8220;E&#8221;) Sus4</div>
<div>[E,A,B]</div>
</blockquote>
<p>Something else I forgot is:</p>
<blockquote><p>intervals Ionian = [2,2,1,2,2,2,1]<br />
intervals Major = Ionian<br />
intervals scale = shift (intervals Ionian) (rank scale)<br />
where rank &#8230;</p></blockquote>
<p>So, every scale is really a shift of the major (well, any) scale, which is actually called the Ionian scale.</p>
<p>This program might come in handy as a summary of music theory in case I forget these things again <img src='http://el-tramo.be/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/basic-music-theory-in-haskell/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>:set noexpandtab</title>
		<link>http://el-tramo.be/blog/set-noexpandtab</link>
		<comments>http://el-tramo.be/blog/set-noexpandtab#comments</comments>
		<pubDate>Wed, 18 Jun 2008 20:58:24 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Coding Style]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Tabs]]></category>

		<guid isPermaLink="false">http://el-tramo.be/?p=97</guid>
		<description><![CDATA[Google recently published a C++ style guide, containing all the rules that Google code adheres to. Many of the style tips are quite sensible, and well accepted by many developers out there. However, I was surprised to find the following rule:
Spaces vs. Tabs: Use only spaces, and indent 2 spaces at a time.
We use spaces for [...]]]></description>
			<content:encoded><![CDATA[<p>Google recently published a <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml">C++ style guide</a>, containing all the rules that Google code adheres to. Many of the style tips are quite sensible, and well accepted by many developers out there. However, I was surprised to find the following rule:</p>
<blockquote><p><span><strong>Spaces vs. Tabs:</strong><em> Use only spaces, and indent 2 spaces at a time.<br />
<span style="font-style: normal;">We use spaces for indentation. Do not use tabs in your code. You should set your editor to emit spaces when you hit the tab key.</span></em></span></p></blockquote>
<p>I never really understood why so many people have such a hatred towards tabs. Is it just because they have seen code where some editor has mixed tabs with spaces (which of course results in a horrible mess)? Or do they have valid counter-arguments, even when tabs are used consistently?</p>
<p><span id="more-97"></span>Why would you force presentation of your code upon someone if you don&#8217;t need to? If you use tabs, you don&#8217;t need rules like ‘indent 2 spaces at a time’: I can choose whether I want 2 spaces, 4, or whatever indentation I feel most comfortable with when reading code. </p>
<p>After some discussion, the pro-space people typically come up with the following piece of code, where they have their parameter names aligned:</p>
<blockquote><p><code>
<pre>void SomeClass::someMethodName(int parameterA,
                               unsigned int parameterB,
                               std::string parameterC)
{
    ...
}</pre>
<p></code></p></blockquote>
<p>No, you can&#8217;t do that with tabs, that&#8217;s true. But why would you do that in the first place (unless you&#8217;re using an editor which does such annoying auto-formating automatically)? When your method name gets too long, it won&#8217;t fit on your screen anyway. Why don&#8217;t you indent 2 tabs for your parameter names instead:</p>
<blockquote><p><code>
<pre>void SomeClassWithALongName::someMethodName(
        unsigned int parameterA,
        int parameterB,
        std::string parameterC)
{
    ...
}</pre>
<p></code></p></blockquote>
<p>Another popular argument is aligning member declarations:</p>
<blockquote><p><code></p>
<pre>FooClass foo_;
Bar      bar_;</pre>
<p></code></p></blockquote>
<p>Same remark: why would you do this? Does it really make your code more readable? Besides, it doesn&#8217;t scale: whenever someone comes along and has to add a <code>VeryLongClassName</code> member, your alignment  will be messed up, and you will have to change every member again.</p>
<p>My opinion: let the person who reads your code decide how he/she wants to see it, and lay out your code in a way it is flexible to be seen with different view settings. This avoids lengthy discussions about whether tabs should be 2, 3, 4, or 13 spaces wide. Besides, people have been preaching the separation of presentation and content for ages for HTML and CSS, why would this be any different for code?</p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/set-noexpandtab/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Unit testing method overrides</title>
		<link>http://el-tramo.be/blog/unit-testing-overrides</link>
		<comments>http://el-tramo.be/blog/unit-testing-overrides#comments</comments>
		<pubDate>Fri, 07 Mar 2008 19:18:01 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://el-tramo.be/blog/unit-testing-overrides</guid>
		<description><![CDATA[It probably happened to most of us developers before: while refactoring, you change the name of a virtual method, but forget to change the name of the overriding method in one of your derived classes. Compilation works fine, all unit tests pass, but your program doesn&#8217;t work: the overriding method is never called. Java (and [...]]]></description>
			<content:encoded><![CDATA[<p>It probably happened to most of us developers before: while refactoring, you change the name of a virtual method, but forget to change the name of the overriding method in one of your derived classes. Compilation works fine, all unit tests pass, but your program doesn&#8217;t work: the overriding method is never called. Java (and C#) programmers can avoid this problem by putting <code>@Override</code> (and <code>override</code>) in front of their methods, which causes the compiler to print out an error message if the method is not overriding anything. However, most other languages leave you hanging with this problem. Luckily, with statically typed languages like C++, you can avoid these bugs by slightly adapting your unit tests.</p>
<p><span id="more-82"></span></p>
<p>Suppose you have a base class <code>Oracle</code>, and a derived class <code>GeekyOracle</code>, defined as follows:<br />
<code></p>
<pre>  class Oracle {
    virtual int getLckyNmbr() {
      return 13;
    }
  };

  class GeekyOracle : public Oracle {
    virtual int getLckyNmbr() {
      return 42;
    }
  };</pre>
<p></code></p>
<p> </p>
<p>Being a good developer, you unit test <code>GeekyOracle</code>&#8217;s <code>getLckyNmbr()</code>:<br />
<code></p>
<pre>  void GeekyOracleTest::testGetLckyNmbr() {
    GeekyOracle* oracle = createGeekyOracle();
    assertEquals(42, oracle-&gt;getLckyNmbr());
  }</pre>
<p></code></p>
<p> </p>
<p>After a while, you realize that using abbreviations in method names is actually not very good practice, so you change your method name to something more readable:<br />
<code></p>
<pre>  class Oracle {
    virtual int getLuckyNumber() {
      return 13;
    }
  };</pre>
<p></code></p>
<p> </p>
<p>However, when you compile your program now, it is behaving completely different than before, although all unit tests passed. It requires manual debugging to find out that you forgot to rename <code>GeekyOracle</code>&#8217;s method as well, causing <code>Oracle</code>&#8217;s <code>getLuckyNumber()</code> to be executed, no matter what oracle you instantiate. Your unit tests didn&#8217;t catch this, because they test every method of a class separately, but don&#8217;t test the class being used in your application.</p>
<p>A way to check for this in your unit tests is to make sure that, when testing a virtual method, you always call it on an object that is <strong>statically typed with its base class</strong>. In our example, our unit test would call <code>getLckyNmbr()</code> on an <code>Oracle</code> instead of on a <code>GeekyOracle</code>:<br />
<code></p>
<pre>  void GeekyOracleTest::testGetLckyNmbr() {
    Oracle* oracle = createGeekyOracle();
    assertEquals(42, oracle-&gt;getLckyNmbr());
  }</pre>
<p></code></p>
<p> </p>
<p>This unit test will fail to compile when you change the method name of the base class, which avoids you end up with the silly bug in your program.</p>
<p>If your test allocates your object under test on the stack (e.g. for simplicity), you could use the following alternative:<br />
<code></p>
<pre>  void GeekyOracleTest::testGetLckyNmbr() {
    GeekyOracle oracle;
    assertEquals(42, ((Oracle*) &amp;oracle)-&gt;getLckyNmbr());
  }</pre>
<p></code></p>
<p> </p>
<p>However, since this degrades the readability of the test, I prefer to add a static helper method to my unit test, and write the test as follows:<br />
<code></p>
<pre>  static inline Oracle* p(Oracle&amp; foo) {
    return &amp;foo;
  }

  void GeekyOracleTest::testGetLckyNmbr() {
    GeekyOracle oracle;
    assertEquals(42, p(oracle)-&gt;getLckyNmbr());
  }</pre>
<p></code></p>
<p> </p>
<p> </p>
<p>Although I used C++ in my example, this technique should work for all statically typed languages. Advocates of dynamically typed languages claim they can compensate the lack of types by unit testing their classes properly; I wonder how they avoid this kind of problems, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/unit-testing-overrides/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qtopia Greenphone Grant</title>
		<link>http://el-tramo.be/blog/greenphone-grant</link>
		<comments>http://el-tramo.be/blog/greenphone-grant#comments</comments>
		<pubDate>Wed, 15 Aug 2007 07:39:22 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Jabber]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Greem]]></category>
		<category><![CDATA[GreenPhone]]></category>
		<category><![CDATA[Qtopia]]></category>
		<category><![CDATA[TrollTech]]></category>
		<category><![CDATA[XMPP]]></category>

		<guid isPermaLink="false">http://el-tramo.be/blog/greenphone-grant</guid>
		<description><![CDATA[A month or 2 ago, I applied for the Qtopia Greenphone Innovation Grant Program, an initiative from TrollTech to promote the development of applications for their Linux-based Qtopia Greenphone. I probably won&#8217;t surprise anyone by saying that I sent in a proposal about writing a good, cross-platform, mobile Jabber/XMPP client. Anyway, I was very excited [...]]]></description>
			<content:encoded><![CDATA[<p>A month or 2 ago, I applied for the Qtopia Greenphone Innovation Grant Program, an initiative from TrollTech to promote the development of applications for their Linux-based Qtopia Greenphone. I probably won&#8217;t surprise anyone by saying that I sent in a proposal about writing a good, cross-platform, mobile Jabber/XMPP client. Anyway, I was very excited to receive a mail from TrollTech yesterday, stating that my proposal was accepted by their review panel! As an applicant, I will be receiving a shiny new Greenphone, together with a Qtopia SDK to develop against. Deadline for submitting my application: October 31st. Let the coding begin.</p>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/greenphone-grant/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>&#8216;The First 10 Prolog Programming Contests&#8217; available for downloading</title>
		<link>http://el-tramo.be/blog/ppcbook</link>
		<comments>http://el-tramo.be/blog/ppcbook#comments</comments>
		<pubDate>Sat, 01 Jul 2006 16:23:47 +0000</pubDate>
		<dc:creator>Remko Tronçon</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[eBooks]]></category>
		<category><![CDATA[Prolog]]></category>

		<guid isPermaLink="false">http://el-tramo.be/blog/ppcbook</guid>
		<description><![CDATA[Exactly one year after we finished it, our book `The First 10 Prolog Programming Contests&#8217; is now freely downloadable. On the home page of the book, you will also find the source code of all solutions presented in the book. Below are some pictures of the &#8216;deluxe&#8217; edition of the book, hand-made by my mom.


]]></description>
			<content:encoded><![CDATA[<p>Exactly one year after we finished it, our book <em>`The First 10 Prolog Programming Contests&#8217;</em> is now <a href="http://www.cs.kuleuven.be/~dtai/ppcbook">freely downloadable</a>. On the home page of the book, you will also find the source code of all solutions presented in the book. Below are some pictures of the &#8216;deluxe&#8217; edition of the book, hand-made by <a href="http://mp.lanemetonne.be">my mom</a>.</p>
<p><span id="more-42"></span></p>
<div style="text-align: center"><a href="http://el-tramo.be/files/ppcbook/ppcbook_1.jpg"><img src="http://el-tramo.be/files/ppcbook/ppcbook_1_thumb.jpg" alt="ppcbook 1" /></a><a href="http://el-tramo.be/files/ppcbook/ppcbook_2.jpg"><img src="http://el-tramo.be/files/ppcbook/ppcbook_2_thumb.jpg" alt="ppcbook 2" /></a><a href="http://el-tramo.be/files/ppcbook/ppcbook_3.jpg"><img src="http://el-tramo.be/files/ppcbook/ppcbook_3_thumb.jpg" alt="ppcbook 3" /></a><a href="http://el-tramo.be/files/ppcbook/ppcbook_4.jpg"><img src="http://el-tramo.be/files/ppcbook/ppcbook_4_thumb.jpg" alt="ppcbook 4" /></a><a href="http://el-tramo.be/files/ppcbook/ppcbook_5.jpg"><img src="http://el-tramo.be/files/ppcbook/ppcbook_5_thumb.jpg" alt="ppcbook 5" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://el-tramo.be/blog/ppcbook/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
