<?xml version="1.0" encoding="iso-8859-1"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
  <title>davidflanagan.com</title>
  <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/" />
  <modified>2008-08-07T18:50:22Z</modified>
  <tagline>books, tools and techniques for programmers (plus some anti-war activism)</tagline>
  <id>tag:www.davidflanagan.com,2008://1</id>
  <generator url="http://www.movabletype.org/" version="2.661">Movable Type</generator>
  <copyright>Copyright (c) 2008, David</copyright>
  <entry>
    <title>Method Chaining Part 2</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_08.html#000163" />
    <modified>2008-08-07T18:50:22Z</modified>
    <issued>2008-08-07T11:50:22-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.163</id>
    <created>2008-08-07T18:50:22Z</created>
    <summary type="text/plain">The comments on my last post about method chaining in JavaScript were spectacular, and I want to publicly thank all who took the time to read my code and think about it. The final version of the code (which you...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>javascript</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>The comments on my last post about method chaining in JavaScript were spectacular, and I want to publicly thank all who took the time to read my code and think about it.  The final version of the code (which you can see below the fold) is much stronger thanks to their comments.]]>
      <![CDATA[<p>Here's the new version of the <tt>defineClass()</tt> function (along with helper functions <tt>heir()</tt> and <tt>chain()</tt>).  It will replace Example 9-10 in my book:

<pre>
/**
 * defineClass() -- a utility function for defining JavaScript classes.
 *
 * This function expects a single object as its only argument. It defines
 * a new JavaScript class based on the data in that object and returns the
 * constructor function of the new class.
 * 
 * The object passed as an argument should have some or all of the
 * following properties:
 *
 *      name: the name of the class being defined.
 *            If specified, this value will be stored in the classname
 *            property of the returned constructor object.
 * 
 *    extend: The constructor of the class to be extended. The returned 
 *            constructor automatically chains to this function. This value
 *            is stored in the superclass property of the constructor object.
 *
 *      init: The initialization function for the class. If defined, the
 *            constructor will pass all of its arguments to this function.
 *            The constructor also automatically invokes the superclass
 *            constructor with the same arguments, so this function must expect
 *            the same arguments, in the same order, as the superclass 
 *            constructor, and can add additional arguments at the end.
 *
 *   methods: An object that specifies the instance methods (and other 
 *            non-method properties for the class.  The properties of
 *            this object become properties of the prototype.  Methods
 *            are given an overrides property for chaining.  They can
 *            call "chain(this, arguments)" to invoke the method they
 *            override. This function adds properties to the methods in
 *            this object, so you may not pass the same method in two
 *            invocations of defineClass().
 *
 *   statics: An object that specifies the static methods (and other static
 *            properties) for the class.  The properties of this object become
 *            properties of the constructor function.
 **/
function defineClass(data) {
    // Extract some properties from the argument object
    var extend = data.extend;
    var superclass = extend || Object;
    var init = data.init;
    var classname = data.name || "Unnamed class";
    var methods = data.methods || {};
    var statics = data.statics || {};

    // Make a constructor function that chains to the superclass constructor
    // and then calls the initialization method of this class.
    // This will become the return value of this defineClass() method.
    var constructor = function() {
        if (extend) extend.apply(this, arguments); // Initialize superclass
        if (init) init.apply(this, arguments);     // Initialize ourself
    };

    // Copy static properties to the constructor function
    if (data.statics)
        for(var p in data.statics) constructor[p] = data.statics[p];

    // Set superclass and classname properties of the constructor
    constructor.superclass = superclass;
    constructor.classname = classname;

    // Create the object that will be the prototype for the class.
    // This new object must inherit from the superclass prototype.
    var proto = (superclass == Object) ? {} : heir(superclass.prototype);

    // Copy instance methods (and other properties) to the prototype object.
    for(var p in methods) {            // For each name in methods object
        if (p == "toString") continue; // Handled below
        var m = methods[p];            // This is the value to copy
        if (typeof m == "function") {  // If it is a function
            m.overrides = proto[p];    // Remember anything it overrides
            m.name = p;                // Tell it what its name is
            m.owner = constructor;     // Tell it what class owns it.
        }
        proto[p] = m;                  // Then store in the prototype
    }

    // In IE, a for/in loop won't enumerate properties that have the same name
    // as non-enumerable Object methods like toString(). As a partial 
    // work-around, we handle the toString method specially
    if (methods.hasOwnProperty("toString")) { // IE DontEnum bug
        methods.toString.overrides = proto.toString;
        methods.toString.name = "toString";
        methods.toString.owner = constructor;
        proto.toString = methods.toString;
    }

    // All objects should know who their constructor was
    proto.constructor = constructor;

    // And the constructor must know what its prototype is
    constructor.prototype = proto;

    // Finally, return the constructor function
    return constructor;
}

/**
 * Return a new object with p as its prototype
 */
function heir(p) { 
    function h(){}
    h.prototype=p; 
    return new h(); 
}

/**
 * Chain from the calling function to the function on its overrides property.
 * Invoke that method on the first argument. The second argument must be the 
 * arguments object of the calling function: its callee property is used to
 * determine what function is doing the chaining. The third argument is an
 * optional array of values to pass to the overridden method.  If omitted, 
 * the second argument is used instead, passing all of the caller's arguments
 * on to the overridden method.
 *
 * This method returns the return value of the overridden method or
 * throws "ChainError" if no overridden method could be found
 *
 * Typical invocation:     chain(this, arguments)
 * To pass different args: chain(this, arguments, [w, h])
 */ 
function chain(o, args, pass) {
    var f = args.callee;         // The calling function. 
    var g = f.overrides;         // The function it chains to.
    var a = pass || args;        // The arguments we'll pass to s
    if (g) return g.apply(o, a); // Call o.g(a) and return its value as ours.
    else throw "ChainError"      // Complain if nothing to override
}

</pre>

<p>And here is code that uses <tt>defineClass()</tt>.  It will replace Example 9-11.

<pre>
// A very simple Rectangle class
var Rectangle = defineClass({
    name: "Rectangle",
    init: function(w,h) { 
        this.w = w;
        this.h = h; 
    },
    methods: {
        area: function() { return this.w * this.h; },
        toString: function() { return "[" + this.w + "," + this.h + "]" }
    }
});

// A subclass of Rectangle
var PositionedRectangle = defineClass({
    name: "PositionedRectangle",
    extend: Rectangle,
    init: function(w,h,x,y) {
        // Automatic chain here: Rectangle.call(this,w,h,x,y)
        this.x = x;
        this.y = y;
    },
    methods: {
        isInside: function(x,y) {
            return x &gt; this.x &amp;&amp; x &lt; this.x + this.w &amp;&amp;
                y &gt; this.y &amp;&amp; y &lt; this.y + this.h;
        },
        toString: function() { 
            return chain(this, arguments) + "(" + this.x + "," + this.y + ")";
        }
    }
});

var ColoredRectangle = defineClass({
    name: "ColoredRectangle",
    extend: PositionedRectangle,
    init: function(w,h,x,y,c) { this.c = c; },
    methods: {
        toString: function() { return this.c + ": " + chain(this,arguments)}
    }
});

</pre>]]>
    </content>
  </entry>
  <entry>
    <title>Method chaining in JavaScript inheritance hierarchies</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_07.html#000162" />
    <modified>2008-08-01T05:48:48Z</modified>
    <issued>2008-07-31T22:48:48-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.162</id>
    <created>2008-08-01T05:48:48Z</created>
    <summary type="text/plain"> In the 5th edition of my JavaScript book I made the embarrassing mistake of recommending a constructor and method chaining technique that only works for shallow class hierarchies--it works when class B extends A, for example, but not when...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>javascript</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
