What is “duck typing”?

Seriously, what is it? It’s not a rhetorical question. I realized this morning that I am totally confused about this.

First off, let me say what I thought “duck typing” was. I thought it was a form of typing.

So what is “typing”? We’ve discussed this before on this blog. (And you might want to check out this post on late binding and this post on strong typing.) To sum up:

A compile-time type system provides three things: first, rules for defining types, like “array of pointers to integer”. Second, rules for logically deducing what type is associated with every expression, variable, method, property, and so on, in a program. And third, rules for determining what programs are legal or illegal based on the type of each entity. These types are used by the compiler to determine the legality of the program.

A run-time type system provides three similar things: first, again, rules for defining types. Second, every object and storage location in the system is associated with a type. And third, rules for what sorts of objects can be stored in what sorts of storage locations. These types are used by the runtime to determine how the program executes, including perhaps halting it in the event of a violation of the rules.

Typically you want the compile time and runtime type systems to be highly similar and complement each other, which is certainly the case in C#. In a C# program the runtime type of an object is almost always identical to or compatible with the compile-time type of the associated expression, and if somehow it is not compatible (due to, say, an incorrect cast operator) then an exception is produced at runtime.

So I had assumed that “duck typing” was first and foremost a form of typing. That is, duck typing is a system for deducing facts about entities in a program and then deciding whether the collection of facts in the program showed that all parts of it were consistent. What then is the “duck” part? Duck typing is so-called because of the principle “if it walks like a duck and quacks like a duck then it is a duck”. Let’s look at an example in C#:

class Duck
{
  public void Quack() { ... }
  public void Walk() { ... }
}
class OtherDuck
{
  public void Quack() { ... }
  public void Walk() { ... }
}
...
void M(Duck bird)
{
  bird.Quack();
  bird.Walk();
}
...
M(new Duck()); // Legal
M(new OtherDuck()); // Illegal

C#’s static type system says that the relevant fact about new OtherDuck() is that it is of type OtherDuck, but the formal parameter bird is of incompatible type Duck, and therefore this is a violation of the type system. A duck-typed system — again, remember we are talking about what my conception of duck typing here — would allow a program like this:

void N(ducktyped bird)
{
  bird.Quack();
  bird.Walk();
}
...
N(new Duck()); // Legal
N(new OtherDuck()); // Legal!
N(123); // Illegal!

That is, the compiler deduces that the relevant fact about bird is “has methods Quack and Walk“. This is then the type that is deduced for bird. Since the types deduced for new Duck() and new OtherDuck() are compatible with this type, these lines are legal. But since the type associated with 123 is not compatible with the type associated with bird, that line is illegal.

In C# of course one would typically do this with interfaces; you’d define an interface IDuck, have the method take one of those, and have both classes implement the interface. The point of duck typing — again, in my conception — is that the compiler essentially deduces the interface for you, saving you from the inconvenience of having to create and name an interface and then ensure that every class or struct in the universe that you would like to make quack implements that interface.

Somewhat surprisingly, C# does implement this feature in some limited ways. For example, when you say from c in customers where c.City == "London" select c, the type system requires that the type of expression customers be associated with a unique best method or an extension method Where that takes a lambda. This was, again to my mind, duck typing. The type of customers is not required to implement IQueryable or anything like that; rather, the only relevant fact in the type system is “can we find a unique best Where method?”

But C# does not implement this kind of typing in general. Scala does, though Scala requires what I might have characterized as manifest or explicit duck typing. In Scala we could define our method N as follows: (Note that I am not a Scala programmer; I might have made some syntax errors here.)

def N(bird : {def quack() : Unit; def walk() : Unit}) 
{
   bird.quack();
   bird.walk();
}

Scala requires that you state the needed methods up front, but does not require that you define an interface. If the argument passed for bird did not have the requisite methods then the program would not compile.

So that was my understanding of duck typing. So imagine my surprise when I looked it up in Wikipedia this morning and discovered:

