<?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>Andy Balaam's Blog &#187; Tech</title>
	<atom:link href="http://www.artificialworlds.net/blog/category/tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.artificialworlds.net/blog</link>
	<description>Four in the morning, still writing Free Software</description>
	<lastBuildDate>Sat, 21 Jan 2012 08:22:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Ethernet not working on Ubuntu with Realtek RTL8111/8168B</title>
		<link>http://www.artificialworlds.net/blog/2012/01/21/ethernet-not-working-on-ubuntu-with-realtek-rtl81118168b/</link>
		<comments>http://www.artificialworlds.net/blog/2012/01/21/ethernet-not-working-on-ubuntu-with-realtek-rtl81118168b/#comments</comments>
		<pubDate>Sat, 21 Jan 2012 08:22:40 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=475</guid>
		<description><![CDATA[Thanks to rvdavid, the network on my new PC is now working, despite Ubuntu misrecognising it: How to Get Gigabit Speeds from RTL8111/8168B PCI Express Gigabit Ethernet controller on Ubuntu Linux. This is the kind of thing I had to do 10 years ago. I thought we&#8217;d moved on&#8230;]]></description>
			<content:encoded><![CDATA[<p>Thanks to rvdavid, the network on my new PC is now working, despite Ubuntu misrecognising it:</p>
<p><a href="http://www.rvdavid.net/how-to-get-gigabit-speeds-from-rtl81118168b-pci-express-gigabit-ethernet-controller-on-ubuntu-linux/">How to Get Gigabit Speeds from RTL8111/8168B PCI Express Gigabit Ethernet controller on Ubuntu Linux</a>.</p>
<p>This is the kind of thing I had to do 10 years ago.  I thought we&#8217;d moved on&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2012/01/21/ethernet-not-working-on-ubuntu-with-realtek-rtl81118168b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FreeGuide usage stats</title>
		<link>http://www.artificialworlds.net/blog/2011/10/16/freeguide-usage-stats/</link>
		<comments>http://www.artificialworlds.net/blog/2011/10/16/freeguide-usage-stats/#comments</comments>
		<pubDate>Sun, 16 Oct 2011 07:06:11 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[FreeGuide]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=472</guid>
		<description><![CDATA[A long time ago I mentioned I&#8217;d added some (opt-in) usage tracking for FreeGuide. Here are the latest stats. I think they&#8217;ve held up pretty well given how much I&#8217;ve neglected the project&#8230;]]></description>
			<content:encoded><![CDATA[<p>A long time ago <a href="http://www.artificialworlds.net/blog/2007/07/31/badly-wrong-usage-statistics-for-freeguide/">I mentioned</a> I&#8217;d added some (opt-in) usage tracking for FreeGuide.  Here are the latest stats.  I think they&#8217;ve held up pretty well given how much I&#8217;ve neglected the project&#8230;</p>
<p><a href="http://www.artificialworlds.net/blog/wp-content/uploads/anon_hits.png"><img src="http://www.artificialworlds.net/blog/wp-content/uploads/anon_hits-300x120.png" alt="" title="anon_hits" width="300" height="120" class="size-medium wp-image-479" /></a></p>
<p><a href="http://www.artificialworlds.net/blog/wp-content/uploads/unique_hits.png"><img src="http://www.artificialworlds.net/blog/wp-content/uploads/unique_hits-300x128.png" alt="" title="unique_hits" width="300" height="128" class="size-medium wp-image-478" /></a></p>
<p><a href="http://www.artificialworlds.net/blog/wp-content/uploads/hits.png"><img src="http://www.artificialworlds.net/blog/wp-content/uploads/hits-300x126.png" alt="" title="hits" width="300" height="126" class="size-medium wp-image-477" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/10/16/freeguide-usage-stats/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Entertain your baby using your Android phone</title>
		<link>http://www.artificialworlds.net/blog/2011/09/01/entertain-your-baby-using-your-android-phone/</link>
		<comments>http://www.artificialworlds.net/blog/2011/09/01/entertain-your-baby-using-your-android-phone/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 13:18:55 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=470</guid>
		<description><![CDATA[Last night my friend and I uploaded the first version of Baby Distraction, an Android app featuring charming cartoon animals, vibration and sounds. I helped almost exclusively in an advisory capacity, but still am inexplicably proud of the result: it&#8217;s incredibly simple, but polished, and, most importantly, their baby loves it. This morning I searched [...]]]></description>
			<content:encoded><![CDATA[<p>Last night my friend and I uploaded the first version of <a href="https://market.android.com/details?id=uk.co.monkdesign.babydistraction">Baby Distraction</a>, an Android app featuring charming cartoon animals, vibration and sounds.</p>
<p>I helped almost exclusively in an advisory capacity, but still am inexplicably proud of the result: it&#8217;s incredibly simple, but polished, and, most importantly, their baby loves it.</p>
<p>This morning I searched for &#8220;baby games&#8221; on the Android Marketplace, and it was the top hit.  Fame and fortune await.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/09/01/entertain-your-baby-using-your-android-phone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rdesktop swallows keyboard events</title>
		<link>http://www.artificialworlds.net/blog/2011/07/06/rdesktop-swallows-keyboard-events/</link>
		<comments>http://www.artificialworlds.net/blog/2011/07/06/rdesktop-swallows-keyboard-events/#comments</comments>
		<pubDate>Wed, 06 Jul 2011 12:03:04 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=461</guid>
		<description><![CDATA[The Linux remote desktop client rdesktop grabs all keyboard events by default, which is good, because it allows e.g. you to Alt-Tab between applications and Ctrl-Alt-Del as if you were in front of the remote machine. However, it is also bad because you can&#8217;t use the standard keyboard shortcuts to switch between virtual desktops. Varius [...]]]></description>
			<content:encoded><![CDATA[<p>The Linux remote desktop client <a href="http://www.rdesktop.org/">rdesktop</a> grabs all keyboard events by default, which is good, because it allows e.g. you to Alt-Tab between applications and Ctrl-Alt-Del as if you were in front of the remote machine.</p>
<p>However, it is also bad because you can&#8217;t use the standard keyboard shortcuts to switch between virtual desktops.  Varius Googling had convinced me that this problem was not soluble, since X only provides a global keyboard-grabbing function <a href="http://www.xfree86.org/current/XGrabKeyboard.3.html">XGrabKeyboard</a>, and once the event has been grabbed and fed to rdesktop, there doesn&#8217;t appear to be a way to re-emit it back up to the window manager so that it can be used to switch desktops.</p>
<p>Kudos to <a href="http://sunner.cn/">Sunner</a>, therefore, for coming up with a <a href="http://blog.sunner.cn/rdesktop-patch-switch-local-workspaces-and-windows-by-local-hot-keys/">workaround</a>.  It&#8217;s really simple: you have to press the key twice, and the first time, rdesktop simply ungrabs the keyboard.  The second time, the window manager receives the event as normal.</p>
<p>Here&#8217;s my version of Sunner&#8217;s patch, against rdesktop 1.6.0.  It removes Alt-Tab support since I don&#8217;t need that, and adds Ctrl-Alt-Up and -Down, because I do need those:</p>
<pre>--- rdesktop-1.6.0/xkeymap.c	2011-07-06 12:49:01.000000000 +0100
+++ rdesktop-1.6.0-mod/xkeymap.c	2011-07-06 11:40:24.000000000 +0100
@@ -598,6 +598,25 @@
 				ui_seamless_toggle();
 			break;

+		case XK_Left:
+		case XK_Right:
+		case XK_Up:
+		case XK_Down:
+			if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
+					&#038;&#038; (get_key_state(state, XK_Control_L)
+						|| get_key_state(state, XK_Control_R)))
+			{
+				/* Ctrl-Alt-Left/Right/Up/Down:
+				 * Ungrab the keyboard so that user can use Windows manager's hot keys */
+				extern RD_BOOL g_fullscreen;
+				if (g_fullscreen) { /* Turn to normal window. Otherwise, rdesktop will be always on top */
+					xwin_toggle_fullscreen();
+				}
+
+				XUngrabKeyboard(g_display, CurrentTime);
+				return True;
+			}
+			break;
 	}
 	return False;
 }</pre>
<p>(Download it here: <a href="http://www.artificialworlds.net/blog/wp-content/uploads/rdesktop-1.6.0-ungrab-on-ctrl-alt-direction.patch">rdesktop-1.6.0-ungrab-on-ctrl-alt-direction.patch</a>)</p>
<p>And as usual here is how to patch your Ubuntu system to include this patch:</p>
<div class="code">sudo apt-get install build-essential fakeroot dpkg-dev<br />
sudo apt-get build-dep rdesktop<br />
mkdir tmp<br />
cd tmp<br />
apt-get source rdesktop<br />
cd rdesktop-*<br />
wget http://www.artificialworlds.net/blog/wp-content/uploads/rdesktop-1.6.0-ungrab-on-ctrl-alt-direction.patch<br />
patch -p1 < rdesktop-1.6.0-ungrab-on-ctrl-alt-direction.patch<br />
dpkg-buildpackage -rfakeroot -b<br />
cd ..<br />
sudo dpkg -i rdesktop*.deb</div>
<p>Now someone just needs to add support for reading your window manager settings to determine automatically what shortcuts you use to switch desktops, and/or support for a config file listing keys that make rdesktop ungrab the keyboard.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/07/06/rdesktop-swallows-keyboard-events/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reclaiming desktop space with Ubuntu&#8217;s window-picker-applet</title>
		<link>http://www.artificialworlds.net/blog/2011/06/16/reclaiming-desktop-space-with-ubuntus-window-picker-applet/</link>
		<comments>http://www.artificialworlds.net/blog/2011/06/16/reclaiming-desktop-space-with-ubuntus-window-picker-applet/#comments</comments>
		<pubDate>Thu, 16 Jun 2011 14:15:16 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=447</guid>
		<description><![CDATA[For a long time I&#8217;ve customised GNOME to have a vertical task bar on the left and launcher buttons across the top. I&#8217;ve struggled with a long-standing bug with using a vertical panel, and I&#8217;ve sacrificed quite a lot of screen space to make enough room to see the window titles. Recently I&#8217;ve found myself [...]]]></description>
			<content:encoded><![CDATA[<p>For a long time I&#8217;ve customised GNOME to have a vertical task bar on the left and launcher buttons across the top.  I&#8217;ve struggled with a <a href="http://www.artificialworlds.net/blog/2008/12/10/fixing-the-vertical-panel-window-list-on-ubuntu-hardy/">long-standing bug with using a vertical panel</a>, and I&#8217;ve sacrificed quite a lot of screen space to make enough room to see the window titles.</p>
<p>Recently I&#8217;ve found myself using smaller screens, and finding certain aspects of the <a href="https://wiki.ubuntu.com/UNR">Ubuntu Netbook Remix</a> quite good.  In particular, I like the combination of <a href="https://launchpad.net/maximus">Maximus</a> and <a href="https://launchpad.net/window-picker-applet">window-picker-applet</a>, which I combine with <a href="http://do.davebsd.com/">GNOME Do</a>.  This setup allows me to have almost all of my screen set aside for programs I am using, without feeling lost or inconvenienced.</p>
<p>I need one setting to prevent Maximus from automatically maximising windows &#8211; I just want it to remove the title bar when a window is maximised, because window-picker-applet shows the title in my panel instead:</p>
<div class="code">gconftool &#8211;type bool &#8211;set /apps/maximus/no_maximize true</div>
<p>and then I add Maximus to my Startup Applications (Click Add, give it a name, and set command to &#8220;maximus&#8221;), and set GNOME Do&#8217;s &#8220;Start GNOME Do at login&#8221; preference (the Preferences screen can be found on the drop-down at the top right of the GNOME Do window).</p>
<p>Now I am happy, except for a little bug fix and visual tweak I want for window-picker-applet.  The relevant bugs are <a href="http://bugs.launchpad.net/ubuntu/+source/window-picker-applet/+bug/425813">Bug #425813</a> (see my patch at the bottom) and <a href="http://bugs.launchpad.net/ubuntu/+source/window-picker-applet/+bug/798197">Bug #798197</a>.  On an Ubuntu system it&#8217;s amazingly easy to use a patched version:</p>
<div class="code">sudo apt-get install build-essential fakeroot dpkg-dev<br />
sudo apt-get build-dep window-picker-applet<br />
mkdir tmp<br />
cd tmp<br />
apt-get source window-picker-applet<br />
cd window-picker-applet-*<br />
wget http://bugs.launchpad.net/ubuntu/+source/window-picker-applet/+bug/798197/+attachment/2171550/+files/show-windows-requring-attention-on-all-workspaces.patch<br />
patch -p1 < show-windows-requring-attention-on-all-workspaces.patch<br />
wget http://bugs.launchpad.net/ubuntu/+source/window-picker-applet/+bug/425813/+attachment/2171630/+files/faster-deeper-attention-flash.patch<br />
patch -p1 < faster-deeper-attention-flash.patch<br />
dpkg-buildpackage -rfakeroot -b<br />
cd ..<br />
sudo dpkg -i window-picker-applet_*.deb<br />
killall gnome-panel</div>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/06/16/reclaiming-desktop-space-with-ubuntus-window-picker-applet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Switching workspace in GNOME via the command line</title>
		<link>http://www.artificialworlds.net/blog/2011/03/04/switching-workspace-in-gnome-via-the-command-line/</link>
		<comments>http://www.artificialworlds.net/blog/2011/03/04/switching-workspace-in-gnome-via-the-command-line/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 17:09:42 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[GNOME]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=426</guid>
		<description><![CDATA[I use rdesktop to connect to some Windows machines, and it works beautifully. I like to allow it to grab keyboard input so I can switch and close windows on my Windows desktop without fear of accidentally doing something to the rest of my Linux desktop. However, I have never found a way of letting [...]]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://www.rdesktop.org/">rdesktop</a> to connect to some Windows machines, and it works beautifully.  I like to allow it to grab keyboard input so I can switch and close windows on my Windows desktop without fear of accidentally doing something to the rest of my Linux desktop.</p>
<p>However, I have never found a way of letting some keystrokes escape &#8211; specifically Ctrl-Alt-Left, Right, Up, Down so that I can switch workspaces (virtual desktops) away from the workspace containing rdesktop.</p>
<p>I have finally found what I hope is a good workaround &#8211; I have installed <a href="http://sourceforge.net/apps/trac/easystroke/wiki">easystroke</a> and defined some mouse gestures I can use to switch desktop.  These mouse gestures are not swallowed by rdesktop, so they still work, even when it has focus.</p>
<p>When I asked easystroke to send the Ctrl-Alt-Left etc. keystrokes, they got swallowed by rdesktop, so all I needed to be able to do complete the story was a command-line tool to switch workspace.</p>
<p>That turned out to be trickier than you might imagine, but here is my solution, using the amazing <a href="http://tomas.styblo.name/wmctrl/">wmctrl</a>.</p>
<p>This should work on GNOME with the metacity window manager, and the standard GNOME workspace switcher.  It should be easy to adapt to other window managers and workspace tools.</p>
<p>First, install some tools.  On Ubuntu you need:</p>
<div class="code">sudo apt-get install bc wmctrl coreutils grep bash</div>
<p>Now create a file with <tt>gedit ~/bin/workspace-switcher &#038;</tt> and edit it to look like this:</p>
<pre>#!/bin/bash

CMD="$1"

NUM_WORKSPACES=`gconftool-2 --get /apps/metacity/general/num_workspaces`
NUM_COLS=`gconftool-2 --get /apps/panel/applets/workspace_switcher_screen0/prefs/num_rows`

NUM_ROWS=`echo "$NUM_WORKSPACES / $NUM_COLS" | bc`

CURRENT_WS=`wmctrl -d | grep \* | cut -d " " -f 1`

MOVE_LEFT="- $NUM_ROWS"
MOVE_RIGHT="+ $NUM_ROWS"
MOVE_UP="-1"
MOVE_DOWN="+1"

case $CMD in

"Left" )
	NEW_WS=`echo $CURRENT_WS "-" $NUM_ROWS | bc`
	if [[ $NEW_WS -lt 0 ]]; then NEW_WS=$CURRENT_WS; fi
	;;

"Right" )
	NEW_WS=`echo $CURRENT_WS "+" $NUM_ROWS | bc`
	if [[ $NEW_WS -ge $NUM_WORKSPACES ]]; then NEW_WS=$CURRENT_WS; fi
	;;

"Up" )
	WS_COL=`echo $CURRENT_WS "%" $NUM_ROWS | bc`
	if [[ $WS_COL -eq 0 ]]; then
	{
		NEW_WS=$CURRENT_WS
	}
	else
	{
		NEW_WS=`echo $CURRENT_WS "- 1" | bc`
	}; fi
	;;

"Down" )
	NEW_WS=`echo $CURRENT_WS "+ 1" | bc`
	NEW_WS_COL=`echo $NEW_WS "%" $NUM_ROWS | bc`
	if [[ $NEW_WS_COL -eq 0 ]]; then NEW_WS=$CURRENT_WS; fi
	;;

* )
	NEW_WS=$CMD

esac

wmctrl -s $NEW_WS</pre>
<p>Make it executable with <tt>chmod +x ~/bin/workspace-switcher</tt> and make sure ~/bin is in your PATH.</p>
<p>You can run it like this:</p>
<div class="code">switch-workspace Left</div>
<p>to move left &#8211; the other possiblities are, obviously, Right, Up and Down.</p>
<p>Or like this:</p>
<div class="code">switch-workspace 3</div>
<p>to move to a workspace by number.</p>
<p>If you want to use it with easystroke, create an action, and for the command simply enter <tt>switch-workspace Left</tt> and similar as the command.</p>
<p>Easystroke can be installed on Ubuntu like this:</p>
<div class="code">sudo apt-get install easystroke</div>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/03/04/switching-workspace-in-gnome-via-the-command-line/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Anatomy of an interpreter: the Evaluator</title>
		<link>http://www.artificialworlds.net/blog/2011/02/12/anatomy-of-an-interpreter-the-evaluator/</link>
		<comments>http://www.artificialworlds.net/blog/2011/02/12/anatomy-of-an-interpreter-the-evaluator/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 01:54:01 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Lisp]]></category>
		<category><![CDATA[Scheme]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Test Driven]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=401</guid>
		<description><![CDATA[Posts in this series: Lexer, Parser, Evaluator I&#8217;m still really enjoying writing my Scheme interpreter Subs, which can now succesfully run all the example code from SICP up to section 2.3.4. I&#8217;ve made the changes I mentioned I would in the Lexer article, so now the Lexer returns Tokens that contain information about their basic [...]]]></description>
			<content:encoded><![CDATA[<p><em>Posts in this series: <a href="http://www.artificialworlds.net/blog/2010/09/01/anatomy-of-an-interpreter-the-lexer/">Lexer</a>, <a href="http://www.artificialworlds.net/blog/2010/09/30/anatomy-of-an-interpreter-the-parser/">Parser</a>, Evaluator</em></p>
<p>I&#8217;m still really enjoying writing my Scheme interpreter <a href="http://www.artificialworlds.net/wiki/Subs">Subs</a>, which can now succesfully run all the example code from <a href="http://mitpress.mit.edu/sicp/full-text/book/book.html">SICP</a> up to section 2.3.4.  I&#8217;ve made the changes I mentioned I would in the <a href="http://www.artificialworlds.net/blog/2010/09/01/anatomy-of-an-interpreter-the-lexer/">Lexer</a> article, so now the Lexer returns Tokens that contain information about their basic types, and I&#8217;ve gone through a significant refactoring to replace one of the several massive switch statements with a virtual function call (<a href="http://www.c2.com/cgi/wiki?SwitchStatementsSmell">Martin Fowler would be proud</a>).</p>
<p>Last time I explained how the <a href="http://www.artificialworlds.net/blog/2010/09/30/anatomy-of-an-interpreter-the-parser/">Parser</a> takes the stream of tokens coming from the Lexer and returns a hierarchical tree of Values, each of which represents an operation or thing in the program.</p>
<p>The Evaluator takes in a tree of Values, &#8220;evaluates&#8221; it, and returns another Value object, which is the answer.  The Evaluator class is by far the most complex part of Subs, so in this post we&#8217;ll start with an overview of how it works.  Future posts will break down the different parts in more detail.</p>
<p>The most interesting parts of the <a href="http://subs-scheme.git.sourceforge.net/git/gitweb.cgi?p=subs-scheme/subs-scheme;a=blob;f=lib/evaluator.cpp;h=c218e2775cb2a97ccfc61ee0bef5c52fabe247e6;hb=0a924579707685d8c65decaa5f289f1300dee9dc">Evaluator</a> class interface look like this:</p>
<pre>class Evaluator
{
public:
    std::auto_ptr&lt;Value&gt; EvalInContext( const Value* value,
        boost::shared_ptr&lt;Environment&gt;&#038; environment );
};</pre>
<p>The EvalInContext method takes in a Value to evaluate, and an &#8220;environment&#8221; *in which to evaluate it.  Note that the in the real code it takes a couple more arguments, including a mysterious and annoying boolean called <tt>is_tail_call</tt> which will be explained later.</p>
<blockquote><p>* More on environments later.  All you need to know for now is that they provide a way of keeping hold of all the things we currently know about, identified by name.</p></blockquote>
<p>A very simplified version of EvalInContext would look like this:</p>
<pre>std::auto_ptr&lt;Value&gt; Evaluator::EvalInContext( const Value* value,
    boost::shared_ptr&lt;Environment&gt;&#038; environment )
{
    if( is_symbol( value ) )
    {
        return eval_symbol( value, environment );
    }

    if( !is_combination( value ) )
    {
        return auto_ptr&lt;Value&gt;( value-&gt;Clone() );
    }

    const CombinationValue* combo = to_combination( value );
    CombinationValue::const_iterator it = combo-&gt;begin();

    auto_ptr&lt;Value&gt; evaldoptr = EvalInContext( *it, environment );

    if( special_symbol( evaldoptr ) )
    {
        return process_special_symbol( evaldoptr, combo );
    }
    else
    {
        ++it;

        CombinationValue argvalues;
        for( ; it != combo-&gt;end(); ++it )
        {
            argvalues.push_back( EvalInContext( *it, environment ).release() );
        }

        return run_procedure( evaldoptr.get(), &#038;argvalues, *this, environment );
    }
}</pre>
<p>If the Value to be evaluated is just a symbol, we call <tt>eval_symbol</tt> which basically looks up the symbol&#8217;s name in the environment and returns the value it finds.</p>
<p>If the Value is not a combination (i.e. the root of a tree of other values) it must be a basic type such as a string or an integer.  In this case we simple copy the Value and return it.</p>
<p>Otherwise, it&#8217;s a combination.  To evaluate a combination, we follow the &#8220;eval-apply&#8221; pattern.  The principle is to evaluate all the Values in the combination separately, and then &#8220;apply&#8221; (run) the first value (the &#8220;operator&#8221;) as a procedure, using the other values as arguments.  The first value must evaluate to something that is recognisable as a procedure, or this doesn&#8217;t make sense and we will throw an error.</p>
<p>In practice it&#8217;s a tiny bit more complicated.  We evaluate the first Value in the combination (by calling EvalInContext recursively), then we check whether it&#8217;s a special symbol such as <tt>if</tt> or <tt>let</tt> and if so, deal with it separately.  Otherwise, we evaluate all the other Values (calling EvalInContext recursively again) and put them into a new CombinationValue, and pass the operator and the arguments to <tt>run_procedure</tt>, which looks something like this:</p>
<pre>std::auto_ptr&lt;Value&gt; run_procedure( const Value* operator,
    const CombinationValue* args, Evaluator&#038; ev,
    boost::shared_ptr&lt;Environment&gt;&#038; environment )
{
    if( is_builtin_procedure( operator ) )
    {
        return handle_builtin_procedure( operator, args, environment );
    }
    else
    {
        std::auto_ptr&lt;Value&gt; ret;

        const CompoundProcedureValue* proc = to_compound_procedure( operator );

        boost::shared_ptr&lt;Environment&gt; new_env =
            proc-&gt;ExtendEnvironmentWithArgs( args );

        for( CombinationValue::const_iterator it = proc-&gt;GetBody()-&gt;begin();
            it != proc-&gt;GetBody()-&gt;end(); ++it )
        {
            ret = ev.EvalInContext( *it, new_env );
        }

        return ret;
    }
}</pre>
<p>Running a procedure means either doing something built-in (for example adding up two numbers and returning the result) or evaluating some other code, which comes from the definition of the procedure being run.  First we call ExtendEnvironmentWithArgs to create a new Environment, which contains the argument Values that were supplied, and then we loop through all the sections of the body of the procedure, evaluating each one.  Note that we throw away the returned Values for all sections except the last one (this is how Scheme works).</p>
<p>Once we&#8217;ve evaluated and applied our procedure, which of course potentially includes numerous recursive calls to EvalInContext, we end up with a Value that is returned, and we&#8217;re done.</p>
<p>Simple eh?</p>
<p>But now I must make a confession: almost everything I have written above is lie.  Why would I lie to you?  Because I missed out something wonderful and strange called &#8220;tail-call optimisation&#8221;.  I&#8217;ll explain next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/02/12/anatomy-of-an-interpreter-the-evaluator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to ask technical questions in person</title>
		<link>http://www.artificialworlds.net/blog/2011/02/12/how-to-ask-technical-questions-in-person/</link>
		<comments>http://www.artificialworlds.net/blog/2011/02/12/how-to-ask-technical-questions-in-person/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 00:27:38 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=365</guid>
		<description><![CDATA[In a healthy team performing a technical task, there will be a lot of questions. Those questions will sometimes be asked by those with less technical knowledge, but (in a healthy team) there will be plenty of questions going back the other way too. Questions that come up in the normal course of your work [...]]]></description>
			<content:encoded><![CDATA[<p>In a healthy team performing a technical task, there will be a lot of questions.  Those questions will sometimes be asked by those with less technical knowledge, but (in a healthy team) there will be plenty of questions going back the other way too.  Questions that come up in the normal course of your work are the main way knowledge is going to be transferred amongst your team members.  They are to be encouraged, and you should never feel like a nuisance, or a technical wimp, because you&#8217;re asking them.</p>
<p>It&#8217;s easy to imagine, when you&#8217;re asking someone a question, that whether you get a good answer depends mainly on the person you&#8217;re asking.</p>
<p>In fact, an awful lot depends on you.</p>
<p>To get a good answer to a question, you need to prepare, to manage the Zone, and above all, to make the person you are asking feel clever.</p>
<p><em>What follows are some tips on how to ask a technical person a technical question when you&#8217;re in the same room as them.  Some of them may also apply to asking on the phone, or even via instant messaging.</em></p>
<h3>1. Prepare</h3>
<p>You&#8217;re about to ask someone a question.</p>
<p>Breathe.</p>
<p>Think about what you are hoping to find out.  This might sound obvious, but when you&#8217;re in the thick of trying to solve a problem, you may find you&#8217;re actually quite confused about what you&#8217;re doing.  If you can, you want to avoid wasting the other person&#8217;s time with your confusion.  Even worse, you might confuse them, and then they won&#8217;t feel clever.</p>
<p>This doesn&#8217;t need to take long &#8211; it may take half a second, but just let it cross your mind &#8211; what do I want to find out?</p>
<p>Think about the other person: what are they doing right now?  Is it related?  What do they know about?  From what angle will they be approaching your question?  Again, this will probably take almost no time at all, but it will help you ask your question well.</p>
<p>Now you need to zoom out.  You are deep into a problem, so deep in fact that you&#8217;re stuck on a very specific part of it.  This part of it is burning into your consciousness, obscuring the wider picture of what you&#8217;re doing.  The person you&#8217;re asking is going to need that wider picture, so remind yourself what it is.</p>
<p>Once you&#8217;ve zoomed out, you will need to engage with the Zone.</p>
<h3>2. Manage the Zone</h3>
<p>The biggest problem you have when asking a technical person a technical question is that they may well be in the Zone.  The Zone is a state of intense concentration in which you get really good work done (Rands elaborates in <a href="http://www.randsinrepose.com/archives/2006/07/10/a_nerd_in_a_cave.html">A Nerd in a Cave</a>).  The thing about the Zone is that it is difficult (sometimes even painful) to come out of.</p>
<p>If the person you&#8217;re asking is in the Zone, they will need to be coaxed out.  When you start talking, even if they turn and look at you and say something encouraging, they are somewhere far away, solving a problem.  Your problem is an unwelcome intrusion.</p>
<p>The first lesson about the Zone is: don&#8217;t say much at first.</p>
<p>When you start talking the other person doesn&#8217;t know whether you&#8217;re going to offer them a cup of tea, talk politics, or ask them how to implement quicksort.  They haven&#8217;t disengaged at all from the problem they are working on.  You need to let them know you are going to ask them a technical question, and start the painful process of pulling them out of their problem, and into yours.</p>
<p>Often the best thing to do is pick a single word or phrase that lets them know the general area you are talking about: for example, &#8220;import&#8221;, or &#8220;the C++ standard&#8221;, or &#8220;garbage collection&#8221;.  If you say something like that, and watch their eyes, you can almost see the glaze of the Zone lifting.</p>
<p>If you can see they&#8217;re still elsewhere, give them a second &#8211; maybe they&#8217;ll even say something like, &#8220;I just want to finish this line.&#8221;  If they do, let them &#8211; step back, take the pressure off &#8211; they will be much better able to answer you when the thing they need to remember is written down.</p>
<p>Now your job is to zoom them in on your problem, at their pace.  It&#8217;s very important to watch and listen to the other person while you do this.  Give them a problem area, and check they understood what you meant.  Now give them closer context &#8211; maybe the directory you&#8217;re talking about, or the DLL you&#8217;re working on.  Now tell them what class you&#8217;re editing, or what file.</p>
<p>As soon as you can see it&#8217;s needed, be quick to show them the exact thing you&#8217;re doing on your screen or paper &#8211; that way they can add any extra context they need themselves.  Be very wary of drawing vague diagrams on paper or a whiteboard &#8211; they confuse more often than they enlighten &#8211; much better to show them the real code or document you are working on.  They can handle it.</p>
<p>All the time, watch how they are reacting &#8211; are they remembering what you&#8217;re talking about, or completely in the dark?  You may need to choose a different way into the problem.  Remember, at this stage it&#8217;s your job to explain what you mean, not their job to guess.</p>
<p>If you do this well, they&#8217;re slightly in the Zone again, but this time focussed on your problem area.  Now, and only now, hit them with your question.  They&#8217;ll know exactly what you&#8217;re talking about, and feel really clever, especially if they know the answer.</p>
<p>There are a couple other things you need to know about the Zone.  As we know, it can be painful to be pulled out of the Zone.  That means that the person you&#8217;re talking to, no matter how nice they are, and how much they like you, may feel a distinct feeling of irritation when you start talking.  To make matters worse, they were concentrating, so probably frowning already.  Even if they don&#8217;t feel any irritation at all, they may look like they do.  What can you do about this?  Not a lot, except don&#8217;t take it personally &#8211; it&#8217;s normally momentary, and experienced technical people will recognise it&#8217;s a false feeling, almost a physical reaction, and put it to one side immediately.</p>
<p>Finally, understanding the Zone explains why preparation is so important.  It&#8217;s very likely you are in the Zone yourself at the beginning of this process.  You are submerged in a difficult problem, and quite possibly deeply irritated by your inability to solve it.  To ask a question effectively (and thus get a good answer) you need to pull yourself out of the Zone and back into human interaction mode.  This includes ensuring your annoyance is fully dissipated, or you&#8217;re going to say something you shouldn&#8217;t.</p>
<p>Throughout all this you need to make it your mission to make the other person feel clever.</p>
<h3>3. Make them feel clever</h3>
<p>Why would you want to make the person you&#8217;re asking feel clever?</p>
<p>I certainly don&#8217;t mean flatter them.  If they&#8217;re deep in their work they don&#8217;t want you to waste their time telling them how good they are at something.</p>
<p>Think about it this way: how likely is it that you&#8217;ll get an answer if you&#8217;ve made them feel stupid?  I don&#8217;t mean you won&#8217;t get an answer because they&#8217;re too annoyed with you to bother &#8211; I mean they&#8217;re feeling stupid because you&#8217;ve confused them, and so they have no idea what the answer is.</p>
<p>Bear in mind that it&#8217;s really easy to confuse someone.  In your technical problem area there are thousands, or possibly even millions, of tiny micro-contexts that make sense within themselves, but sound like gibberish if you&#8217;re outside that context.</p>
<p>Turning to someone and saying something like, &#8220;How do I Frobnish the Pernicator?&#8221; without first reminding them that Pernicators get created every time the TunableBeadnest is RePreppered is very hard work for them: they need to ask you a series of questions before they can work out what you&#8217;re asking.  Making them do this work makes them feel like they aren&#8217;t clever enough to hold the entire knowledge of your arena in the front of their mind simultaneously.  Of course, no-one is able to do this, but everyone feels like they ought to be.  Don&#8217;t make them feel stupid.</p>
<p>Even worse is to say something like, &#8220;How do I call this method?&#8221;  In this case, even if they had total front-of-brain memory of the entire arena, they still couldn&#8217;t answer this question, without interrogating you about what you meant.</p>
<p>You goal should be that the first thing they have to say in the whole interaction is when they give you the answer, or at least ask a question that shows they have grasped what you&#8217;re asking, and makes them feel clever.</p>
<p>Of course, making them feel clever also makes them more inclined to talk to you next time you have a question, but that&#8217;s merely a side benefit.  The real reason you want to make them feel clever is that when they feel like that, it means you have given them the information they need, in the order they want, with timing that works for them, so that they can give you a great answer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2011/02/12/how-to-ask-technical-questions-in-person/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scalable Graph Coverage</title>
		<link>http://www.artificialworlds.net/blog/2010/06/21/scalable-graph-coverage/</link>
		<comments>http://www.artificialworlds.net/blog/2010/06/21/scalable-graph-coverage/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 00:25:47 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[BOOST]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Writing]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=310</guid>
		<description><![CDATA[If you&#8217;re interested in dealing with large directed graphs of dependent objects and want some tips on how to process them in a way that scales in terms of memory usage, you may be interested in the article I wrote for Overload, which is a journal of the ACCU (an organisation promoting &#8220;professionalism in programming&#8221;). [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re interested in dealing with large directed graphs of dependent objects and want some tips on how to process them in a way that scales in terms of memory usage, you may be interested in the article I wrote for <a href="http://accu.org/index.php/overloadonline">Overload</a>, which is a journal of the <a href="http://accu.org">ACCU</a> (an organisation promoting &#8220;professionalism in programming&#8221;).</p>
<p>The article is <a href="http://accu.org/index.php/journals/1632">Scalable Graph Coverage</a>, or, in my original title, &#8220;Comparing scalable algorithms for walking all nodes of a dependency graph&#8221;.</p>
<p>It contains lots of code, written in C++, using BOOST Graph Library.  The code demonstrates some of the algorithms that are available for choosing batches of nodes to be processed together to reduce the number of nodes that are loaded several times, and without running out of memory.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2010/06/21/scalable-graph-coverage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu Lucid upgrade &#8211; a catalogue of disaster and pain</title>
		<link>http://www.artificialworlds.net/blog/2010/05/14/ubuntu-lucid-upgrade-a-catalogue-of-disaster-and-pain/</link>
		<comments>http://www.artificialworlds.net/blog/2010/05/14/ubuntu-lucid-upgrade-a-catalogue-of-disaster-and-pain/#comments</comments>
		<pubDate>Fri, 14 May 2010 10:37:33 +0000</pubDate>
		<dc:creator>Andy Balaam</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.artificialworlds.net/blog/?p=288</guid>
		<description><![CDATA[I recently upgraded 3 machines to Lucid. I don&#8217;t recommend it. Broken after upgrade 2 out of 3 machines did not boot after upgrade to Lucid. One, an upgrade from Hardy, crashed hard during the upgrade (the screen was frozen with a prompt about lmsensors visible). It&#8217;s possible this was caused by a hardware issue [...]]]></description>
			<content:encoded><![CDATA[<p>I recently upgraded 3 machines to Lucid.  I don&#8217;t recommend it.</p>
<h3>Broken after upgrade</h3>
<p>2 out of 3 machines did not boot after upgrade to Lucid.</p>
<p>One, an upgrade from Hardy, crashed hard during the upgrade (the screen was frozen with a prompt about lmsensors visible).  It&#8217;s possible this was caused by a hardware issue of some kind, but it&#8217;s behaved itself since.  When I powered off the machine it failed to boot because grub couldn&#8217;t see my hard drive.  I believe this was because the file system had been changed in some way (to ext4?) but grub hadn&#8217;t been upgraded because of the crash, so it couldn&#8217;t handle it.</p>
<p>Anyway, I spent a day trying to recover the system, and then a night rebuilding from scratch.  I&#8217;m still configuring the system and regretting the upgrade.</p>
<p>The second, a netbook with a fairly standard Karmic install on it, upgraded smoothly and worked.</p>
<p>The third, my work machine, upgraded smoothly from Karmic, and frigged my fstab so my second drive wasn&#8217;t found.  It changed my main drive to be identified by a UUID (instead of being /dev/sda), and this meant my second drive, which used to be /dev/sdb was now called /dev/sda.  The upgrade failed to correct this in my fstab and gave me a very rude error during boot.</p>
<p>Fortunately I had the technical knowledge and found the time to fix these things, but it&#8217;s hardly something I&#8217;d like someone like my parents to have to deal with.</p>
<h3>Annoying after upgrade</h3>
<ul>
<li>My volume applet disappeared. <a href="http://bugs.launchpad.net/ubuntu/+source/gnome-media/+bug/552221">Bug 552221</a></li>
<li>Empathy doesn&#8217;t tell me about messages any more.  When I enable the stupid indicator applet, I get a tiny yellow star when a new message has arrived.  I can&#8217;t get an Empathy applet to appear in the status area.</li>
<li>Thunderbird 3 thrashed my disk and network for a couple of days to download and index all my IMAP mail.  It is faster now, though.</li>
<li>I can&#8217;t get Thunderbird to give me a &#8220;Calendar&#8221; link in the bottom left to switch to the Lightning plugin.  I did find the &#8220;LightningButton&#8221; add-on that allows me to have a button on the toolbar.  Yes, you are reading that correctly.</li>
</ul>
<p>I loved Karmic.  It got me all excited about Ubuntu again.  I wish I&#8217;d stuck with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artificialworlds.net/blog/2010/05/14/ubuntu-lucid-upgrade-a-catalogue-of-disaster-and-pain/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