In the 5th edition of 
<a href="http://www.amazon.com/gp/product/0596101996?ie=UTF8&tag=davidflanagancom&link_code=as3&camp=211189&creative=373489&creativeASIN=0596101996">
my JavaScript book</a> I made the embarrassing mistake of recommending a constructor and method chaining technique that only works for shallow class hierarchies--it works when class B extends A, for example, but not when C extends B and B extends A.  
<p>
The technique I recommended was to put a <tt>superclass</tt> property in the prototype object of a class, and then to chain to a superclass constructor by calling <tt>this.superclass()</tt>.  To see why 
this fails, imagine that we're creating an instance of class C (which extends B which extends A).
The constructor <tt>C()</tt> chains to <tt>B()</tt> by calling <tt>this.superclass()</tt>.  The constructor method <tt>B()</tt> is invoked on the same instance of C, however, so when it attempts to chain to <tt>A()</tt> by calling <tt>this.superclass()</tt>, it just ends up invoking itself.  This incorrect chaining technique is discussed in sections 9.5.1 and 9.5.2, and is also used in example 9-10 and 9-11 at the very end of the chapter.  I blogged about this mistake and a possible workaround <a href="http://www.davidflanagan.com/blog/2006_10.html#000115">
almost two  years ago</a>.
<p>
Now, however, O'Reilly is preparing to do a reprint of the book, and I have an opportunity to fix this mistake.  Below is a revised code from examples 9-10 and 9-11.  I've renamed the <tt>defineClass()</tt> method to <tt>Class()</tt> and have modified it so that it automatically does constructor chaining (I was inspired by dojo for this change).  More importantly, I've simplified method chaining by defining a global method named <tt>chain()</tt> for method chaining.  If a method overrides a method defined by a superclass (or a "mixin" class) it can invoke that overridden class by invoking <tt>chain()</tt> like this: <tt>chain(this,arguments)</tt>.
(The second argument must be the arguments array of the overriding method, and the first argument must be the object on which that method was invoked.)
<p>
The code is below the fold.
I think this is interesting JavaScript, and I'd love to have it checked for errors before it goes into print again...  Please leave a comment if you think it could be improved!
<b>Update:</b> comments are now closed; spammers have struck.]]>
      <![CDATA[<pre>
/**
 * Class() -- a utility function for defining JavaScript classes.
 *
 * This function expects a single object as its only argument. It defines
 * a new JavaScript class based on the data in that object and returns the
 * constructor function of the new class. This function handles the repetitive
 * tasks of defining classes: setting up the prototype object for correct
 * inheritance, copying methods from other types, and so on.
 * 
 * The object passed as an argument should have some or all of the
 * following properties:
 *
 *      name: the name of the class being defined.
 *            If specified, this value will be stored in the classname
 *            property of the returned constructor object.
 * 
 *    extend: The constructor of the class to be extended. The returned 
 *            constructor automatically chains to this function. This value
 *            is stored in the superclass property of the constructor object.
 *
 *      init: The initialization function for the class. If defined, the
 *            constructor will pass all of its arguments to this function.
 *
 *   methods: An object that specifies the instance methods for the class.
 *            These functions are given an overrides property for chaining.
 *            They can call "chain(this, arguments)" to invoke the method
 *            they override.  "arguments" must appear literally.
 *
 *   statics: An object that specifies the static methods (and other static
 *            properties) for the class.  The properties of this object become
 *            properties of the constructor function.
 *
 *    mixins: A constructor function or array of constructor functions.
 *            The instance methods of each of the specified classes are copied
 *            into the prototype object of this new class so that the 
 *            new class borrows the methods of each specified class.
 *            Mixins are processed in the order they are specified,
 *            so the methods of a mixin listed at the end of the array may
 *            overwrite the methods of those specified earlier. Note that
 *            methods specified in the methods object can override (and chain 
 *            to) mixed-in methods.
 *
 * This function is named with a capital letter and looks like a constructor
 * function. It can (but need not) be used with new: new Class({...})
 **/
function Class(data) {
    // Extract the fields we'll use from the argument object.
    var extend = data.extend;
    var init = data.init;
    var classname = data.name || "Unnamed Class";
    var statics = data.statics || {};
    var mixins = data.mixins || [];
    var methods = data.methods || {};

    // Make a constructor function that chains to the superclass constructor
    // and then calls the initialization method of this class.
    // This will become the return value of this Class() method.
    var constructor = function() {
	if (extend) extend.apply(this, arguments);  // Initialize superclass
	if (init) init.apply(this, arguments);      // Initialize ourself
    };

    // Copy static properties to the constructor function
    for(var p in statics) constructor[p] = statics[p];

    // Set superclass and classname properties of the constructor
    constructor.superclass = extend || Object;
    constructor.classname = classname;

    // Create an instance of the superclass to use as the prototype for 
    // the new class.  Assign it to constructor.prototype
    var proto = constructor.prototype = new constructor.superclass();

    // Delete any local properties of the prototype object
    for(var p in proto)             
	if (proto.hasOwnProperty(p)) delete proto[p];

    // Borrow methods from mixin classes by copying methods to our prototype.
    if (!(mixins instanceof Array)) mixins = [mixins]; // Ensure an array
    for(var i = 0; i &lt; mixins.length; i++) {  // For each mixin class
        var m = mixins[i].prototype;          // This is mixin prototype
        for(var p in m) {                     // For each property of mixin
            if (typeof m[p] == "function")    // If it is a function
		proto[p] = m[p];              // Copy it to our prototype
	}
    }

    // Copy instance methods to the prototype object
    // This may override methods of the mixin classes or the superclass
    for(var p in methods) {           // For each name in methods object
	var m = methods[p];           // This is the method to copy
	if (typeof m == "function") { // If it is a function
	    m.overrides = proto[p];   // Remember anything it overrides
	    proto[p] = m;             // Then store in the prototype
	}
    }

    // All objects should know who their constructor was
    proto.constructor = constructor;

    // Finally, return the constructor function
    return constructor;
}

/**
 * This function is designed to be invoked with the this keyword as its
 * 1st argument and the arguments array as its 2nd: chain(this, arguments).
 * It uses the callee property to determine what function called this 
 * function, and then looks for an overrides property on that function.
 * If it finds one, it invokes the overridden function on the object,
 * passing the arguments
 */
function chain(o, args) {
    m = args.callee;                 // The method that wants to chain
    om = m.overrides                 // The method it overrides
    if (om) return om.apply(o, args) // Invoke it, if it exists
}

// Example 9-11 demonstrates the methods above
//-----------------------------------------------
// A mixin class with a usefully generic equals() method for borrowing
var GenericEquals = Class({
    name: "GenericEquals",
    methods: {
        equals: function(that) {
            if (this == that) return true;
            var propsInThat = 0; 
            for(var name in that) {
                propsInThat++;
                if (this[name] !== that[name]) return false;
            }

            // Now make sure that this object doesn't have additional props
            var propsInThis = 0;
            for(name in this) propsInThis++;

            // If this has additional properties then they are not equal
            if (propsInThis != propsInThat) return false;

            // The two objects appear to be equal.
            return true;
        }
    }
});


// A very simple Rectangle class
var Rectangle = Class({
    name: "Rectangle",
    init: function(w,h) { 
	this.width = w; this.height = h; 
    },
    methods: {
        area: function() { return this.width * this.height; },
        compareTo: function(that) { return this.area() - that.area(); },
	toString: function() { 
	    return "[" + this.width + "," + this.height + "]"
	}
    }
});

// A subclass of Rectangle
var PositionedRectangle = Class({
    name: "PositionedRectangle",
    extend: Rectangle,
    init: function(w,h,x,y) {
        this.x = x;
        this.y = y;
    },
    methods: {
        isInside: function(x,y) {
            return x &gt; this.x &amp;&amp; x &lt; this.x+this.width &amp;&amp;
                y &gt; this.y &amp;&amp; y &lt; this.y+this.height;
        },
	toString: function() { 
	    return chain(this,arguments) + "(" + this.x + "," + this.y + ")";
	},
    },
    mixins: [GenericEquals]
});

var ColoredRectangle = new Class({
    name: "ColoredRectangle",
    extend: PositionedRectangle,
    init: function(w,h,x,y,c) {	this.c = c; },
    methods: {
	toString: function() { return chain(this,arguments) + ": " + this.c}
    }
});

var cr = new ColoredRectangle(1,2,3,4,5);
alert(cr.toString()); // Demonstrate constructor and method chaining
</pre>]]>
    </content>
  </entry>
  <entry>
    <title>Ruby Review Roundup</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_04.html#000161" />
    <modified>2008-04-17T17:24:08Z</modified>
    <issued>2008-04-17T10:24:08-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.161</id>
    <created>2008-04-17T17:24:08Z</created>
    <summary type="text/plain"> The Ruby Programming Language has been gratifyingly well received by readers and reviewers. In addition to glowing reviews at rubyinside.com and slashdot.org, it has been reviewed ten times at amazon.com and I proud to say that all ten reviews...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