In computer programming with object-oriented programming languages, duck typing is a style of typing in which an object’s methods and properties determine the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.

This is off to a bad start. I don’t see what in the slightest object-orientedness has to do with it; it seems perfectly reasonable to have a duck-typed functional language or procedural language. Nor do I see why methods and properties are so important; surely there are other relevant facts that can be deduced from usage. But so far this agrees with my concept more or less. Then we come to:

In duck typing, one is concerned with just those aspects of an object that are used, rather than with the type of the object itself.

Again, this is inelegantly expressed. “Aspects” are not clearly defined; are these the “methods and properties” mentioned before? Worse, there seems to be a fundamental incoherency here: that the object has a “real type” of itself. Is this trying to draw a distinction between the runtime and compile time types? What exactly is meant by “object” here? I think of objects as being a runtime concept. Though this is perhaps badly stated, it still agrees more or less with my conceptualization of duck typing. But then we come to:

For example, in a non-duck-typed language, one can create a function that takes an object of type Duck and calls that object’s walk and quack methods. In a duck-typed language, the equivalent function would take an object of any type and call that object’s walk and quack methods. If the object does not have the methods that are called then the function signals a run-time error.

My emphasis.

But this is not even typing in the first place! We already have a name for this; this is late binding. “Binding” is the association of a particular method, property, variable, and so on, with a particular name (or operator) in a particular context; if done by the compiler then it is “early binding”, and if it is done at runtime then it is “late binding”. (As I noted in the article linked above, certain forms of binding such as virtual method calls have both early and late aspects; the “virtual method slot” is bound early but the contents of that slot are determined late.) Why would we even need to invent this misleadingly-named idea of “duck typing” in the first place??? If you mean “late binding” then just say “late binding”!

So OK, perhaps my whole concept of duck typing all these years has simply been wrong. All those people who said “duck typing” actually meant “late binding”, and I just didn’t realize they were synonyms. But the Wikipedia page goes on to say:

Certain usually statically typed languages such as … C# have extra type annotations that instruct the compiler to arrange for type checking of classes to occur at run-time rather than compile time

The page is of course referring to dynamic which it then goes on to say is how you do duck typing in C#. But I don’t think of dynamic typing in C# as duck typing at all; rather, it means “defer what would normally be the compile-time analysis of this expression until runtime, and use the runtime type of the object as the compile-time type. (As an aside I note that the actual meaning is rather more subtle; the runtime type might not have been accessible at the call site. The type actually used is the most derived type that would have been accessible.) of the object as the compile-time type.” Again, this is late binding, not (again, to my mind) duck typing.

And the page then goes on to say, bizarrely and ungrammatically:

Other statically typed languages like F# supports static duck typing which verifies on compile time that the type have the specific method available

Wikipedia started this article by saying that duck typing happens at runtime in object oriented languages, and now apparently we are saying that it also happens at compile time in a functional language?! And it then goes on to give an example in Scala that is again, checked at compile time rather than at runtime, despite stating several times in the article that duck typing only means runtime checking, except when it doesn’t.

I am utterly confused, and I am coming to believe that either this Wikipedia page is incoherent, or worse, the whole idea of duck typing is fundamentally incoherent.

Can anyone out there resolve this for me? Or do I have to treat “duck typing” the same way I treat “strong typing”? “Strong typing” without a careful definition is essentially meaningless; any two people talking to each other can reasonably have completely opposite definitions of “strong typing” in their head. Apparently for a long time that has been true of me and “duck typing”; anyone else I talked to using that term likely thought I meant something completely different, and I might have been the one in the wrong.

Oh and happy new year all!

About these ads

