4 ms·
Duck typing is according to Wikipedia: https://en.wikipedia.org/wiki/Duck_typing https://en.wikipedia.org/wiki/Duck_typing Duck typing as a concept was re(?)-p
by loopz 7y ago
Duck typing is according to Wikipedia: https://en.wikipedia.org/wiki/Duck_typing https://en.wikipedia.org/wiki/Duck_typing
Duck typing as a concept was re(?)-popularized around the advent of ruby, so might make sense to talk from a ruby perspective: http://rubylearning.com/satishtalim/duck_typing.html http://rubylearning.com/satishtalim/duck_typing.html
With ruby, most everything you interact with is a true object, ie. you can modify behaviour of almost all classes/objects by adding/removing methods, mixin, etc. It's not unheard of monkey patching Integer or Array classes, core parts of standard library and language. Thus, you could dynamically invoke any object with any methods, without regards to compile-time constraints or "types". Errorhandling thus delegated almost entirely to runtime beyond basic syntax parsing.
Golang furthers the notion of capabilities as shared method signatures, by loosely binding this into interfaces, and enforcing many errors by static type checks at compile time. It's interesting as a development away from inheritance and towards composition and loose coupling of static program components.
- tgv 7y agoWouldn't that make any language with reflection Duck-typed? That would suggest Wikipedia's definition is not very useful.
- loopz 7y agoFair question! "Duck typing" can be implicit, if you can call quack() on this() without error, you (the programmer) assume it's a Duck. The language may make it explicit (loosely structural typed like in golang, or other variations), or implicit (like in ruby). There are varying degrees, but you should be able to have a collection of the "Ducks" and be able to invoke quack() on them all. Can't really say I see the connection with reflection. If quack() fails, you can get an error, either at runtime or compile-time. So no reflection required, though using reflection you may avoid errors dynamically. Structural Typing as a concept is much better defined though.
- abhorrence 7y agoReflection isn’t required, but with sufficient reflection a language could essentially be extended to include duck typing.
- lmm 7y agoNo more than any language with casts is untyped. Reflection lets you avoid the type system and program in a duck-typed way, but unless the language uses reflection for normal values and functions then I wouldn't call the language duck typed as a whole.
- lkitching 7y agoI'm not sure what you mean by 'not exact' since the article you posted explictly contrasts duck typing with structural type systems of which Go is given as an example.
- deleted 7y ago[deleted]
- Footkerchief 7y agoThe contrast in the Wikipedia article is: > Structural typing is a static typing system that determines type compatibility and equivalence by a type's structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type's structure that is accessed during run time. That sounds like static vs. dynamic implementations of the same thing.
- lkitching 7y agoThe fact that one is checked statically and the other is only enforced at runtime is a significant different between them, since the static approach will reject some programs that are dynamically safe. The term duck typing when employed by dynamic languages like Ruby is misleading since it's a consequence of not having a type system at all.
- derefr 7y agoWhen you're talking about type systems, "dynamic" really doesn't make much sense to talk about. It's not like the runtime constructs a typing model out of its observations of the properties of objects' runtime interactions. The notion of there being a "type" to a duck-typed object is purely a theoretical one; in practice, the object just does whatever it wants moment-to-moment, and the runtime has no idea. Consider a generic "proxy" object that can be arbitrarily disconnected and reconnected to objects of different types. These can exist in any duck-typed runtime system. What is such an object's "type", even in the sense of its "runtime type"? There isn't one. There might be a sense in which it has an instantaneous type—a type it has as of a given program world-state—but that information is inaccessible to the runtime, since any probing it might do to ascertain this might also cause the object's instantaneous typing to change in the middle of the probing procedure. (See also: the Universal Server in Erlang [ https://joearms.github.io/published/2013-11-21-My-favorite-erlang-program.html https://joearms.github.io/published/2013-11-21-My-favorite-e... ]. What is this server's "type"?) A type system is something that can make guarantees about the behavior of a program in advance. In that sense, duck-typing isn't really a type system. It's just asking objects questions and then blindly trusting the responses you get. There's nothing but convention guaranteeing that an object that e.g. in Ruby implements `respond_to?` a certain way, will _actually_ respond to those methods when they're called. The object can lie. Which means you don't have a guarantee, and so you don't have a type system.
- taklon 7y ago> Golang furthers the notion of capabilities as shared method signatures, by loosely binding this into interfaces, and enforcing many errors by static type checks at compile time. This, I think, is the main point of the parent comment. I think the distinction (and overlap) come into focus when you think computationally: how is a type computed? Type semantics are determined by the type checker, and Go's interface types are checked at compile time. Duck type checking happens at runtime. There's no language support in Go for this, but the closest thing would be passing a bunch of empty interfaces around and using the stdlib's reflect package everywhere so that you never panic, but sometimes return a user-generated TypeError. Sure, Go's interfaces allow clients to accept multiple concrete types, but that's checked at compile time, not runtime, and so it will never be duck typed.
- GlitchMr 7y agoWhile Go interfaces are usually checked at compile time, this doesn't have to be the case - you don't even have to use reflection. Consider the following program. package main import "fmt" type Dog struct{} func (d Dog) NumberOfLegs() int { return 4 } func (d Dog) Genus() string { return "Canin" } func main() { var dog interface{} = Dog{} fmt.Println(dog.(interface{ NumberOfLegs() int }).NumberOfLegs()) fmt.Println(dog.(interface{ Genus() string }).Genus()) fmt.Println(dog.(interface{ Happy() bool }).Happy()) } This fails at runtime, as `Dog` doesn't have `Happy` method.
- loopz 7y agoWhy do good people downvote what they don't understand? https://play.golang.org/p/d0TkGTCZa2S https://play.golang.org/p/d0TkGTCZa2S Runtime results in panic: 4 Canin panic: interface conversion: main.Dog is not interface { Happy() bool }: missing method Happy goroutine 1 [running]: main.main() /tmp/sandbox251002434/prog.go:18 +0x200 Using interface casting, Golang do support "duck typing" in similar fashion as ruby's Object class. Here, by convention, the instance of Dog doesn't support "type" Happy(), therefore fails at runtime. So golang is somewhat dynamic as well, although using interface{} is kludgy and one would want to avoid that and reflection whenever possible.