The article suggests that static typing precludes duck typing. However, duck typing can work just fine at compile time. Duck typing simply means typing based on the ability to use particular methods or access particular properties. That just means the type system needs sufficient expressiveness to say that a function takes anything for which a particular method or property exists.
Haskell's typeclasses, for instance, support a form of duck typing. Go can do something similar with its interfaces.
Duck typing does not imply dynamic runtime typing; static duck typing seems just as useful.
Exactly the term I wanted, thanks! Just didn't manage to remember it.
Structural typing allows the creation of functions which only require their inputs to have the specific methods or properties needed to perform the given function, rather than an exact type. Effectively, this creates a minimal supertype for each function, such that the function can accept any subtype of that minimal supertype.
The common bias against structural typing is that there might be types with the same structure but subtly different semantics, e.g. coordinate systems. Same structural type, different semantic:
struct carthesian_coords { int x; int y; }
struct polar_coords { int r; int theta; }
Most of the structural typing systems I've seen count the names of fields as part of the type, not just the types of the fields. So, those two structs would have incompatible types in such a system.
Namely, "playing fast and loose with data representation"? That makes more sense, yeah. And now, it fits nicely with "pointer tricks" as something I can happily live without.
Mutation, on the other hand, I can easily see the arguments for either way; it represents a pretty large thing to give up in exchange for a more "obviously correct" programming environment. But pointer tricks have no place outside of low-level systems programming (OS kernels and language runtimes), and as little of that as possible to bootstrap something more comfortable.
I work on BITS (http://biosbits.org/), a project based on GRUB for doing BIOS testing. It has a pile of low-level C code to interface with hardware and system facilities, as well as other existing C interfaces like ACPICA; however, a while ago we ported the Python runtime, and since then we've ported more and more of the functionality to Python scripts.
Python doesn't have static typing, but it does handle memory management and object lifetimes automatically. It represents a good balance of high-level safety and comfort, acceptance by the target audience, and ease of porting to a freestanding environment with no OS support. I still wish I could find and eliminate more errors at compile time rather than only at runtime, but Python certainly manages to avoid the chainsaw-juggling feeling of programming in C.
Haskell's typeclasses, for instance, support a form of duck typing. Go can do something similar with its interfaces.
Duck typing does not imply dynamic runtime typing; static duck typing seems just as useful.