<i>The Ruby Programming Language</i> has been gratifyingly well received by readers and reviewers.  In addition to glowing reviews at <a href="http://www.rubyinside.com/the-new-most-important-ruby-book-oreillys-the-ruby-programming-language-778.html">rubyinside.com</a> and <a href="http://books.slashdot.org/article.pl?sid=08/03/03/1515239">slashdot.org</a>, it has been <a href="http://www.amazon.com/review/product/0596516177">reviewed ten times at amazon.com</a> and I proud to say that all ten reviews give it a five-star rating.
<p>
Here are the reviews.  For all except the slashdot review, the linked text is the title of the review:
<ul>
<li><a href="http://www.rubyinside.com/the-new-most-important-ruby-book-oreillys-the-ruby-programming-language-778.html">
The New Most Important Ruby Book</a> [rubyinside.com]

<li><a href="http://books.slashdot.org/article.pl?sid=08/03/03/1515239">...the most authoritative language book for Ruby...</a> [slashdot.org]

<li><a href="http://www.amazon.com/review/RLJ78T9DWIPBD/ref=cm_cr_rdp_perm">
This is the new authoritative Ruby book. Buy it, not the Pickaxe.
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/RKF38WCT9EOCU/ref=cm_cr_rdp_perm">
Finally! And worth it!
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/RTOHB75Y3KXFM/ref=cm_cr_rdp_perm">
A Must-Have For Serious Ruby Developers
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R1Z8850Y0UX4Q3/ref=cm_cr_rdp_perm">
Perfect For Experienced Ruby Developers
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R3RPLS7OINFZMA/ref=cm_cr_rdp_perm">
Great introduction to Ruby for experienced programmers
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R3KM5D9AW2IPS0/ref=cm_cr_rdp_perm">
Good book on Ruby
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R6FKGG4OJKSDU/ref=cm_cr_rdp_perm">
The best Ruby book I've seen
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R341K1NH874QYO/ref=cm_cr_rdp_perm">
The Ruby Book!
</a> [amazon.com]

