<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>www.hans-eric.com</title>
	
	<link>http://www.hans-eric.com</link>
	<description>Hans-Eric Grönlund on software development</description>
	<pubDate>Tue, 09 Jun 2009 15:20:04 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<geo:lat>60.666667</geo:lat><geo:long>17.132975</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><image><link>http://www.hans-eric.com</link><url>http://www.hans-eric.com/hans-eric.png</url><title>Hans-Eric Grönlund</title></image><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/hans-eric" type="application/rss+xml" /><feedburner:emailServiceId>hans-eric</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Method Reference Events? Nah, Not Yet.</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/wLIM9VqZdUg/</link>
		<comments>http://www.hans-eric.com/2009/06/05/method-reference-events-nah-not-yet/#comments</comments>
		<pubDate>Fri, 05 Jun 2009 11:59:41 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[opinion]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=150</guid>
		<description><![CDATA[In my previous post I discussed the problem that method pointers aren’t able to store references to anonymous methods. Unfortunately that limitation makes anonymous methods less useful since they can’t be used to set up event handlers on the fly, like so:

// Wouldn't it be great
// if we could do something
// like this?

Memo1.OnKeyPress :=
  [...]]]></description>
			<content:encoded><![CDATA[<p>In <a title="CodeGear, Please Fix the Anonymous Method Asymmetry" href="http://www.hans-eric.com/2009/06/03/codegear-please-fix-the-anonymous-method-assymetry/">my previous post</a> I discussed the problem that method pointers aren’t able to store references to anonymous methods. Unfortunately that limitation makes anonymous methods less useful since they can’t be used to set up event handlers on the fly, like so:</p>
<pre><code>
// Wouldn't it be great
// if we could do something
// like this?

Memo1.OnKeyPress :=
  procedure(Sender: TObject; var Key: Char)
  begin
    Key := Chr(Ord(Key) + 1);
  end;
</code></pre>
<p>One thing I wasn’t aware of when I wrote that previous post is that while method pointers can’t be used to store anonymous methods, the opposite is true: Method references can indeed store both anonymous methods and instance methods. Many thanks to <a href="http://barrkel.blogspot.com/">Barry Kelly</a> who pointed it out to me in <a href="http://www.hans-eric.com/2009/06/03/codegear-please-fix-the-anonymous-method-assymetry/#comment-32280">a comment</a>.</p>
<p>Could this be the way to go? Shall we all start using method references instead of method pointers when we declare the events of our components from now on? Let’s take a look shall we? But just so that we’re clear with what we mean – there are many ways to say the same thing - here are the definitions I’m using in this post.</p>
<p><strong></strong>First of all, when I say method I mean either a function or a procedure, and it can be any of the types below. This is different from <a title="Wikipedia: Definition of Method" href="http://en.wikipedia.org/wiki/Method_(computer_science)">the common definition</a> stating that methods are subroutines associated with either a class or an object.</p>
<p><strong><em>Plain methods</em></strong><br />
These are functions and procedures declared outside the context of a class.</p>
<pre><code>procedure PlainProcedure;
begin
  // Has no Self pointer
end;</code></pre>
<p><strong><em>Instance methods</em></strong><br />
Functions or procedures associated to an object instance</p>
<pre><code>Procedure TSomeClass.InstanceProcedure;
begin
  // Self is an instance of TSomeClass
end;
</code></pre>
<p><strong><em>Class methods</em></strong><br />
Functions or procedures associated to a class. In other languages also called static methods.</p>
<pre><code>class procedure TSomeClass.ClassProcedure;
begin
  // Self is TSomeClass
end;
</code></pre>
<p><em><strong>Anonymous methods</strong></em><br />
Functions or procedures declared as they are assigned in an execution context. These methods capture the surrounding context and may use local variables and arguments even if they’re out of execution scope.</p>
<pre><code>SomeItems.Sort(
  function(Item1, Item2: TSomeItem): Integer;
  begin
    if Item1.Value &gt; Item2.Value then
      Result := 1
    else if Item1.Value &lt; Item2.Value then
      Result :=  -1
    else
      Result := 0;
    end
  );
</code></pre>
<p>For these four types of methods there are <em>three reference types</em> to store pointers for later invocation of the methods.</p>
<p><em><strong>Plain method pointer</strong></em></p>
<pre><code>type TPlainMethodPointer =
  procedure(ASender: TObject);</code></pre>
<p><em><strong>Method pointers</strong></em></p>
<pre><code>type TMethodPointer =
  procedure(ASender: TObject) of object;</code></pre>
<p><em><strong>Method references</strong></em></p>
<pre><code>type TMethodReference =
  reference to procedure(ASender: TObject);</code></pre>
<p>This compatibility graph shows what method types can be stored with the respective reference type.</p>
<table border="1">
<tbody>
<tr>
<th></th>
<th>Plain</th>
<th>Instance</th>
<th>Class</th>
<th>Anonymous</th>
</tr>
<tr>
<th>Plain method pointer</th>
<td>YES</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<th>Method pointer</th>
<td>no</td>
<td>YES</td>
<td>YES</td>
<td>no</td>
</tr>
<tr>
<th>Method reference</th>
<td>YES</td>
<td>YES</td>
<td>YES</td>
<td>YES</td>
</tr>
</tbody>
</table>
<p>From this graph we can see that the Method reference type is the unifying type that can store all types of method references. It seems like the way to go is to embrace Method references and render the other reference types obsolete. Is it possible? The answer is yes but no.</p>
<p>Take the event example of my last post. The VCL can not be changed to utilize Method pointers for backward compatibility reasons (like the widespread use of TMethod casts) so there’s nothing to do about it there. But what about our own components, and components created from now on?</p>
<pre><code>
type
  TNotifyMethod = reference to procedure(Sender: TObject);

  TMyComponent = class(TComponent)
    ...
  published
    property OnChange: TNotifyMethod read FOnChange write FOnChange;
  end;
</pre>
<p></code></p>
<p>Well, it works fine as long as you set up the event handlers (OnChange in the above example) dynamically, but the method reference type events do not play well with the Delphi 2009 IDE. The object inspector doesn’t recognize possible event handlers and won’t create one automatically I you double click the event property. If you try to force the assignment by giving the name of an existing event handler method explicitly, the IDE throws an ugly Invalid Property Error Dialog.</p>
<p><img class="alignnone size-medium wp-image-151" title="Invalid property error" src="http://www.hans-eric.com/wp-content/uploads/2009/06/error-300x145.png" alt="Invalid property error" width="300" height="145" /></p>
<p>As much as I’d like to be able to assign anonymous methods as event handlers to my components’, I’m not prepared to sacrifice the IDE integration. Hopefully CodeGear will fix this issue in future releases but until then anonymous methods will remain less useful than they could be.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=wLIM9VqZdUg:XZTHkfNDXSw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=wLIM9VqZdUg:XZTHkfNDXSw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=wLIM9VqZdUg:XZTHkfNDXSw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=wLIM9VqZdUg:XZTHkfNDXSw:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=wLIM9VqZdUg:XZTHkfNDXSw:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/wLIM9VqZdUg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2009/06/05/method-reference-events-nah-not-yet/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2009/06/05/method-reference-events-nah-not-yet/</feedburner:origLink></item>
		<item>
		<title>CodeGear, Please Fix the Anonymous Method Assymetry</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/9HhuS-p9Lo0/</link>
		<comments>http://www.hans-eric.com/2009/06/03/codegear-please-fix-the-anonymous-method-assymetry/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 20:25:08 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[opinion]]></category>

		<category><![CDATA[programming]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=135</guid>
		<description><![CDATA[As I noted in my previous post, anonymous methods is a big new feature in Delphi 2009 for the Win32 platform. While “closures” is natural and much appreciated in other languages, most notably Ruby, the Delphi community is still a bit reluctant and hesitant. Segunda Feira put words on it in his post on the [...]]]></description>
			<content:encoded><![CDATA[<p>As I noted <a title="Welcome Back Delphi" href="http://www.hans-eric.com/2009/02/09/welcome-back-delphi/">in my previous post</a>, anonymous methods is a big new feature in Delphi 2009 for the Win32 platform. While “closures” is natural and much appreciated in other languages, most notably Ruby, the Delphi community is still a bit reluctant and hesitant. Segunda Feira put words on it in <a title="Anonymous methods - when should they be used?" href="http://delphidicas.blogspot.com/2008/08/anonymous-methods-when-should-they-be.html">his post on the subject</a>.</p>
<blockquote><p>I am still not convinced that this convenience is worth getting all that excited about - It has not enabled anything that was previously impossible, nor even especially difficult either to implement or to understand</p>
<p>[...]</p>
<p>anonymous methods should be used <em>only</em> when you absolutely have to, and so far I have not yet seen an example where anonymous methods are the only way to achieve anything</p></blockquote>
<p>I agree that more often than not a problem can be solved with equal elegance using a pure object orientated approach, but there are situations where anonymous methods may actually be the better alternative. One situation that comes to mind is the setting up of test fixtures.<br />
Say, for instance, that we want to test the event firing mechanism of a component. An easy way to set this up could be like the following.</p>
<pre><code>procedure TestSomeComponent.TestOnChange;
var
  SUT: TSomeComponent;
  OnChangeFired: Boolean;
begin
  OnChangeFired := False;
  // Set up the fixture
  SUT := CreateTheComponentToTest;
  SUT.OnChange :=
    procedure(ASender: TObject)
    begin
      OnChangeFired := True;
      CheckSame(SUT, ASender, 'The Sender event argument should be set');
    end;
  // Perform operation
  SUT.Text := 'Some text';
  // Check the result
  CheckTrue(OnChangeFired, 'Setting the Text property should fire the OnChange event');
end;
</code></pre>
<p>The above code checks that the component’s OnChange event is fired when the Text property is set, and that the component is set as the Sender reference to the event handler. Except for being more compact, the biggest advantage to using anonymous methods in this scenario is that we avoid <a href="http://xunitpatterns.com/Obscure%20Test.html">the obscure test smell</a> and that we don’t have to clutter our test class with an instance variable (like FOnChangeFired) to identify if the event was really fired or not.</p>
<p><strong>The only problem is: it doesn’t work</strong>. Why? Well, because the OnChange property is most likely of an instance method reference type (i.e. TNotifyEvent), meaning it doesn&#8217;t accept a references to an anonymous method even if it has the same signature.</p>
<pre><code>type TNotifyEvent = procedure(ASender: TObject) <strong>of object</strong>;</code></pre>
<p>For our code to compile we need to redeclare TNotifyEvent and remove the “of object” keywords and instead use the method reference type.</p>
<pre><code>type TNotifyEvent = <strong>reference to</strong> procedure(ASender: TObject);</code></pre>
<p>But of course, that’s not an option. It would mean that the traditional way of setting up an event handler (by using an instance method) would not work.</p>
<p>I see a definite problem with how the Delphi language explicitly forces you to distinguish between instance methods (and class methods for that matter) and anonymous method references, even though they share the same signature.<br />
This is most unfortunate since I feel that the situations where we’d like to support both kinds of event handlers are quite common. And with the current semantics we have to use code duplication in order to achieve that. Like the two Synchronize methods of the built in TThread class.</p>
<p>In Delphi 2009 an overloaded variant of the TThread.Synchronize method was introduced, one that make use of anonymous methods. Here are snippets from that code:</p>
<pre><code>
type
  TThreadMethod = procedure of object;
  TThreadProcedure = reference to procedure;
...
  class TThread = class
    …
    procedure Synchronize(AMethod: TThreadMethod); overload;
    procedure Synchronize(AThreadProc: TThreadProcedure); overload;
    ...
  end;</code></pre>
<p>The two methods have almost identical implementations. The only real difference is the type of the argument.</p>
<pre><code>procedure TThread.Synchronize(AMethod: TThreadMethod);
begin
  FSynchronize.FThread := Self;
  FSynchronize.FSynchronizeException := nil;
  FSynchronize.FMethod := AMethod;
  FSynchronize.FProcedure := nil;
  Synchronize(@FSynchronize);
end;

procedure TThread.Synchronize(AThreadProc: TThreadProcedure);
begin
  FSynchronize.FThread := Self;
  FSynchronize.FSynchronizeException := nil;
  FSynchronize.FMethod := nil;
  FSynchronize.FProcedure := AThreadProc;
  Synchronize(@FSynchronize);
end;</code></pre>
<p>I may be overly sensitive, but code like that really disturbs me. Unfortunately it gets worse. If we follow the execution chain down into the Synchronize class method that is invoked by the two, we find this.</p>
<pre><code>class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
var
  SyncProc: TSyncProc;
  SyncProcPtr: PSyncProc;
begin
  if GetCurrentThreadID = MainThreadID then
  begin
    <strong>if Assigned(ASyncRec.FMethod) then
      ASyncRec.FMethod()
    else if Assigned(ASyncRec.FProcedure) then
      ASyncRec.FProcedure();
    </strong>end else
      …
end;</code></pre>
<p>It would be a lot nicer if the two reference types were joined under a common reference type. And I can’t see why it couldn’t be done. When I look at the “of object” keywords I get a feeling that <em>the language is leaking compiler implementation</em> through the language interface; information that is indifferent to the developer. What matters from a callers’ perspective is the method signature, not whether the method has a self pointer or not.</p>
<p>I hope CodeGear recognizes this problem and find a way to clean this assymetry from the language. Anonymous methods would be so much more useful if they do.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=9HhuS-p9Lo0:9Qe_ZQDz_Z0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=9HhuS-p9Lo0:9Qe_ZQDz_Z0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=9HhuS-p9Lo0:9Qe_ZQDz_Z0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=9HhuS-p9Lo0:9Qe_ZQDz_Z0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=9HhuS-p9Lo0:9Qe_ZQDz_Z0:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/9HhuS-p9Lo0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2009/06/03/codegear-please-fix-the-anonymous-method-assymetry/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2009/06/03/codegear-please-fix-the-anonymous-method-assymetry/</feedburner:origLink></item>
		<item>
		<title>Welcome Back Delphi</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/S5RMrCxzuj8/</link>
		<comments>http://www.hans-eric.com/2009/02/09/welcome-back-delphi/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 16:37:41 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Delphi 2009]]></category>

		<category><![CDATA[Rapid Application Development]]></category>

		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=128</guid>
		<description><![CDATA[Several years ago I said goodbye to the programming language in which I took my first stumbeling steps as a coder. I had moved on and there were no reasons to believe I&#8217;d ever go back. I was wrong. A reason emerged and Delphi 2009 now has a place, both in my computer - and [...]]]></description>
			<content:encoded><![CDATA[<p>Several years ago <a title="Rest In Peace Delphi" href="http://www.hans-eric.com/2007/09/02/rest-in-peace-delphi/">I said goodbye</a> to the programming language in which I took my first stumbeling steps as a coder. I had moved on and there were no reasons to believe I&#8217;d ever go back. I was wrong. A reason emerged and Delphi 2009 now has a place, both in my computer - and in my heart.</p>
<p><img class="alignnone size-medium wp-image-129" title="Delphi 2009 comes with a great IDE" src="http://www.hans-eric.com/wp-content/uploads/2009/02/delphi-2009-ide-300x227.png" alt="Delphi 2009 comes with a great IDE" width="300" height="227" /></p>
<p><strong>A sort of homecoming</strong></p>
<p>Firing up the new IDE from CodeGear with Delphi for Win32 felt a lot like coming home. The outstanding graphical editor was there as was the lightning fast compiler. Visual Studio is great in many ways but it can&#8217;t compete with CodeGear&#8217;s RAD Studio when it comes to speed and rapid application development.</p>
<p>Not only that, the language (Object Pascal) has finally woken from its stagnated state and is getting increasingly modern. It now implements, for instance, closures (anonymous methods) which is quite rare for a non garbage collected language.</p>
<pre><code>type
  TClosureProc = reference to procedure(AMsg: string);

function CreatePrefixedWriter(APrefix: string): TClosureProc;
begin
  Result := procedure(AMsg: string)
  begin
    WriteLn(APrefix + AMsg);
  end;
end;

var
  Log: TClosureProc;

begin
  Log := CreatePrefixedWriter('Closure Test: ');
  Log('Write this');
  Log('And this');
end.
</code></pre>
<p>The above program should produce the following output.</p>
<p><code>Closure Test: Write this<br />
Closure Test: And this<br />
</code></p>
<p><strong>I gotta wear shades</strong></p>
<p>I am not the only one being thrilled with the rebirth of Delphi. A look at the <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">TIOBE Programming Community Index</a> for February shows that Delphi is the 9th most popular programming language, with a steady increase. That is a lot better than the 15th position a year and a half ago. At that time Delphi felt like a marginalized language with little promises for the future; Now it feels alive and vibrant.</p>
<p>Since the magic is back, I think I&#8217;ll stick around for a while.</p>
<p>Cheers</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=S5RMrCxzuj8:2KgRPnXZCDA:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=S5RMrCxzuj8:2KgRPnXZCDA:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=S5RMrCxzuj8:2KgRPnXZCDA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=S5RMrCxzuj8:2KgRPnXZCDA:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=S5RMrCxzuj8:2KgRPnXZCDA:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/S5RMrCxzuj8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2009/02/09/welcome-back-delphi/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2009/02/09/welcome-back-delphi/</feedburner:origLink></item>
		<item>
		<title>Don’t touch my Alt Gr Button</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/0k-R0IJkYTY/</link>
		<comments>http://www.hans-eric.com/2008/10/07/dont-touch-my-alt-gr-button/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 08:23:38 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[opinion]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=125</guid>
		<description><![CDATA[I just downloaded and installed the HTML-Kit editor to see if it can help me in the WordPress Theme development projects I just started. Until now I&#8217;ve been relying upon the built in editor of the admin interface, handy for small changes but not for building themes from scratch.
Anyway, HTML-Kit was supposedly an excellent HTML [...]]]></description>
			<content:encoded><![CDATA[<p>I just downloaded and installed the <a href="http://www.htmlkit.com/">HTML-Kit editor</a> to see if it can help me in the WordPress Theme development projects I just started. Until now I&#8217;ve been relying upon the built in editor of the admin interface, handy for small changes but not for building themes from scratch.</p>
<p>Anyway, HTML-Kit was supposedly an excellent HTML editor and at a first glance it seemed good enough. That was until I tried to hit the &#8221; (double quotation marks) key. Instead of inserting the expected character into the html document I was currently editing, HTML-Kit threw me a new MDI window containing a fresh HTML document. As if I&#8217;d pressed Ctrl-N(ew) or something.</p>
<p>What was going on? Well, it turned out that the default shortcuts of HTML-Kit was interfering with <a title="Tools of the Effective Developer: Touch Typing" href="http://www.hans-eric.com/2007/12/06/tools-of-the-effective-developer-touch-typing/">my custom keyboard layout</a>. (This has happened to me with other editors as well.) My layout takes advantage of the Alt Gr button to move common special characters, like the &#8221; character, from the top row to the base row, all for the sake of speed and ergonomy.</p>
<p>On my keyboard, to strike the &#8221; key I have to press Alt Gr + L, which is actually Alt Gr + N since I base my layout on Dvorak, and since pressing Alt Gr is the same as pressing Alt + Ctrl this combination was coming in the way of the built in Alt + Ctrl + N, which means New HTML document i HTML-Kit. (Do you follow?)</p>
<p><a href="http://www.hans-eric.com/wp-content/uploads/2008/10/my_dvorak.png"><img class="alignnone size-full wp-image-126" title="My custom keyboard layout" src="http://www.hans-eric.com/wp-content/uploads/2008/10/my_dvorak.png" alt="" width="500" height="170" /></a></p>
<p>The fact that HTML-Kit didn&#8217;t allow me to type a common HTML character made the editor seemingly useless. But, that happened to not be the case. HTML-Kit has a great feature that allows you to define your own shortcuts. So, I did just that: define a new Alt + Ctrl + N to just output my double-quote. (I had to do the same for right brackets, } )</p>
<p><a href="http://www.hans-eric.com/wp-content/uploads/2008/10/shortcuts.png"><img class="alignnone size-medium wp-image-127" title="HTML-Kit lets you customize shortcuts" src="http://www.hans-eric.com/wp-content/uploads/2008/10/shortcuts-300x244.png" alt="" width="300" height="244" /></a></p>
<p>I&#8217;d much prefer it if application creators wouldn&#8217;t define Alt + Ctrl shortcuts at all, for the reasons given above, but if they absolutely have to, HTML-Kit&#8217;s level of customizability is the next best thing.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=0k-R0IJkYTY:5d6t5E9yNtw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=0k-R0IJkYTY:5d6t5E9yNtw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=0k-R0IJkYTY:5d6t5E9yNtw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=0k-R0IJkYTY:5d6t5E9yNtw:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=0k-R0IJkYTY:5d6t5E9yNtw:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/0k-R0IJkYTY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/10/07/dont-touch-my-alt-gr-button/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/10/07/dont-touch-my-alt-gr-button/</feedburner:origLink></item>
		<item>
		<title>Functional D: Is Transitive Const Fundamental?</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/PyWLqEWtd8s/</link>
		<comments>http://www.hans-eric.com/2008/07/30/functional-d-is-transitive-const-fundamental/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 11:50:56 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[D Programming Language]]></category>

		<category><![CDATA[Functional D]]></category>

		<category><![CDATA[functional programming]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=124</guid>
		<description><![CDATA[As I&#8217;ve mentioned before, a pure functional subset is forming in the D Programming Language. According to the creators of D, transitive const is a key feature to make this work.
The future of programming will be multicore, multithreaded. Languages that 	make it easy to program them will supplant languages that don&#8217;t. Transitive const is key [...]]]></description>
			<content:encoded><![CDATA[<p>As <a title="The Functional Subset of D" href="http://www.hans-eric.com/2008/05/20/the-functional-subset-of-d/">I&#8217;ve mentioned before</a>, a pure functional subset is forming in the D Programming Language. According to the creators of D, transitive const is a key feature to make this work.</p>
<blockquote><p>The future of programming will be multicore, multithreaded. Languages that 	make it easy to program them will supplant languages that don&#8217;t. Transitive const is key to bringing D into this paradigm. [...] C++ cannot be retrofitted to supporting multiprogramming in a manner that makes it accessible. D isn&#8217;t there yet, but it will be, and transitive const will be absolutely fundamental to making it work.</p></blockquote>
<p><small>[<a title="Const(FAQ)" href="http://www.digitalmars.com/d/2.0/const-faq.html#transitive-const">Quote from the D website</a>]</small></p>
<p><strong>What is transitive const?</strong><br />
Just a quick explanation for those of us who doesn&#8217;t have academic terms in close memory. Transitivity is a property of some binary relations, for example equality:</p>
<p><em>if A = B and B = C, then A = C</em></p>
<p>Applied to the concept of const it means, simply put, that anything reachable from a const type is also a const. So, for a declaration <em>const int **p</em>, <em>p</em> is const, as well as <em>*p</em> and <em>**p</em>.<br />
The same is true in the case of composite types:</p>
<pre><code>class A {
  int f;

  void set_f(int a_value) {
    f = a_value;
  }
}

const A a = new A();
a = new A(); // error
a.a = 2; // error
a.set_a(2); // error</code></pre>
<p>All three reassignments above result in compiler errors due to the fact that a is const, and anything reachable from it is also const.</p>
<p><strong>Why does it matter?</strong><br />
So, in what way is transitive const fundamental to concurrent programming? Well, it isn&#8217;t. What Walter Bright and his companions refer to is the fact that pure functional programming is thread-safe by design. That is, in a pure functional language the result of a function is solely dependent on its arguments. Thus, in a code like this:</p>
<p>val = some_func( a(), b(), c() );</p>
<p>functions a(), b() and c() can be safely executed concurrently in a multi-core architecture; Nothing a(), b() or c() does can affect each others results. This is not the case for imperative languages that builds on the notion of mutable and global state. With mutable state comes hidden side-effects (a(), b() or c() could change common data and cause raise conditions) that complicates multi-thread programming so much.</p>
<p>What the people behind D tries to do is to create a pure functional subset within the language. I like to refer to it as Functional D. Such a subset would allow us to write code that is thread-safe by default, all you have to do is to write Functional D code. The compiler would then be able to chisel out the functional code and fully utilize the advantages of functional programming.</p>
<p><strong>Immutable data and pure functions <em>are</em> fundamental</strong><br />
To make this work we need a way to make data immutable and a way to shut down access to the global state. In D you use the <em>invariant</em> keyword to create immutable data. The <em>pure</em> keyword is used to mark functions that may only take invariant arguments, no access to the global state, and that may only invoke other pure functions. (As of this writing, the semantics of the pure keyword is not yet implemented).</p>
<pre><code>
int g = 0;

pure int pure_func(invariant int a) {
  a = 0; // error, a is invariant
  g = 1; // error, can't write to global g
  writefln(a); // error, writefln is not pure
  return g + a; // error, can't read global g
}</code></pre>
<p>How does transitive const fit into all of this? To use the intuitive definitions from Andrei Alexandrescu&#8217;s <a title="Grafting Functional Support on Top of an Imperative Language" href="http://www.digitalmars.com/d/2.0/accu-functional.pdf">slides on the functional subset of D</a>:</p>
<blockquote>
<ul>
<li>const(T) x: I can’t modify x or anything reachable from it</li>
<li>invariant(T) x: Nobody can modify x or anything reachable from it</li>
</ul>
</blockquote>
<p>Const is not strong enough to be used in the functional subset (which depends on truly immutable data), but it has one application that could be important. From Walter Bright at the D newsgroup:</p>
<blockquote><p>Const allows you to reuse code that works on invariants to work with<br />
mutables, too.</p></blockquote>
<p><strong>How usable is const to the functional subset?<br />
</strong>Const can be used to write code that works with data from both the imperative (mutable) and the functional (immutable) subsets. For example, the print function below.</p>
<pre><code>void print(const int a) {
  writefln(a);
}

const int a = 1;
print(a); // ok

invariant int b = 2;
print(b); // ok

print(3); // ok
</code></pre>
<p>The reason this works is that invariants and immutable data is implicitly converted to const when necessary. One can question how useful this would be in practice though, the print function above would not be invokable from the functional subset (which would require it to be pure).</p>
<p>My conclusion is that although it may very well be important, transitive const is not &#8220;absolutely fundamental to making it work.&#8221; Transitive invariant, on the other hand, is.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=PyWLqEWtd8s:L6mSYDGtcM4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=PyWLqEWtd8s:L6mSYDGtcM4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=PyWLqEWtd8s:L6mSYDGtcM4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=PyWLqEWtd8s:L6mSYDGtcM4:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=PyWLqEWtd8s:L6mSYDGtcM4:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/PyWLqEWtd8s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/07/30/functional-d-is-transitive-const-fundamental/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/07/30/functional-d-is-transitive-const-fundamental/</feedburner:origLink></item>
		<item>
		<title>Hacker or Developer?</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/FKHlcAIizZY/</link>
		<comments>http://www.hans-eric.com/2008/07/29/123/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 11:02:43 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[opinion]]></category>

		<category><![CDATA[software development]]></category>

		<category><![CDATA[Definition]]></category>

		<category><![CDATA[Developer]]></category>

		<category><![CDATA[Hacker]]></category>

		<category><![CDATA[Programmer]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=123</guid>
		<description><![CDATA[Jay Fields has a post up today where he makes a distinction between Developers and Hackers.
Time after time I see requirements gathered and presented in a way that is totally disconnected from the business problem that&#8217;s being addressed. There are two ways to handle the situation.

Write the best code you can.
Talk to the business.

Hackers generally [...]]]></description>
			<content:encoded><![CDATA[<p>Jay Fields has a post up today where he makes <a title="Developers needed; Hackers need not apply" href="http://blog.jayfields.com/2008/07/developers-needed-hackers-need-not.html">a distinction between Developers and Hackers</a>.</p>
<blockquote><p>Time after time I see requirements gathered and presented in a way that is totally disconnected from the business problem that&#8217;s being addressed. There are two ways to handle the situation.</p>
<ol>
<li>Write the best code you can.</li>
<li>Talk to the business.</li>
</ol>
<p>Hackers generally go for the first choice, which doesn&#8217;t guarantee failure. In fact, a good hacker can still deliver code quickly enough that the business will be happy. Often, he gets it right on the 2nd or 3rd try.</p>
<p>But, a developer can deliver what the business is looking for the first time. A(n often) quick conversation with the business ensures that the developer knows what to work on and how it will benefit the business. This dialog often leads to a superior solution implementation where the business gets what it wants and the developer is able to do it in the most efficient way (e.g. I don&#8217;t need a beautiful website, I need a command line application).</p></blockquote>
<p>It&#8217;s essentially <a title="Programmer or Developer?" href="http://www.hans-eric.com/2007/09/04/programmer-or-developer/">the same distinction I tried to make</a> a while ago, although I used the term Programmer instead of Hacker. Maybe if I&#8217;d used the term Hacker as well, I might have avoided some of the heat I took for those definitions <img src='http://www.hans-eric.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Interestingly Jay too suggests &#8212; although he doesn&#8217;t say it outright &#8212; a definition where human interaction and <a title="Tools of the Effective Developer: Customev View" href="http://www.hans-eric.com/2007/09/27/tools-of-the-effective-developer-customer-view/">taking the Customer&#8217;s view</a> is what distinguishes a developer, rather than coding skills.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=FKHlcAIizZY:_K4mPNCe-QY:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=FKHlcAIizZY:_K4mPNCe-QY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=FKHlcAIizZY:_K4mPNCe-QY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=FKHlcAIizZY:_K4mPNCe-QY:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=FKHlcAIizZY:_K4mPNCe-QY:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/FKHlcAIizZY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/07/29/123/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/07/29/123/</feedburner:origLink></item>
		<item>
		<title>Introducing reviews.hans-eric.com</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/q65_PxrmWpw/</link>
		<comments>http://www.hans-eric.com/2008/07/21/introducing-reviewshans-ericcom/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 13:53:13 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[books]]></category>

		<category><![CDATA[learning]]></category>

		<category><![CDATA[reading]]></category>

		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=121</guid>
		<description><![CDATA[I&#8217;m back from my summer vacation. I try to take a long holiday every year and stay away from computers, be with my family, visit interesting places and, of course, read books. Summer is the time of year when I take my reading habits away from the toilet out to the hammock. Time is still [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m back from my summer vacation. I try to take a long holiday every year and stay away from computers, be with my family, visit interesting places and, of course, read books. Summer is the time of year when I take <a title="Kill Two Birds With One Stone" href="http://www.hans-eric.com/2007/07/10/kill-two-birds-with-one-stone-i-am-a-very-busy-ma/">my reading habits</a> away from the toilet out to the hammock. Time is still scarce but this year I managed to finish five books, mostly in a horizontal position.</p>
<p>As you may know <a title="Tools of the Effective Developer: Personal Logs" href="http://www.hans-eric.com/2007/08/31/tools-of-the-effective-developer-personal-logs/">I keep personal logs for almost everything</a>, including notes on the books I&#8217;ve read. Now I decided to take that habit and make it public, something I&#8217;ve been meaning to do for a very long time. For that reason I&#8217;ve set up a new sub domain, <a href="http://reviews.hans-eric.com">reviews.hans-eric.com</a>, where I&#8217;ll publish such notes. It won&#8217;t be fully fledged reviews, but short posts that primarily reflects how I found the book (or the movie, or whatever.)</p>
<p>Here are four of the books I read during my holiday:</p>
<ul>
<li><a title="Review: Agile Software Development with Scrum" href="http://reviews.hans-eric.com/2008/07/21/agile-software-development-with-scrum/">Agile Software Development with Scrum</a></li>
<li><a title="Review: The Art of Happiness" href="http://reviews.hans-eric.com/2008/07/20/the-art-of-happiness/">The Art of Happiness</a></li>
<li><a title="Review: My Job Went to India" href="http://reviews.hans-eric.com/2008/07/20/chad-fowler-my-job-went-to-india/">My Job Went to India</a></li>
<li><a title="Review: Maya Cosmogenesis 2021" href="http://reviews.hans-eric.com/2008/07/15/maya-cosmogenesis-2012/">Maya Cosmogenesis 2012</a></li>
</ul>
<p>If you&#8217;re interested in following what books I read (and what movies I watch,) subscribe to <a href="http://reviews.hans-eric.com/feed/rss/">my reviews feed</a>.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=q65_PxrmWpw:qgXMhTkutx8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=q65_PxrmWpw:qgXMhTkutx8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=q65_PxrmWpw:qgXMhTkutx8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=q65_PxrmWpw:qgXMhTkutx8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=q65_PxrmWpw:qgXMhTkutx8:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/q65_PxrmWpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/07/21/introducing-reviewshans-ericcom/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/07/21/introducing-reviewshans-ericcom/</feedburner:origLink></item>
		<item>
		<title>ModRewrite Problems</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/6jyVjjELNuk/</link>
		<comments>http://www.hans-eric.com/2008/07/05/modrewrite-problems/#comments</comments>
		<pubDate>Sat, 05 Jul 2008 14:26:05 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[blogging]]></category>

		<category><![CDATA[off-topic]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=119</guid>
		<description><![CDATA[As you may or may not have discovered I have been on a long vacation, and intentionally stayed far away from any computer. Unfortunately my blog seems to have broken while I have been gone, particularely the single post pages.
Somehow the ModRewrite rules got screwed up, no idea how. Anyway, it has been taken care [...]]]></description>
			<content:encoded><![CDATA[<p>As you may or may not have discovered I have been on a long vacation, and intentionally stayed far away from any computer. Unfortunately my blog seems to have broken while I have been gone, particularely the single post pages.</p>
<p>Somehow the ModRewrite rules got screwed up, no idea how. Anyway, it has been taken care of now and the site should be up and running as usual. Many thank&#8217;s to <a href="http://www.robertames.com">Robert Ames</a> who pointed it out for me.</p>
<p>Now, back to vacationing (I still have a week left).</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=6jyVjjELNuk:8pkqzGPiYo0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=6jyVjjELNuk:8pkqzGPiYo0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=6jyVjjELNuk:8pkqzGPiYo0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=6jyVjjELNuk:8pkqzGPiYo0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=6jyVjjELNuk:8pkqzGPiYo0:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/6jyVjjELNuk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/07/05/modrewrite-problems/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/07/05/modrewrite-problems/</feedburner:origLink></item>
		<item>
		<title>The Functional Subset of D</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/O15AM0Dm2RQ/</link>
		<comments>http://www.hans-eric.com/2008/05/20/the-functional-subset-of-d/#comments</comments>
		<pubDate>Tue, 20 May 2008 12:00:11 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[D Programming Language]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/?p=117</guid>
		<description><![CDATA[As I wrote about in an earlier post, the future of D lies in the field of functional programming. More specifically, what the creators of D are trying to do, is to construct a pure functional subset that can be utilized within the otherwise imperative language.
Let&#8217;s take a closer look at that functional subset that [...]]]></description>
			<content:encoded><![CDATA[<p>As I <a title="The Future of D is Functional" href="http://www.hans-eric.com/2008/04/16/the-future-of-d-is-functional/">wrote about in an earlier post</a>, the future of D lies in the field of functional programming. More specifically, what the creators of D are trying to do, is to construct a pure functional subset that can be utilized within the otherwise imperative language.</p>
<p>Let&#8217;s take a closer look at that functional subset that is taking form in the experimental 2.0 version of D.</p>
<p><strong>Immutable data</strong></p>
<p>The most fundamental difference between a purely functional language and an imperative one is how they treat data. Many of us are used to think of data in terms of state, where variables can be changed through assignments. But in a functional program there are no states. There are only constant values and functions that operate on them.</p>
<p>In D, immutability is achieved with the <em>invariant</em> keyword, either as a storage class:</p>
<pre><code>invariant int i = 3;</code></pre>
<p>or as a type constructor:</p>
<pre><code>invariant(int) i = 3;</code></pre>
<p><strong>Transitive invariance</strong></p>
<p>The side-effect free nature that comes with immutable data has some great advantages.  For one thing it simplifies testing since the result of a function only depends on its input. There are also some optimizations that can be done by the compiler, but the biggest advantage is that programs written in this way are thread-safe by default.</p>
<p>To take advantage of these things the compiler needs to be able to trust the immutability of our data. This is where transitivity comes in.  In D, invariance is transitive, which basically means that no data reachable from an invariant reference can be changed. Here&#8217;s an example.</p>
<pre><code>int ga = 2; // mutable

struct A {
  int *p = &amp;ga; // pointer to mutable
}

invariant(A) a; // a is immutable
A b; // b is mutable

// invariant is transitive
a = b; // ERROR, a is immutable
a.p = null; // ERROR, a.p is immutable
*a.p = 3; // ERROR, data pointed to by a.p is also immutable
</code></pre>
<p><strong>Garbage collection</strong></p>
<p>Since data must never change in a functional program, and consequently must not be destroyed while the data is in use, it&#8217;s usually a good idea for a functional language to utilize automatic memory management. Like most functional languages, D features garbage collection (<a title="Managing Object Lifetimes in D" href="http://www.hans-eric.com/2008/02/07/managing-object-lifetimes-in-d/">alongside with explicit memory management</a>.)</p>
<p><strong>Higher class functions</strong></p>
<p>In order to do anything interesting in a purely functional language you need higher order functions, or - in other words - the ability to send functions as arguments to other functions. For this we can use the function pointers (or delegates for methods and nested functions).</p>
<p>As an example, let&#8217;s say that we want to create a function that calculates the sum of two adjacent Fibonacci numbers. Here&#8217;s one way to do that.</p>
<pre><code>int nth_fib(int n) {
  if(n == 0) return 0;
  if(n == 1) return 1;
  return nth_fib(n-1) + nth_fib(n-2);
}

int add_next_fib(int n) {
  return nth_fib(n) + nth_fib(n+1);
}</code></pre>
<p>Now, let&#8217;s say that we want to do the same operation on a different sequence, for example natural numbers. Well, we could use the good old copy and paste but that isn&#8217;t very <a title="Don't Repeat Yourself" href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>. Let&#8217;s make add_next a higher order function instead so that it could be used with any sequence function.</p>
<pre><code>int add_next(int n, <em>int function(int) nth</em>) {
  return nth(n) + nth(n+1);
}

int i = add_next(3, &amp;nth_fib);
// i is 8 (3+5)</code></pre>
<p>Now, we can write any sequence function we want and have add_next apply it.</p>
<pre><code>// Sequence function for natural numbers
int nth_nat(int n) {
  return n;
}

int i = add_next(3, &amp;nth_nat);
// i is 7 (3+4)
</code></pre>
<p>Note: For methods and nested functions, the keyword <em>function</em> is replaced with the keyword <em>delegate</em>, otherwise it&#8217;s the same syntax.</p>
<p><strong>Closures</strong></p>
<p>Closures is another indispensable feature of functional languages. In short, it&#8217;s the ability to extract a function pointer for later use, and when invoked the function will still have access to the context in which it was created, even though that context has gone out of scope.</p>
<p>In D, closures are created with the <em>delegate</em> keyword.</p>
<pre><code>int delegate() create_closure() {
  int x = 3;

  int f() {
    return x;
  }

  return &amp;f;
}

int delegate() a_closure = create_closure();
int i = a_closure();
// i is 3
</code></pre>
<p>Note that the extracted function f (referenced by the a_closure variable) accesses the local variable x, although it has gone out of scope at the time of execution. D got this ability with the 2.07 version, before that <a href="http://www.hans-eric.com/2007/09/11/d-doesnt-have-real-closures/">it didn&#8217;t have real closures</a>.</p>
<p><strong>Currying</strong></p>
<p>Closures provide an easy way to do currying, which is common in functional languages. Simply put, currying is a technique where functions take a general function and return a new, more specialized one.</p>
<p>For instance, we could curry our add_next function in our previous example and create a specialized version of it, say add_next_fib (and thus get back to where we started).</p>
<pre><code>int delegate(int) curry_add_next(int function(int) nth) {
  int curry_f(int n) {
    return add_next(n, nth);
  }
  return &amp;curry_f;
}

int delegate(int) add_next_fib = curry_add_next(&amp;nth_fib);
int i = add_next_fib(5);
// i is still 8
</code></pre>
<p><strong>Pure functions</strong></p>
<p>These features are all we need to write purely functional code, but in order to take full advantage of the functional programming paradigm some major things remain unsolved.</p>
<p>For one thing, the compiler needs to know whether or not our code is functional in order to apply possible optimizations. The easiest way to do this is to give the programmer a keyword to tell the compiler she wishes purity, and then have the compiler enforce it. In D this is the purpose of the <em>pure storage class</em>.</p>
<pre><code><em>pure</em> int a_pure_square_function(invariant(int) x) {
  return x * x;
}</code></pre>
<p>A pure function must not access non-invariant data, and may not invoke other non-pure functions. As per D2.13, the pure storage class has not had its semantics implemented and are therefore not enforcing purity. I sense this is not a trivial matter, so it may take some time before we have it.</p>
<p>Cheers!</p>
<p>Update: Added a link and rewrote the section on garbage collection.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=O15AM0Dm2RQ:s9irr1-5kp8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=O15AM0Dm2RQ:s9irr1-5kp8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=O15AM0Dm2RQ:s9irr1-5kp8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=O15AM0Dm2RQ:s9irr1-5kp8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=O15AM0Dm2RQ:s9irr1-5kp8:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/O15AM0Dm2RQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/05/20/the-functional-subset-of-d/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/05/20/the-functional-subset-of-d/</feedburner:origLink></item>
		<item>
		<title>Alan Cooper: Open-Source is a Sign of Failure</title>
		<link>http://feedproxy.google.com/~r/hans-eric/~3/zIk9lFZIrcE/</link>
		<comments>http://www.hans-eric.com/2008/04/28/alan-cooper-open-source-is-a-sign-of-failure/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 10:45:47 +0000</pubDate>
		<dc:creator>Hans-Eric</dc:creator>
		
		<category><![CDATA[opinion]]></category>

		<guid isPermaLink="false">http://www.hans-eric.com/2008/04/28/alan-cooper-open-source-is-a-sign-of-failure/</guid>
		<description><![CDATA[In the keynote where Alan Cooper proclaimed that Agile processes are bad for developing quality software, he made another provoking statement: that Open-Source is ultimately a symptom of management failure. His point is that with the right enthusiasm and commitment to your products, why would anyone go and work in an Open-Source project on their [...]]]></description>
			<content:encoded><![CDATA[<p>In the keynote where <a href="http://www.hans-eric.com/2008/03/28/is-agile-only-for-elites/" title="Is Agile Only For Elites?">Alan Cooper proclaimed</a> that Agile processes are bad for developing quality software, he made another provoking statement: that Open-Source is ultimately a symptom of management failure. His point is that with the right enthusiasm and commitment to <em>your</em> products, why would anyone go and work in an Open-Source project on their spare time?</p>
<p>Well, there are plenty of good reasons for doing Open-Source pro bono work; it&#8217;s a great way to get experience and widen perspectives for instance, but still, Alan has a point. Many of us are not as content as we could be with our regular work. Instead we&#8217;re seeking satisfaction elsewhere.</p>
<p>So, what should our employers do to get our full attention? Here&#8217;s my list.</p>
<ul>
<li><strong>Creative freedom</strong><br />
Give me a chance to contribute, to be innovative and creative. Let me spend a part of my time doing research and follow paths that interest and inspires me. Google is <a href="http://www.hans-eric.com/2007/09/19/the-google-example/" title="The Google Example">a great example</a> of a company that understands the importance of this.</li>
<li><strong>Personal Development</strong><br />
As <a href="http://www.xprogramming.com/Blog/Page.aspx?display=GoodEnough" title="Good Enough">Ron Jeffries has said</a>, &#8220;the river is moving, and if we don&#8217;t keep rowing, we are going to drift back downstream.&#8221; I think self improvement is a spice of life. If my company provides me with all the books I need (and want), and lets me attend courses and conferences of my choice, chances are I&#8217;ll stay with it for life.</li>
<li><strong>Ownership</strong><br />
People usually do a better job, are more careful and thorough, if they own the thing they&#8217;re working on. This is true for software as well. Make me a business partner and I&#8217;ll optimize my work according to your business goals.</li>
<li><strong>Appreciation</strong><br />
The human race seems to be immensely better at criticizing than at giving appreciation. Yet, this is what we all crave, and - it has a great impact on how we see our employers. A rewarding salary is one form of showing appreciation, but I also need the outspoken forms.</li>
<li><strong>Closures</strong><br />
No one can go on for ever without reaching a finish line. I want to work in a team that is long-term efficient and gets  to <em>get done</em> often. Help me divide and I&#8217;ll conquer for you.</li>
</ul>
<p>That was my list, what&#8217;s on yours?</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=zIk9lFZIrcE:X6OqRAyLVRo:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=dnMXMwOfBR0" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=zIk9lFZIrcE:X6OqRAyLVRo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=zIk9lFZIrcE:X6OqRAyLVRo:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/hans-eric?i=zIk9lFZIrcE:X6OqRAyLVRo:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=YwkR-u9nhCs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/hans-eric?a=zIk9lFZIrcE:X6OqRAyLVRo:l6gmwiTKsz0"><img src="http://feeds.feedburner.com/~ff/hans-eric?d=l6gmwiTKsz0" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/hans-eric/~4/zIk9lFZIrcE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.hans-eric.com/2008/04/28/alan-cooper-open-source-is-a-sign-of-failure/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.hans-eric.com/2008/04/28/alan-cooper-open-source-is-a-sign-of-failure/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 1.961 seconds -->
