Back when I was younger, and object[-oriented] programming was fairly new, my colleagues and I seemed to spend a lot of time philosophizing about types and objects. Although I don’t remember talking about ducks, we did talk a lot about the theater. The most common word we used to use for what we now call a duck type was a role.
Another way of looking at this, is that duck typing is akin to the way a person is chosen to fill the role of the American President. An assessment is performed on the candidates,one is chosen, and then the country, and world adapt.
Contrast this to the way things are done in picking the next British monarch, or the type systems of C++ or Java. In both cases one has to be born into the role, having the right genes via inheritance. Of course in the first case, who gets the job doesn’t matter all that much anymore.
Recently a thread about patterns on the ruby-talk mailing list turned, as threads there are wont to do, to duck-typing.
William Crawford, helpfully contributed:
In short, if a type/class/whatever has all the methods of a duck (that
you intend to use), it’s a duck and can be used as a duck would be used,
regardless of what’s actually under the feathers.
In other words, TCPSocket doesn’t just inherit from Socket, Object,
etc… It IS a Socket, it IS an Object, etc.
While this is true, the second paragraph is not a particularly good example to explain duck typing.
Duck typing is not about what an object “is”, but what it can be used for. Whether an object can be used for something depends on who is using it.
Let’s look at DT’s example from the Pickaxe. Cutting the code down to the bare essentials we’ve got:
def csv_from_row(op, row) #code to compute res from row op << res << CRLF end
Now what kind of duck does op need to be? Simply an object which accumulates objects via the << method.
His first use was:
result = ""
query.each_row {|row| csv_from_row(result, row)
http.write result
</type:code>
This works, but it's slow as the number of rows gets large. Strings meet the requirements of the op parameter, but they also have other characteristics. The important one here is the subtle effect on GC. For a more detailed analysis of this see why's article http://whytheluckystiff.net/articles/theFullyUpturnedBin.html
So let's try to find another object which we can put in the role of the op parameter. Arrays also can be used. So we have
<typo:code lang="ruby">
result = []
query.each_row {|row| csv_from_row(result, row)
http.write resultHowever we’ve now got a little problem in that although an array works as the op parameter, http.write probably won’t like it. But that’s easy to fix, just change the last line slightly to accomodate the new duck in the outer context:
http.write result.join
So, getting back to the theater analogy, when we duck type, we’re in a position similar to a director casting for a role in a play. Sometimes, we find a great actor, but we need to subtly adapt the script to fit his style. That’s what’s happening in DT’s pickaxe example.
Trackbacks
Use the following link to trackback from your own site:
http://talklikeaduck.denhaven2.com/trackbacks?article_id=25




