Hacker News new | ask | show | jobs
by neonsunset 662 days ago
> So, is there an ELI5 for the difference between structural typing and duck typing?

Likely just semantics. You could argue that the sliver of difference is just treating something like a particular API shape hence duck typing over structurally matching to an interface. For practical purposes however it does not matter. The runtime vs compile time argument is purely an implementation detail that has no relation to structural matching aka duck typing (heh) otherwise.

In practice, I find this idea rather uncomfortable and C# has been avoiding it except for few very defined cases that are least likely to cause this confusion, like GetEnumerator and Enumerator.MoveNext+Current (it could be used as an enumerable in foreach loops but unless the type implements IEnumerable, you can't coerce it to the type).

For the cases where specialization is needed, it is usually written as

     // could also be Handle<T> where T: IDataArg to avoid boxing for structs
     // as struct generics in .net are zero-cost via monomorphization

     void Handle(IDataArg arg) {

         if (arg is IPooledArg pooled) {
             var rented = arg.Rent();
             // do something with the arg
             rented.Return();
         }

         // slow path
     }
No type confusion is possible as whatever is passed to the method has to declare it implements IDataArg. Same applies to 'arg' being 'IPooledArg' - it could have methods with names that would make it match the interface structurally but this is, quite literally, not a type-safe assumption. The authors may have explicitly decided not to expose it, or to provide explicit interface implementation that differs from pre-existing names.

All this is very upfront and you won't be finding yourself having to rename methods or be surprised when your objects or structs are used in a way they are not supposed to because their triangle-shaped type happened to fit in a square-shaped interface hole.

1 comments

Thanks for your reply.

I think I share your perception of ugliness in TS.

It feels like in TS, most if not all of the worries around complex types originate in compromises like this, or in other words, structural/duck typing.

Also feels a bit like functions are an elephant in the room. Function types with structural typing for parameters, arguments and return values are useful.

But then you have to use overloads and "extends" in generics for the first time in order to *describe* something, and if you're like me, you might cry a little from the inside. Especially when you simultaneously chastise yourself for wasting time on ignorable TS issues.