In article <52245df4$0$2743$c3e8da3$76491...@news.astraweb.com>, Steven D'Aprano <st...@pearwood.info> wrote:
> One factor I don't see very often mentioned is that static typing > increases coupling between distant parts of your code. If func() changes > from returning int to MyInt, everything that calls func now needs to be > modified to accept MyInt, no matter how similar MyInt is to int. You have > to make changes just to satisfy the compiler. This really ties in with what I was getting at in: Message-ID : <roy-dfb5e5.20525231082...@news.panix.com> Subject: Re: Interface and duck typing woes Date: Wed, 28 Aug 2013 21:27:34 -0400 Every interface requires certain things and promises certain things (i.e. the contract). At some point, the caller and the callee have to agree on what's required, what's allowed, and what's a bug. There's lots of ways of doing that. At one end of the spectrum, there's the type bondage languages like C++ and Java. But even there, you have things like: double sqrt (double x); which only tells part of the "what's required" story. For the rest of the story, you have to resort to reading the natural language documentation: "If the argument is negative, a domain error occurs" At the other end of the spectrum, there's Python's duck typing, which says, "Give me something, and I'll let you know if I can't deal with it". But we're still not playing 20 questions. Presumably, the callee gives you some kind of hint about what sort of duck they're expecting. It seems to me that any time you can encapsulate knowledge about the contract into something that's machine readable, you've added value. Now you can have automated tools do something useful with that knowledge. Maybe that means raising an error at compile time, or when you run a static analysis tool. Or, more apropos to Python, at function call time using pep-3107 annotations. So, let's go back to your original statement (requoted here for convenience): > One factor I don't see very often mentioned is that static typing > increases coupling between distant parts of your code. If func() changes > from returning int to MyInt, everything that calls func now needs to be > modified to accept MyInt, no matter how similar MyInt is to int. You have > to make changes just to satisfy the compiler. It's not that static typing has increased coupling. The coupling has always been there, it's just that now it's being enforced at compile time. What's the difference between int and MyInt? I'm going to speculate that ints are 64 bit 2s-complement binary and MyInts are BCD-encoded fixed-width character strings with leading blank padding. The problem is NOT that static typing forced me to change every place that calls func(). The problem is that func() has fundamentally changed, and THAT is what's forcing me to change all my code that calls it. The static typing just lets me communicate that to the compiler. I actually think Java was on the right track with interfaces. They are essentially duck typing enforced at compile time. Rather than saying, "You must pass me a Duck", you're saying, "You must pass me something that has quack(), waddle(), and poop() methods". If I later change func() to also call your_object.fly(), I've changed the contract on you. And whether you know about it or not, your code and my code are coupled. The difference is that with static typing, you find out about it quickly, and with pythonic duck typing, you may not find out about it until three years later when some unusual condition finally causes the fly() code path to get executed and you've long since moved on to another project. The next step is to understand that the real contract may be more complex than can be easily encapsulated in a type or annotation or whatever. The contract may be: "You must pass me something that can quack(), waddle(), and poop(). In addition, if it's a full moon, it must also be able to fly()." So, the big question is, how should I specify that to a human, and how should I specify that to the computer? -- http://mail.python.org/mailman/listinfo/python-list