<li><a href="http://www.amazon.com/review/R374CQSM7T3128/ref=cm_cr_rdp_perm">
Great!
</a> [amazon.com]

<li><a
href="http://www.amazon.com/review/R1TTOWJXBEIHAG/ref=cm_cr_rdp_perm">
great book
</a> [amazon.com]
</ul>
<p>
Thanks everyone!]]>
      
    </content>
  </entry>
  <entry>
    <title>Errata for my Ruby Book</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_04.html#000160" />
    <modified>2008-04-15T04:18:10Z</modified>
    <issued>2008-04-14T21:18:10-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.160</id>
    <created>2008-04-15T04:18:10Z</created>
    <summary type="text/plain"> I&apos;ve put together a list of 81 errors and updates to my Ruby book. These are fixed in the next printing. If you already own a copy of the book, however, you can go through and enter the changes...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
I've put together 
<a href="http://www.davidflanagan.com/documents/RubyReprintChanges1.txt">a list of 81 errors and updates to my Ruby book</a>.  These are fixed in the next printing.  If you already own a copy of the book, however, you can go through and enter the changes yourself, if you are so inclined.
<p>
I use O'Reilly's style for describing the changes.  Each entry in the file begins with a page number within delimiter characters.  The delimiters indicate the severity of the change:
<ul>
<li>Page numbers in parentheses usually indicate typos or other minor non-technical changes.  You can ignore these if you want.
<li>Page numbers in curly braces indicate minor technical errors that have been corrected
<li>Page numbers in square braces indicate more severe technical errors that have been corrected.  There are only two of these, but they're worth noting.
<li>Page numbers in angle brackets are updates (this differs a bit from normal O'Reilly style) to keep the book in sync with the evolution of Ruby 1.9.  In my opinion, these are the interesting ones.
</ul>
<p>
I've posted my list of changes <a href="http://www.davidflanagan.com/documents/RubyReprintChanges1.txt">here</a>.  They will all  eventually appear on 
<a href="http://www.oreilly.com/catalog/9780596516178/errata/">O'Reilly's errata page for the book</a> as well.]]>
      
    </content>
  </entry>
  <entry>
    <title>Help fix up my book, please</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_04.html#000159" />
    <modified>2008-04-07T22:04:26Z</modified>
    <issued>2008-04-07T15:04:26-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.159</id>
    <created>2008-04-07T22:04:26Z</created>
    <summary type="text/plain"> The Ruby Programming Language is going to be reprinted next week, and O&apos;Reilly has given me SVN write access to the docbook files to fix typos, errors, etc. I&apos;ve got a list of about 25 relatively minor erros that...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