108 thoughts on “What is “duck typing”?

  1. Hey Eric,

    Your Scala code is almost perfect. You just need an = sign after the method signature and before the first open bracket for it to be syntactically correct:

    def n(bird: { def quack(): Unit; def walk(): Unit }) = { … }

  2. What is present in most dynamic languages that are characterized as duck-typed cannot be called “typing” in any nontrivial sense.

    In C#, once you have a “string” object (verified by the runtime type system), you know what kind of operations you can perform on it (guaranteed to be meaningful by the static type system); nothing in Ruby or Python makes such checks on your behalf or gives you any guarantee – the only checks performed are on the level of a single invocation and it makes no more sense to call that “typing” than to call the empty string a separate type of string because it raises an exception on .Substring(1).

    To reason about the supported operations on an object you have to query it explicitly or examine it’s type – but that’s not a “type system” any more than checking string.Length against zero.

    • > What is present in most dynamic languages that are characterized as duck-typed cannot be called “typing” in any nontrivial sense.

      I really have to disagree with your choice of words here.

      What you call “typing” is actually called “static typing”. Javascript, Ruby and Python use “dynamic typing”. They represent a totally different idea and purpose, and should not be confused.

      As static typing has been extensively studied in academia, it is totally ok that people that study Computer Science and write papers just say “typing” to refer to static typing — because Computer Science do not interests itself in dynamic types that cannot lead to proof about programs.

      However, there is also the side of practice. One should not forget that programs written in dynamically-typed languages exist, and that they do make use of dynamic types to store metadata about the runtime instances, and that all of this is used and useful.

      So, when both world meet, as in discussions about “duck typing” (which is not a clearly defined Computer Science term), I think that a big part of the confusion would be avoided by simply disambiguating between static types and dynamic types.

      For example, as a (sometimes) user of dynamically-typed languages, I feel kinda offended when you say that duck typing is not typing. But were I to read a modified version of your comment where every occurrence of “type” is replaced by “static type”, suddenly your comment would become perfectly correct to my eyes.

      Let’s read again a modified version of your first sentence :

      > What is present in most dynamic languages that are characterized as duck-typed cannot be called “*static* typing” in any nontrivial sense.

      Now it’s good!

      • @Eldc, I meant and still mean exactly what I wrote – there is no typing framework, static or runtime, that does any nontrivial work on your behalf. And no, tagging objects with their constructed type isn’t enough. Consider the following Python fragment:

        if foo.bar():
        foo.asfd()
        else:
        foo.moo()
        end

        Semantically, the above is valid if either 1) foo’s runtime type defines “bar”, which returns a bool, and 2) foo’s runtime type defines “asdf” or “moo”, depending on the output of bar. Not only will bar() be executed regardless of the validity of 2), the validity of the entire code fragment may change at runtime for the same object instance. Any and all checks for such conditions are up to you, hence no “typing system”.

        • Your example of how dynamic typing does not statically enforce anything sits well with the differences I see between static typing and dynamic typing. Obviously types in Python are not part of a static type system, but they are certainly part of a dynamic system, whose goals do not even include static proof.
          I would like to understand how to explain my point better, but it seems this will remain fruitless. Oh well. I continue to blame the choice of words.

          • I’m sorry but I believe you’re missing my point by concentrating on “static”-ness, whereas I’m arguing about what is required for a typing “system” to be said to exist in the first place.

            A meaningful example of a *dynamic* type system would take the fragment above and validate it at runtime, before any of the code is executed – for example, when the containing method is entered (of course since objects are fluid, this could still be broken, but it does provide some nontrivial safety net). We don’t even get that, so what’s the point of talking about a typing system in the first place? What is your definition of a typing system?

  3. Pingback: Interesting stuff about Duck Typing | Code Mischiefs

  4. I think it can be summed up like this: Duck Typing is an “After the Fact” assessment whereas Static Typing is a “Before the Fact” assessment. In static typing, we can achieve in two ways – via an interface or a class. A class will state what an instance or its children will have. With an interface, it states what something *can* be at least in part. Both of these determinations can be made before they exist. With Duck Typing, we only know what something is until after it has been created.

    In a duck type world, if I have all of your members, we are of the same type. I may have additional members, which makes me a more specialized type of you – but we are still of the same type. In the OO world, to be of the same type, we have to share some common lineage, either via a class or interface inheritance.

    A good analogy is this. In the old days of the British Aristocracy, to be *of* them, you had to be born into it (inherited). Even if you had as much money, property, an estate, etc (AKA you looked like them) – you would never be of them. But if it was a duck type world, then you would be of them since you had all the same semantics.

  5. This discussion missed a key element of Duck Typing, which is that you can add a new method to the type at runtime:

    var x = 7;
    x.Triple() = function() { return this * 3; }
    var y = x.Triple(); // y is 21

    // This function turns any object into a Duck
    function MakeDuck(something)
    {
    something.Quack = function() { alert(“Quack”); }
    something.Walk = function() { alert(“Walk”); }
    }

    var x = “dog”;
    MakeDuck(x);
    x.Quack();
    x.Walk();
    // This instance of “dog” is now also a duck

    TypeMock and Castle Dynamic Proxy add Duck Typing to C#. I found TypeMock to be phenomenal for creating mock objects.

  6. Pingback: Programming 이슈. 1월 1주 | devgrapher

  7. The way I see it is this:

    Duck typing is a form of typing in which type correctness is verified by the actual use of the object at the use spot (rather than contracts present in its declaration). This may take the form of:
    1. Constraints expressed on-the-spot (and by that I mean constraints that are not expressed in a formal interface acting as a contract in the object’s declaration), which can be verified using compile-time analysis (but this is an implementation detail) or
    2. Direct (unconstrained) usage, the legality of which is verified completely at runtime, using some form of late binding, as you’ve said (again, this being an implementation detail).

    Now, I recognize that the quotations you picked from the Wikipedia page are contradictory, as you’ve pointed out, and I definitely can’t speak for the author(s) of the page, but the above is what I think they meant and how I think of duck typing. (…And I might be dead wrong or contradicting myself without realizing it, as well!)

  8. > it seems perfectly reasonable to have a duck-typed functional language or procedural language.

    I suspect any functional or procedural language that you think it seems reasonable to have duck-typing in is also an object-oriented language by a sufficiently expansive definition of “object-oriented”.

  9. You’re conflating two different issues in binding of a call.

    1. Is binding done using the static type of the expression or the dynamic type of the object?
    2. Is binding done by the method’s name or signature?

    In C#, you have (static, signature), (dynamic, signature), and (dynamic, name).

    (static, signature) – A call to a non-virtual method
    (dynamic, signature) – A call to a virtual method
    (dynamic, name) – Use of the “dynamic” keyword

    Duck typing corresponds to (*, name)

    There’s a form of duck typing which is not dynamic binding or late binding. C# does not have it, other languages do. It’s the fourth tuple:

    (static, name)

    It applies only to generic code, and it means that method resolution is done based on looking for the named method in the actual compile-time parameter type. In constrast to .NET generics where, as we know, overload resolution uses the constraints, and then the method matching that signature is used from the actual compile-time argument (where signature is equivalent to vtable slot — it includes “what function I overrode” as well as argument types).

    MethodBase.IsHideBySig seems like a related concept.

  10. I like that compile-time view of duck typing. Just being able to call everything on every object and risk runtime failures is not a solution for a language like C#.

    What I like is the definition of interfaces on the call side instead of the classes themselves like in the Go language (I’ve just had a short look at the language but that caught my eye). At least that’s a good thing in some situations where we want to have an abstracted view on the behaviour of sealed classes or just want to avoid subclassing from 3rd party classes to make them fit to a certain interface.

    Might there be a chance to get language support for automatic proxy generation or something like this in a future version of the C# compiler? Or are there remarkable drawbacks or problems implementing such explicit duck typing support in a .NET language?

  11. Thank you for this interesting post. My understanding is that duck typing is largely akin to structural typing and is defined by when binding occurs. The Wikipedia definition seems to conflate duck typing with late binding as you say. This is probably because the term is often used in the context of dynamically typed, late-bound languages such as Python.

  12. Pingback: Programming 이슈. 1월 1주 | TDD

  13. Pingback: Patos y código C# | Mouseless Me

  14. In all the discussion nobody seems to be bringing up semantics. I thought everyone kind of knew that duck typing refers to the idea that any object that conforms to an implicit contract (e.g. that has a certain set of methods) is accepted as a duck and all the comparisons with static typing or any typing at all are beside the point.

    My impression was that duck typing talks more about something like “behavioral subtyping”, e.g. it’s important what happens once quack() is actually called, not whether quack exists. That’s what I got out of the “don’t check whether the object has quack()” lingo in the old quote.

  15. Long-time Python programmer here.

    tl;dr Duck typing is based around conventions, written in the docs instead of code. This allows the language to defer the type system.

    You’re not actually too far off. Like the distinction between static and dynamic languages, there’s also a “static” and “dynamic” concept of duck typing, which isn’t often discussed.

    You nailed “static” duck typing with “again, in my conception — is that the compiler essentially deduces the interface for you, saving you from the inconvenience of having to create and name an interface and then ensure that every class or struct in the universe that you would like to make quack implements that interface.” The obvious advantage is that you catch some problems at compile-time.

    With “dynamic” duck typing, the concept is the same, but you don’t get the compile-time check. Late-binding is the mechanism here. (And so, as you pointed out, they are equivalent on a technical level.) The difference is subtle. With duck typing you start giving explicit names to these “types” and describe them in the docs, function docstrings, and with argument name conventions. And you can verify them at “test-time” with some good tests. There’s no assumption about what you mean when you say a variable is “late-bound” though. Other than “try to use these members when the time comes.” Usually you do have one or more language-defined types in mind with late-binding.

    For example, in Python you have “Iterator types” [1]. The only expectation, as per the docs [2], is to provide an __iter__ method. Any function that takes a an “iterator” object, as indicated in its name, docstring, etc, then you’d better pass it an object you can iterate over. File objects are a little more complicated, but notice the docs still only require a handful of methods for a type to be considered “file-like” [3]. The Python community does understand the importance of type inspection though, so they added Abstract Base Types [4] in 2.6 to help in a more consistent way.

    Now the question is “why would I ever do this?” I’ll try to give a practical answer. It’s simply because we haven’t discovered a better type system. It’s deferred until we do. With duck typing, you say an object is an X, but you don’t encode what that means into the language directly. Rather, you describe it in your docs and verify it with your tests. This is easy to do in Python because of its late-binding. If Python did implement “inferred interfaces,” that would restrict the language from adopting a better approach later, such as pysonar [5]. (Also, I don’t think some of these techniques were around / popular at the time Python introduced duck typing. Or it was too much work. One difficulty is that Python is interpreted, so when would these type checks happen? And how would you do this across all modules, since imports are resolved at runtime?)

    Hope this helps.

    [1]: http://docs.python.org/2/library/stdtypes.html#iterator-types
    [2]: “One method needs to be defined for container objects to provide iteration support”
    [3]: http://docs.python.org/2/library/stdtypes.html#file-objects
    [4]: http://docs.python.org/2/library/abc.html The Rationale section is a good read on the philosophy
    [5]: http://yinwang0.wordpress.com/2010/09/12/pysonar/ is an interesting approach. It’s big though. Not something Guido would have wanted to do because it involves a lot of research and would have delayed Python. Worse, if he didn’t get it right, the language surely would have failed. I’m sure there will be even better techniques in the future. Verifying Turing-complete code is, well, hard.

  16. Pingback: What is “duck typing”? | Fabulous Adventures In Coding | josephdung

  17. Pingback: What is late binding? | Fabulous adventures in coding

  18. Pingback: Following the pattern | Fabulous adventures in coding

  19. As this seems to be a rather philosophical discussion, I cannot help but pointing to the concepts of the substance of objects vs. bundles of properties.
    While the substance-approach to describe things seems to be more common, the bundle theory also provides a nice framework to describe objects.

    So in my opinion, duck typing is the application of the bundle theory (http://en.wikipedia.org/wiki/Bundle_theory) to programming languages.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s