Duck typing, must it be dynamic?
Asked Answered
D

8

26

Wikipedia used to say* about duck-typing:

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

(* Ed. note: Since this question was posted, the Wikipedia article has been edited to remove the word "dynamic".)

It says about structural typing:

A structural type system (or property-based type system) is a major class of type system, in which type compatibility and equivalence are determined by the type's structure, and not through explicit declarations.

It contrasts structural subtyping with duck-typing as so:

[Structural systems] contrasts with ... duck typing, in which only the part of the structure accessed at runtime is checked for compatibility.

However, the term duck-typing seems to me at least to intuitively subsume structural sub-typing systems. In fact Wikipedia says:

The name of the concept [duck-typing] refers to the duck test, attributed to James Whitcomb Riley which may be phrased as follows: "when I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."

So my question is: why can't I call structural subtyping duck-typing? Do there even exist dynamically typed languages which can't also be classified as being duck-typed?

Postscript:

As someone named daydreamdrunk on reddit.com so eloquently put-it "If it compiles like a duck and links like a duck ..."

Post-postscript

Many answers seem to be basically just rehashing what I already quoted here, without addressing the deeper question, which is why not use the term duck-typing to cover both dynamic typing and structural sub-typing? If you only want to talk about duck-typing and not structural sub-typing, then just call it what it is: dynamic member lookup. My problem is that nothing about the term duck-typing says to me, this only applies to dynamic languages.

Doorknob answered 22/12, 2009 at 17:53 Comment(3)
Just curious, what's the deal with the title-based pseudotags that have been popping up lately?Lenalenard
I tagged this as [CW] because find that that it isn't always sufficiently obvious that something is community wiki. Sometimes I work hard to answer questions but overlook it being CW, getting no reputation bonus (call me a rep whore if you want). I thought I would tag the title to make it obvious to any potential answers, that yes I recognize this as being subjective, somewhat open-ended, but at the same time it isn't a reputation grab on my part.Doorknob
It looks like the claim that duck-typing must be dynamic isn't completely gone from Wikipedia - see en.wikipedia.org/wiki/…Signesignet
D
30

C++ and D templates are a perfect example of duck typing that is not dynamic. It is definitely:

typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.

You don't explicitly specify an interface that your type must inherit from to instantiate the template. It just needs to have all the features that are used inside the template definition. However, everything gets resolved at compile time, and compiled down to raw, inscrutable hexadecimal numbers. I call this "compile time duck typing". I've written entire libraries from this mindset that implicit template instantiation is compile time duck typing and think it's one of the most under-appreciated features out there.

Damnable answered 22/12, 2009 at 17:53 Comment(1)
Structural typing is the term that best expresses the subject here. See Gosu's structural typing feature: gosu-lang.github.io/2014/04/22/structural-types-in-gosu.htmlExclamatory
S
17

Structural Type System

A structural type system compares one entire type to another entire type to determine whether they are compatible. For two types A and B to be compatible, A and B must have the same structure – that is, every method on A and on B must have the same signature.

Duck Typing

Duck typing considers two types to be equivalent for the task at hand if they can both handle that task. For two types A and B to be equivalent to a piece of code that wants to write to a file, A and B both must implement a write method.

Summary

Structural type systems compare every method signature (entire structure). Duck typing compares the methods that are relevant to a specific task (structure relevant to a task).

Substantial answered 22/12, 2009 at 17:53 Comment(4)
This is definitely a clear explanation of what seems to be the commonly accepted wisdom, and that which Wikipedia use. However, I am still questioning this definition. Every dynamically typed language satisfies "duck-typing", so why not use the original term "dynamically typed" for these languages, and use "duck-typing" to cover them plus structural subtyping. Otherwise, if you have structural subtyping in your language, which for most programmers is effectively the same as duck-typing, with a confusing name attached. my predicament make any sense?Doorknob
Dynamic typing describes something very subtly different. A dynamically typed language can still be strongly typed. Sure, the foo variable may be either a Teacher object or a Convict object, but at run-time, the type of foo can be definitely known. Duck typing describes the behaviour of the object. foo can be either a Teacher or a Convict, but I don't care as long as foo can sing(carol). Dynamic typing means that we know an object's type at run-time; duck typing means that we only care whether an object can behave a certain way.Substantial
I liked this post very much, as well as the comment made by you. I wish I could give it more than one upvotes .Krick
Your description of structural typing is flat out wrong for OCaml. let foo bar = bar#baz 1 infers a type of val foo: <baz : int -> 'a; .. > -> 'a, meaning that it can have additional methods as long as there is a method baz which takes an int. Thus, "for the task at hand" applies as well. (I don't claim to speak for the ST found in Scala, though).Burack
P
12