<i>The Ruby Programming Language</i> is going to be reprinted next week, and O'Reilly has given me SVN write access to the docbook files to fix typos, errors, etc.  I've got a list of about 25 relatively minor erros that I'll be fixing, but I'd love to stomp out more bugs on this reprint.
<p>
So, if you've got a copy of the book, and have found typos, mistakes or omissions, please let me know.  You can email me (david@ this domain) or post them as comments on this blog.  (Normally, you'd submit them <a href="http://www.oreilly.com/catalog/9780596516178/errata/">on the O'Reilly website</a> but since time is factor for this reprint, send them directly to me, please.)  Keep in mind that this is just a reprint, not a new edition of the book, so I'm pretty constrained about the kinds of changes I can make.  I can't add new sections or figures or tables, or cover brand new topics that aren't currently covered.  I can often squeeze in short new paragraphs when they're needed to clarify things or if there is something important that I left out.
<p>
Thanks to DH, MD, RM, and DB, all of whom submitted one or more errata to me or to O'Reilly's website recently.  I don't have access to the names (or initials) of the others who submitted errata to the publisher's website back in March and February.
<p><b>Update:</b> Thanks to those (BR, CS, ADS, MD) who commented and emailed me with other errors to correct.  I ended up making about 80 changes--half to fix typos and minor errors, and half to update the book to track minor (mostly) changes in Ruby 1.9.  I'll post a list of all changes soon.
]]>
      
    </content>
  </entry>
  <entry>
    <title>Will C++ get Closures before Java does?</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_03.html#000158" />
    <modified>2008-04-01T05:34:14Z</modified>
    <issued>2008-03-31T22:34:14-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.158</id>
    <created>2008-04-01T05:34:14Z</created>
    <summary type="text/plain"> I just read that closures are being added to C++ [PDF link]. A note to Sun: you know your language is falling embarrassingly behind if the C++ standards committee can move more nimbly than you can! (For those who...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>java</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
I just <a href="http://www.weiqigao.com/blog/2008/03/30/closures_comes_to_c0x.html">read</a> that <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf">closures are being added to C++ [PDF link]</a>.
<p>
A note to Sun: you know your language is falling embarrassingly behind if the C++ standards committee can move more nimbly than you can!
<p>
(For those who aren't already sick of reading about closures in Java, Neal Gafter is developing a <a href="http://javac.info">prototype Java compiler</a> that supports closures, and he even has a <a href="http://www.javac.info/consensus-closures-jsr.html">JSR proposal</a> drafted and ready to go.)]]>
      
    </content>
  </entry>
  <entry>
    <title>5 Years in Iraq</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_03.html#000157" />
    <modified>2008-03-18T19:02:53Z</modified>
    <issued>2008-03-18T12:02:53-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.157</id>
    <created>2008-03-18T19:02:53Z</created>
    <summary type="text/plain"> Tomorrow marks the 5th anniversary of Bush&apos;s war with Iraq. The costs: 3990 US soldiers dead That is more than 2 per day. 20,416 US soldiers wounded (badly enough to require air transport). That&apos;s more than 11 per day....</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>anti-war</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
Tomorrow marks the 5th anniversary of Bush's war with Iraq.  The costs:
<ul>
<li><a href="http://icasualties.org">3990 US soldiers dead</a>  That is more than 2 per day.
<li><a href="http://icasualties.org">20,416 US soldiers wounded</a> (badly enough to require air transport).  That's more than 11 per day.
<li><a href="http://www.iraqbodycount.org">At least 82,240 civilians killed</a>.  That's 45 a day and only includes deaths that get reported in the media.  One <a href="http://www.zmag.org/lancet.pdf">study</a> puts the civilian death toll much, much higher.
<li><a href="http://costofwar.com">$503 billion</a>.  That's 275 million dollars a day, and it doesn't include future obligations, such as veteran's health care. (Nobel laureate economist Joseph Stiglitz <a href="http://www.amazon.com/Three-Trillion-Dollar-War-Conflict/dp/0393067017/">argues</a> that the war has already cost 3 <i>trillion</i> dollars.)
</ul>
<p>
The blood of 2 soldiers and $275 million down the drain today and tomorrow and the day after....  With no end in sight.
<p>
Our elected representatives seem uninterested in stopping this war, but 
these <a href="http://www.actblue.com/page/aresponsibleplan">candidates</a> for the US House of Representatives have <a href="http://www.responsibleplan.com/">a responsible plan</a> to end the war.  It is remarkably sane and it is the only glimmer of hope I've had in a long time.]]>
      
    </content>
  </entry>
  <entry>
    <title>Welcome Slashdot Readers</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_03.html#000156" />
    <modified>2008-03-03T19:34:34Z</modified>
    <issued>2008-03-03T11:34:34-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.156</id>
    <created>2008-03-03T19:34:34Z</created>
    <summary type="text/plain"> If you arrived here after reading slashdot&apos;s review of The Ruby Programming Language, you&apos;ve come to the right place. Thanks, Brian, for the kind words! The post below includes links to the book&apos;s table of contents and to an...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<iframe src="http://rcm.amazon.com/e/cm?t=davidflanagancom&o=1&p=8&l=as1&asins=0596516177&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float:right;margin:5px" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>
If you arrived here after reading
<a href='http://books.slashdot.org/books/08/03/03/1515239.shtml'>
slashdot's review
</a>
of <i>The Ruby Programming Language</i>, you've come to the right place.
Thanks, Brian, for the kind words!  The post below includes links to the book's table of contents and to an interactive preview.]]>
      
    </content>
  </entry>
  <entry>
    <title>Finally!</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_02.html#000154" />
    <modified>2008-02-07T19:39:24Z</modified>
    <issued>2008-02-07T11:39:24-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.154</id>
    <created>2008-02-07T19:39:24Z</created>
    <summary type="text/plain"> The Ruby Programming Language is finally in stock and shipping from online booksellers! Press Release: actually quite a good overview of the book, who it is for and the niche it hopes to fill. Preview: an interactive table-of-contents, with...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
<i>The Ruby Programming Language</i> is finally in stock and shipping from online booksellers!
<p>
<a href="http://press.oreilly.com/pub/pr/1916">Press Release</a>: actually quite a good overview of the book, who it is for and the niche it hopes to fill.
<p>
<a href="http://www.oreilly.com/catalog/9780596516178/toc.html">Preview</a>: an interactive table-of-contents, with excerpts from each chapter and section.
<p>
<a href="http://www.davidflanagan.com/documents/rpl_frontmatter2.pdf">Table of contents</a> (in PDF form)
<p>
Buy it from:
<ul>
<li><a href="http://www.oreilly.com/catalog/9780596516178/">O'Reilly</a>
<li><a href="http://www.amazon.com/dp/0596516177?tag=davidflanagancom&camp=14573&creative=327641&linkCode=as1&creativeASIN=0596516177&adid=0EQ3FX643NPNV9SB51N8&">Amazon</a>
<li><a href="http://www.bookpool.com/sm/0596516177">Bookpool</a>
<li><a href="http://www.buy.com/prod/the-ruby-programming-language/q/loc/106/205620743.html">Buy.com</a>
<li><a href="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?z=y&EAN=9780596516178">bn.com</a>
</ul>
<p>
I think (and hope) that this should be my last post flogging this book!]]>
      
    </content>
  </entry>
  <entry>
    <title>Preview my Ruby book</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_01.html#000153" />
    <modified>2008-01-24T21:47:35Z</modified>
    <issued>2008-01-24T13:47:35-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.153</id>
    <created>2008-01-24T21:47:35Z</created>
    <summary type="text/plain"> I&apos;ve just discovered that the O&apos;Reilly website now displays a browsable table of contents that allows you to preview the start of each chapter and each section of my book. In other book news, Amazon is still listing the...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
