Live data from Hacker News

Is Go Duck-Typed?

bionic.fullstory.com

81–89 of 89 posts

Re: Is Go Duck-Typed?

#81
post #71
post #66

Earlier quoted context omitted.

On JVM level, yes. But on Java level, the type of the method is structurally matched to the type of the interface.

The name of the function is typically the same though, even with structural typing. This doesn’t seem quite like that.

If you mean the name of the function in the interface, it's basically ignored in this pattern, similar to how argument names are ignored. The entire interface definition should be treated as a function type with some redundant metadata.

Re: Is Go Duck-Typed?

#82
post #49

Earlier quoted context omitted.

A function explicitly has no further semantics than its inputs and outputs. The receiving function shouldn't, and won't, assume anything about what the function it's passed does. Whereas when you're passed a bundle of named functions that (presumably) share state between them, it's very natural to assume that this implies relationships between how those functions will behave (even in the simplest examples, e.g. Java'…

You have the same issue if you pass multiple callbacks to a given function, except as previously mentioned, you're more likely to pass the wrong set of callbacks than to pass the wrong interface implementation (because interface methods are named must be bound to the same data).

Right, but you don't do that. The people who are happy passing functions around are not happy passing multiple callbacks around, by and large. (For example, rather than separate hasNext and next functions, you'd have a single function that returned an optional value).

Re: Is Go Duck-Typed?

#83
post #75

Earlier quoted context omitted.

Nothing can go wrong with a single function like Write - but in that case you don't need a structural type, you can just pass a write function. As soon as you pass a bundle of two or more functions, you're implying a relationship between them, and it's then easy to accidentally violate that relationship - for instance, a structural type will almost always admit a mutable implementation where the relationship breaks d…

Like I said elsewhere in the thread, you can have the same problem with callbacks: func receiver(next func() bool, getItem func() Foo) {} vs type FooIter interface { Next() bool; Item() Foo } func receiver(iter FooIter) {} You're more likely to pass the wrong set of callbacks than to pass the wrong FooIter implementation since the type system doesn't require the callbacks to be related to the same data nor named any…

Replied elsewhere.

Re: Is Go Duck-Typed?

#84
post #35
post #2

This is called Structural Typing[0] and is in contrast to Nominal Typing[1] (e.g. Java). 0: https://en.wikipedia.org/wiki/Structural_type_system 1: https://en.wikipedia.org/wiki/Nominal_type_system

I think the difference between structural typing and duck typing is one of explicitness. When passing an object `o` into a function `f`, structural typing enables `f` to explicitly say “`o` must support `a`, `b` and `c`”, even if `f` only ever calls `a` and `b`. With duck typing, the interface is implicit - if `f` only calls `a` and `b`, then that’s exactly what `o` needs to support. Duck typing also allows more dyna…

Why not just have "a" return something containing "b"? In Python 3.8 for the brief syntax afforded by assignment expressions:

    def foo(o):
        if (b := o.a()) is not None:
            b()
Because the original interface indicates that all "o"s must know about the link between "a" and "b", there's no loss of generality, but now there's a statically inferable structure: "o" must support an "a" that returns None or a callable.

If you do a tiny modification to "def foo(o, a): ..." then this doesn't apply any more, and you're outside the realm of structural types and into the realm of dependent types, which means you must drink deeply of the static typing kool-aid and want to write type signatures that run the risk of being more complex than the code they describe.

(But I like to quote Conor McBride: "if you're not going to write types your type system has to be stupid enough a computer can do it", from https://www.youtube.com/watch?v=3U3lV5VPmOU&feature=youtu.be...).

Re: Is Go Duck-Typed?

#85
post #82

Earlier quoted context omitted.

You have the same issue if you pass multiple callbacks to a given function, except as previously mentioned, you're more likely to pass the wrong set of callbacks than to pass the wrong interface implementation (because interface methods are named must be bound to the same data).

Right, but you don't do that. The people who are happy passing functions around are not happy passing multiple callbacks around, by and large. (For example, rather than separate hasNext and next functions, you'd have a single function that returned an optional value).