Duck typing means If it just fits, it's OK

This applies to both dynamically typed

def foo obj
    obj.quak()
end

or statically typed, compiled languages

template <typename T>
void foo(T& obj) {
    obj.quak();
}

The point is that in both examples, there has not been any information on the type given. Just when used (either at runtime or compile-time!), the types are checked and if all requirements are fulfilled, the code works. Values don't have an explicit type at their point of declaration.

Structural typing relies on explicitly typing your values, just as usual - The difference is just that the concrete type is not identified by inheritance but by it's structure.

A structurally typed code (Scala-style) for the above example would be

def foo(obj : { def quak() : Unit }) {
    obj.quak()
}

Don't confuse this with the fact that some structurally typed languages like OCaml combine this with type inference in order to prevent us from defining the types explicitly.

Percolator answered 22/12, 2009 at 17:53 Comment(2)
The Scala example does a good job of illustrating what structural typing means. Also notice that with duck typing, if you have an if-branch, the object only needs to have the methods used in one branch or the other. With structural typing, the object's type must include all of the methods the function might call.Lavabo
I like the definition you propose, but where did it come from? Did you just decide upon it, or is there some authoritative reference that I can use?Doorknob
L
6

I'm not sure if it really answers your question, but...

Templated C++ code looks very much like duck-typing, yet is static, compile-time, structural.

template<typename T>
struct Test
{
    void op(T& t)
    {
        t.set(t.get() + t.alpha() - t.omega(t, t.inverse()));
    }
};
Lysander answered 22/12, 2009 at 17:53 Comment(0)
E
5

There are always going to be examples from some programming languages that violate some definitions of various terms. For example, ActionScript supports doing duck-typing style programming on instances that are not technically dynamic.

var x:Object = new SomeClass();
if ("begin" in x) {
    x.begin();
}

In this case we tested if the object instance in "x" has a method "begin" before calling it instead of using an interface. This works in ActionScript and is pretty much duck-typing, even though the class SomeClass() may not itself be dynamic.

Eucharis answered 22/12, 2009 at 17:53 Comment(0)
L
5

It's my understanding that structural typing is used by type inferencers and the like to determine type information (think Haskell or OCaml), while duck typing doesn't care about "types" per se, just that the thing can handle a specific method invocation/property access, etc. (think respond_to? in Ruby or capability checking in Javascript).

Lowerclassman answered 22/12, 2009 at 17:53 Comment(0)
S
4

There are situations in which dynamic duck typing and the similar static-typed code (in i.e. C++) behave differently:

template <typename T>
void foo(T& obj) {
    if(obj.isAlive()) {
        obj.quak();
    }
}

In C++, the object must have both the isAlive and quak methods for the code to compile; for the equivalent code in dynamically typed languages, the object only needs to have the quak method if isAlive() returns true. I interpret this as a difference between structure (structural typing) and behavior (duck typing).

(However, I reached this interpretation by taking Wikipedia's "duck-typing must be dynamic" at face value and trying to make it make sense. The alternate interpretation that implicit structural typing is duck typing is also coherent.)

Signesignet answered 22/12, 2009 at 17:53 Comment(0)
C
2

I see "duck typing" more as a programming style, whereas "structural typing" is a type system feature.

Structural typing refers to the ability of the type system to express types that include all values that have certain structural properties.

Duck typing refers to writing code that just uses the features of values that it is passed that are actually needed for the job at hand, without imposing any other constraints.

So I could use structural types to code in a duck typing style, by formally declaring my "duck types" as structural types. But I could also use structural types without "doing duck typing". For example, if I write interfaces to a bunch of related functions/methods/procedures/predicates/classes/whatever by declaring and naming a common structural type and then using that everywhere, it's very likely that some of the code units don't need all of the features of the structural type, and so I have unnecessarily constrained some of them to reject values on which they could theoretically work correctly.

So while I can see how there is common ground, I don't think duck typing subsumes structural typing. The way I think about them, duck typing isn't even a thing that might have been able to subsume structural typing, because they're not the same kind of thing. Thinking of duck typing in dynamic languages as just "implicit, unchecked structural types" is missing something, IMHO. Duck typing is a coding style you choose to use or not, not just a technical feature of a programming language.

For example, it's possible to use isinstance checks in Python to fake OO-style "class-or-subclass" type constraints. It's also possible to check for particular attributes and methods, to fake structural type constraints (you could even put the checks in an external function, thus effectively getting a named structural type!). I would claim that neither of these options is exemplifying duck typing (unless the structural types are quite fine grained and kept in close sync with the code checking for them).

Colleague answered 22/12, 2009 at 17:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.