I've just discovered that the O'Reilly website now displays a browsable table of contents that allows you to <a href='http://www.oreilly.com/catalog/9780596516178/toc.html'>preview the start of each chapter and each section</a> of my book.
<p>
In other book news, Amazon is still listing the book for pre-order, so I guess the January 24th date isn't quite right. 
<p>
<b>Update:</b> I received my copy from O'Reilly today, so the book has been printed, and Amazon should be shipping orders soon.
<p>
<b>Second Update, (February 1st):</b> Amazon now shows the book available for order, but is saying "two to three weeks" for shipping.  The folks in the know at O'Reilly say that books are on their way from the O'Reilly warehouse to the Amazon warehouse, and Amazon should start shipping them out by mid-week.  In the meantime, it looks as if oreilly.com is the only place that is currently shipping copies of the book.
I was under the mistaken impression that books went directly from the printer to major booksellers like Amazon.  Given these normal and predictable shipping delays, I don't know why Amazon listed 1/24 as the availability date for so long.  

<p>
 They still seem to be offering the extra 5% discount.  I've also discovered that you can get an even better price on it at <a href='http://www.buy.com/prod/the-ruby-programming-language/q/loc/106/205620743.html'>buy.com</a> (though they don't have it in stock yet, either).
 <p>
Finally, the book is available now online (for preview or by subscription) at <a href="http://safari.oreilly.com/9780596516178">Safari</a>.]]>
      
    </content>
  </entry>
  <entry>
    <title>Examples from my Ruby book now online</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_01.html#000152" />
    <modified>2008-01-23T23:16:10Z</modified>
    <issued>2008-01-23T15:16:10-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.152</id>
    <created>2008-01-23T23:16:10Z</created>
    <summary type="text/plain"> All the example code from my Ruby book is now available for download. As I&apos;ve mentioned before, you can also browse the book&apos;s table of contents....</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