I agree, but we're arguing about a hypothetical bug scenario that has probably never ever happened: accidentally implementing this sort of stateful interface. These stateful interfaces are already very rare (at least in Go) and accidentally implementing an interface is itself vanishingly rare (I don't think I've ever heard of this happening in practice). It doesn't make sense to me to take grievance with Go's interfaces (which offer strictly stronger protections than callbacks), but be okay with naked callbacks on the basis that "people tend not to use them in a stateful manner" (never mind the stateless scenario in which bare callbacks also provide weaker guarantees than Go's interfaces).

Re: Is Go Duck-Typed?

#86
post #46
post #11

Earlier quoted context omitted.

I tend to use nominal types a lot in other languages, so I have a lot of types with id() or value(). Would those be mixed up?

In practice if your 'id() string' method returns an id as a string for the object doesn't it do what you need it to? So you actually need to care whether the intended to satisfy your contract or not? You might care if you expect the Id string to look a particular way. But then you probably wanted to use a type other than string for the return type.

> you probably wanted to use a type other than string for the return type.

That's the point. In order for (String userId) to not be confused with (String password), I wrap them with nominal types UserId and Password.

If the language looks at both UserId and Password and decides they're interchangeable because they both satisfy the contract 'contain a String', then that completely negates the point.

Re: Is Go Duck-Typed?

#87
post #41

Earlier quoted context omitted.

It has already caused several issues in golang, and this is an example: https://github.com/golang/go/issues/16474

That’s a different issue. This is not just using structural interfaces but downcasting to even lower interfaces without warning. That is, the method lies about what it’s looking for.

[deleted]

Re: Is Go Duck-Typed?

#88
post #41

Earlier quoted context omitted.

It has already caused several issues in golang, and this is an example: https://github.com/golang/go/issues/16474

That’s a different issue. This is not just using structural interfaces but downcasting to even lower interfaces without warning. That is, the method lies about what it’s looking for.

It will cause issues if a type implements the interface where it didn't mean to.

Re: Is Go Duck-Typed?

#89
post #82

Earlier quoted context omitted.

Right, but you don't do that. The people who are happy passing functions around are not happy passing multiple callbacks around, by and large. (For example, rather than separate hasNext and next functions, you'd have a single function that returned an optional value).

I agree, but we're arguing about a hypothetical bug scenario that has probably never ever happened: accidentally implementing this sort of stateful interface. These stateful interfaces are already very rare (at least in Go) and accidentally implementing an interface is itself vanishingly rare (I don't think I've ever heard of this happening in practice). It doesn't make sense to me to take grievance with Go's interfa…

> we're arguing about a hypothetical bug scenario that has probably never ever happened: accidentally implementing this sort of stateful interface. These stateful interfaces are already very rare (at least in Go)

Any interface can be implemented by something that's accidentally (or intentionally) stateful - there's nothing that prevents that in Go. And a interface containing more than one function almost certainly has an implicit relationship between those functions that an implementation could accidentally violate.

> and accidentally implementing an interface is itself vanishingly rare (I don't think I've ever heard of this happening in practice).

Accidentally implementing an interface must happen all the time - not in the sense of unrelated functions having a name collision, but in the sense of implementing a type that looks like another type and not explicitly looking through all the interfaces that other type implements and what expectations they carry.

> It doesn't make sense to me to take grievance with Go's interfaces (which offer strictly stronger protections than callbacks), but be okay with naked callbacks on the basis that "people tend not to use them in a stateful manner" (never mind the stateless scenario in which bare callbacks also provide weaker guarantees than Go's interfaces).

Naked callbacks make it clear what the expectation is and where the responsibility lies. It's the same as the idea that bad encryption is worse than no encryption at all, or a datastructure that is "mostly threadsafe" is worse than one that immediately errors when used from multiple threads.

Post reply on HN