All the example code from my Ruby book is now 
<a href="http://www.davidflanagan.com/rpl/">available for download</a>.
<p>
As I've mentioned before, you can also
<a href="http://www.davidflanagan.com/documents/rpl_frontmatter2.pdf">
browse the book's table of contents</a>.]]>
      
    </content>
  </entry>
  <entry>
    <title>Last day for Amazon&apos;s pre-order discount</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_01.html#000151" />
    <modified>2008-01-23T15:10:16Z</modified>
    <issued>2008-01-23T07:10:16-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.151</id>
    <created>2008-01-23T15:10:16Z</created>
    <summary type="text/plain"> Amazon continues to say that my Ruby book will be in stock tomorrow. So today is the last day that you can pre-order the book and save an additional 5% on it. As I type this, they&apos;re listing it...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<iframe src="http://rcm.amazon.com/e/cm?t=davidflanagancom&o=1&p=8&l=as1&asins=0596516177&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float:right;margin:5px" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<p>
Amazon continues to say that my Ruby book will be in stock tomorrow.  So today is the last day that you can pre-order the book and save an additional 5% on it.  As I type this, they're listing it at $26.39.  After another 5%, you'd be paying just over $25, which is pretty good for a $40 book.]]>
      
    </content>
  </entry>
  <entry>
    <title>Off to the Printer</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_01.html#000150" />
    <modified>2008-01-15T23:46:25Z</modified>
    <issued>2008-01-15T15:46:25-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.150</id>
    <created>2008-01-15T23:46:25Z</created>
    <summary type="text/plain"> The Ruby Programming Language was sent to the printer on Friday the 11th, and should be printed and bound on Monday January 21st. This is on schedule. Amazon still says that they expect to start fulfilling orders on January...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<iframe src="http://rcm.amazon.com/e/cm?t=davidflanagancom&o=1&p=8&l=as1&asins=0596516177&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float:right;margin:5px" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>


<p>
<i>The Ruby Programming Language</i> was sent to the printer on Friday the 11th, and should be printed and bound on Monday January 21st.  This is on schedule.  Amazon still says that they expect to start fulfilling orders on January 24th.  I don't know the logistics of getting copies from the printer to Amazon, but it seems likely that they can meet (or come close) to that date.
<p>
I've uploaded a pdf of the final  
<a href="http://www.davidflanagan.com/documents/rpl_frontmatter2.pdf">
frontmatter
</a> in case you'd like to browse the table of contents to see what material I cover.  (My older, 
<a href="http://www.davidflanagan.com/documents/rpl_frontmatter.pdf">
homebrew TOC</a> is a little out of date but includes 2nd-level section titles as well as the top-level sections, so it gives quite a bit more detail about the book's contents.)
<p>
I've seen the book get as high as #64 on Amazon's list of bestselling programming books even before it is released.  It's fallen off the list today, but if you pre-order it now, maybe it will come back on!  :-)

<p><b>Update:</b> In the comments, Adriano asks a good (and common) question about the stability of Ruby 1.9.  I'm posting my response here:
<blockquote><p>
Adriano,
<p>
Thanks for your comment.  I hope my book can meet
your expectations!  I should make clear that this
book is a language reference, but not an API
reference.  Unlike my JavaScript book, there is
not a section that documents each class and method
of the core library.  (Though there is a long
example-based chapter that demonstrates the most
important classes of the core library.)
<p>
Matz has changed the release numbering scheme for
this release of Ruby.  1.9.x will be a stable
version of the language, not a development
version, despite the fact that 9 is an odd number.
The original intent, I believe, was to release
1.9.1 on Christmas.  But the code was not stable
enough.  So Matz's Christmas release is still
called 1.9.0, and is effectively a beta-release of
1.9.  Matz does not yet recommend it for
production use, but it is stable enough to begin
porting applications to.
<p>
The Christmas release of 1.9.0 was nominally an
API freeze as well.  There have been, and will
continue to be minor API changes between 1.9.0 and
1.9.1, but there shouldn't be many of them: the
intent is to keep the API frozen.
<p>
My book went to the printer after the Christmas
release, so it covers everything that was in the
frozen 1.9.0 release, and even a couple of changes
that happened after the release.  I may have to
release a few errata when 1.9.1 comes out, but
overall, this book should have very complete
coverage of 1.9.x
</blockquote>]]>
      
    </content>
  </entry>
  <entry>
    <title>Giles Bowkett Replaced by Mindless Fanboy</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2008_01.html#000149" />
    <modified>2008-01-15T21:06:50Z</modified>
    <issued>2008-01-15T13:06:50-08:00</issued>
    <id>tag:www.davidflanagan.com,2008://1.149</id>
    <created>2008-01-15T21:06:50Z</created>
    <summary type="text/plain"> This post, and its title, is a response to Giles Bowkett&apos;s clairvoyant review of my Ruby book. In that review, he says: I am &quot;soulless&quot;, my publisher was &quot;really cool once&quot;, and that you &quot;sure as hell don&apos;t want...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<p>
This post, and its title, is a response to 

<a
href="http://gilesbowkett.blogspot.com/2007/12/david-flanagan-replaced-by-soulless.html">
Giles Bowkett's clairvoyant review</a> of <a
href="http://www.amazon.com/dp/0596516177?tag=davidflanagancom&camp=14573&creative=327641&linkCode=as1&creativeASIN=0596516177&adid=1NTC4XN4EE98Z2RR3KD8&">my
Ruby book</a>.  In that review, he says:

<ul>
<li>I am "soulless", 
<li>my publisher was "really cool once", and that
<li>you "sure as hell don't want a copy of Flanagan's upcoming book".
</ul>

<p> The book is not out yet, and as far as I know no one has shown him
one of the drafts circulated at ruby-conf. He bases his opinions on one comment I
posted on Sam Ruby's blog.

<p> The crux of Giles's argument is apparently that O'Reilly was
disrespectful to the Ruby community because they're "publishing
something by an author...who isn't even a significant part of the
community".

<p>Being called "soulless" (that's a fighting word,
Giles) makes me angry, but this "in group" nonsense is what gets under my skin and is
why I'm taking this fight to my blog. Had Giles been a participant in
the ruby-core mailing list he would know that I've been an active member
of that list for almost a year.  He might also know that I have commit
privileges and have made small but non-trivial contributions (such as
implementing <code>\u</code> Unicode escapes in string literals) to the
Ruby 1.9 codebase.

<p>I've spent a year and a half learning and writing about Ruby. I've
argued vocally for changes to the language and I've implemented changes to
the language.  Of course I'm part of the Ruby community. What Giles
really means is that I'm not part of the Ruby club, of which Giles
fancies himself a member. I have to say that this fanboy boosterism that
pervades certain Ruby circles is a real turn off for newcomers to the
language. The Ruby club has never managed to produce competent
(English-language) documentation of the language, Giles.  How can you
blame O'Reilly for asking an experienced writer to do the job?

<p>Giles writes:

<blockquote><p> Bear in mind this...comes from somebody who's
programming and blogging at 11pm on a Friday </p></blockquote>

<p>You need to learn, Giles, that insults posted on a blog at 11pm on a
Friday can still be gracefully retracted...it would be soulful thing to
do.

<p>(I should make clear that I do not know Giles.  The title of this post
parallels the title of his post, but I do not really know if he is a
mindless fanboy, or just acts like one sometimes.)
]]>
      
    </content>
  </entry>
  <entry>
    <title>Surprise!</title>
    <link rel="alternate" type="text/html" href="http://www.davidflanagan.com/blog/2007_11.html#000148" />
    <modified>2007-11-27T06:16:43Z</modified>
    <issued>2007-11-26T22:16:43-08:00</issued>
    <id>tag:www.davidflanagan.com,2007://1.148</id>
    <created>2007-11-27T06:16:43Z</created>
    <summary type="text/plain"> In the post below I hinted at a secret contributor, besides Matz and myself, to the Ruby book. Amazon now displays the latest cover design for the book, and all can now be revealed.... To find out who&apos;s contribution...</summary>
    <author>
      <name>David</name>
      
      <email>david@davidflanagan.com</email>
    </author>
    <dc:subject>ruby</dc:subject>
    <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.davidflanagan.com/">
      <![CDATA[<iframe src="http://rcm.amazon.com/e/cm?t=davidflanagancom&o=1&p=8&l=as1&asins=0596516177&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float:right;margin:5px" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<p>In the <a href="http://www.davidflanagan.com/blog/2007_11.html#000147">post below</a>
I hinted at a secret contributor, besides Matz and myself, to the Ruby book.
Amazon now displays the latest cover design for the book, and all can now be revealed....
</p><p>
To find out who's contribution I am honored to have in this book, 
click on the Amazon.com link to the right to visit the pre-order page for the book.  This will let you see the cover at a readable size--look for the "see larger image" link.  If you've been working with Ruby for a while, you will recognize the new name on the cover. 
</p><p>
And when you've recovered from your surprise, you can pre-order your copy of the book!  :-)
</p>
<p><b>Update:</b> the name has now disappeared from the cover.  I don't know why.  When I first posted this, it read: "with drawings by why the lucky stiff"</p>]]>
      
    </content>
  </entry>

</feed>