2019-09-08

1: The Revealed Reality of "Duck Typing"

<The previous article in this series | The table of contents of this series | The next article in this series>

In fact, "Duck Typing" does not represent the reality well. 'Dodo Typing' or 'Duckelatta Typing' will be a more suitable name.

Topics


About: The Python programming language
About: "Duck Typing"

The table of contents of this article


Starting Context


  • The reader has a basic knowledge on object-oriented programming.

Target Context


  • The reader will understand the reality of "Duck Typing".

Orientation


There is an article that introduces the minimal sufficient technique for doing static types checking in Python with mypy.


Main Body


1: A Duck? No, It Is a Dodo, or What?


Hypothesizer 7
The well-known explanation on "Duck Typing" is "If it walks like a duck and it quacks like a duck, then it must be a duck.".

A problem is that it is not a duck, but a dodo.

So, does it quack like a dodo? But how does a dodo quack? . . .

In fact, more problematically, it is not a dodo, but a duckelatta.

So, the explanation should be really "If it walks like a duckelatta and it quacks like a duckelatta, then it must be a duckelatta.".

Well, how will that statement be useful for me? . . . 1st, I do not know how a duckelatta walks, quacks, or whatever-ks, so, I have no idea whether it is quacking like a duckelatta or not, and 2nd, what, the hell, is "duckelatta"?!

The answer is, only the mad programmer should know.

Is it OK for you because you are the mad programmer? Well, I said "the mad programmer should know", but do you really remember how each of duckelatta, swannata, turkeylatta, etc. quacks? How long do you remember?

If you insist that you do as long as desired, you are a superman, or has written only very simple throwaway code.

The dark reality is that usually, even the mad programmer does not remember how exactly a duckelatta whatever-ks or even what duckelatta is.


2: Not Every Entity That Quacks Like a Duck Is Not a Duck, Actually


Hypothesizer 7
As "it quacks like a duck", "it must be a duck."?

Too bad! It is an MP3 player.

But any MP3 player does not walk like a duck? But the MP3 player is mounted on a pair of mechanical legs that walks like a duck.

So, the conjecture is not really warranted.


3: What Is Duckelatta, Really?


Hypothesizer 7
In any statically-typed programming language, any duckelatta is an object that has implemented the 'Duckelatta' interface (or class, but I will assume it to be an interface, hereafter), and if a function argument is typed as 'Duckelatta', any object that has been passed into the function argument is definitely a duckelatta.

In "Duck Typing", a duckelatta is not an object that has implemented the 'Duckelatta' interface (in fact, there may not be such an interface): that is the point of "Duck Typing".

So, what is duckelatta in "Duck Typing"?

The definition of duckelatta is only inside the mad programmer's head (supposing that it has not been documented), or it was there, usually, because the mad programmer does not remember it any more.

Can it not be figured out from the code? . . . No, generally speaking, because there can be multiple interpretations.

For example, when a duckelatta object is being passed into some multiple functions, is the definition of duckelatta "an object that can be successfully passed into the functions"?

Not necessarily, as the duckelatta object may be also a maletta object (why not?), it may be able to be passed into some of the functions only because the object is a maletta object. The criterion for an object to be a duckelatta may be that it can be successfully passed into a single one of the functions, but which one?

In the 1st place, of course, whether the object is a duckelatta object or not is only inside the mad programmer's head.

As such information is not written in the code, the definition of duckelatta cannot be inferred from the code.

The inference is impossible not only by me, but also by the Python interpreter.

In fact, sometimes, even whether there ever existed a consistent definition in the mad programmer's head is questionable.

So, is that OK? I cannot know what duckelatta is, not to mention whether an object is a duckelatta or not!

Well, let me reveal the real intention of "Duck Typing": "What the heck whether it is a duck or not! If the program works, it should be fine!"


4: "Duck Typing" Is Not Particularly About Behavior


Hypothesizer 7
Some people say that "Duck Typing" is about behavior, instead of interface, but that is not true, actually.

Also in "Duck Typing" as in any statically-typed programming language, whether an object is passable as a duckelatta or not is only whether it has some methods or not; what exactly the methods behave does not matter. And whether it has some methods or not is exactly about interface.

The difference of "Duck Typing" from static-typing is just that interfaces are not explicitly specified in the code, but are only implicitly imagined in the mad programmer's head.


5: A Herculean Task of Knowing What a Function Argument Accepts


Hypothesizer 7
"Duck Typing" does not really care what duck is, but I have to know what I can pass into a function argument, nevertheless.

In any statically-typed programming language, the information is represented by the argument type, mostly. Certainly, it may not be entirely (the argument may not accept the whole data area of the type), but if you think that the fact can damn static typing, you should see a subsequent argument.

In "Duck Typing", the effort starts with "what, the hell, is this argument"?

I have to analyze the whole implementation of the function, right?

But if you think that the function suffices, you are way too optimistic.

Let me see a Python function.

@Python Source Code
def functionA (a_duck, a_destination, a_key, a_music):
	~
	functionB (a_duck.walks (a_destination))
	~
	l_duck = a_duck
	~
	functionC (l_duck.quacks (a_key))
	~
	l_mallard = functionD (l_duck)
	~
	return l_mallard.dances (a_music)

While I have to pass a duck into 'functionA', what, the hell, is 'duck', indeed?

Well, searching 'a_duck' in 'functionA', the duck seems to have to have a 'walks' method with 1 argument, although I do not know what "a_destination" is meant to be (is it a string like "The Sam's SlaughterHouse", a place code like '132', or a 'Destination' class instance?). . . . Obviously, I have to look into the 'walks' method and see how "a_destination" is used. However, which 'walks'? . . . I mean, there may be many classes each of which has a 'walks' method with 1 argument. . . . In fact, I cannot determine which, because all of them are candidates at this stage of investigation. So, I cannot help but list all the candidate classes for further profiling . . .

Next, I have to know what the return type of 'walks' has to be. . . . As the return value is passed into 'functionB', obviously, I have to look into 'functionB' and see how it is used. . . . Wait, 'functionB' is passing it into another function, which is passing it into another function, and so on. . . . Do I have to see all these functions through? . . . Of course! How else can it be! . . . Only after seeing all these functions through, I can rule out some of the candidates that are not compatible with the required return type, having some yet multiple candidates. . . .

Now what? Of course, I cannot see only 'a_duck', but also 'l_duck', because 'l_duck' refers to the same duck object obviously. . . . The duck has to have a 'quacks' method with 1 argument, which I do not know what. . . . Of course, I know what I have to do: look into the multiple 'quacks' methods. Then, of course, I have to look into the 'functionC' method, which passes the return value into another method, and so on. . . . Cheer up, me! I can do it!

Now what? The 'functionD' method, right? Chin up, me! This should be the last stretch! . . . Wait, I have to go through the 'functionD' method as I have done through the 'functionA', again, actually . . .

. . . Well, is that all? No, in fact, 'functionD' has really returned the duck, meaning that 'l_mallard' refers to the 'a_duck' object. . . . So, it is not really so simple as to just search for 'a_duck' and the obvious equivalents as 'l_duck', as a lesson. . . . Anyway, the duck has to have also a 'dances' method with 1 argument, which I do not know what. . . . Of course, I have to look into the multiple 'dances' methods . . .

And I have to know what the return type of 'dances' has to be, of course. . . . This time, I seem to have to search for all the callers of 'functionA' and see how the return values of 'functionA' are used. . . . The return values are, actually, passed into some functions, which pass them into some other functions, and so on. . . . Do not lose heart, me! I am strong! I will not give up!

That . . . is . . . "Duck Typing".

In "Duck Typing", in order to know what a function argument accepts, you have to see possibly the whole code through, unless, of course, you know it already.


6: A Deadly Setback: the Function Cannot Be Safely Modified Singly!


Hypothesizer 7
In my understanding, the greatest merit of function is that the function can be safely modified singly, as long as the signature is preserved: the callers of the function will not be broken by the modifications.

That enables the strategy of 'divide and conquer', which is indispensable as the code becomes complex.

Not any more in "Duck Typing".

In "Duck Typing", as what the function argument accepts is determined by not only the function implementation but also possibly the whole code, a modification not only inside the function but also somewhere in the whole code can break a caller of the function.

If you are the mad programmer and remember all the details of the whole code, you will know what you can do with each function, but that is, usually, possible only if the program is very simple and has been written very recently.


7: On Some Advocacy of "Duck Typing"


Hypothesizer 7
As I see some advocacy of "Duck Typing", I will comment on it.

I have to say, the existing claims of the advocacy as far as I find sound far-fetched, and better explanations are due, if you really mean them.


7-1: "Specifying the Variable Type Doesn't Really Prevent Invalid Values"?


Hypothesizer 7
A claim seems to be "Specifying the variable type doesn't really prevent invalid values' being set into the variable: any millimeter value can be set into any intended-to-be-meter integer variable, for example. So, 'static typing' is meaningless!".

Well, one of the most popular and most harmful line of argument is 'all or nothing': for example, "As there can't be such thing as perfect fairness, this egregious unfairness shouldn't matter!".

You know, almost everything contrived by the mortals is not perfect, and if it is meaningless because it is not perfect, almost every ill of the world will be left flourishing.

What are desired of humans is to make it better, incessantly.

In this case, preventing non-integer values' being set into the integer variable is much better than preventing nothing.

I do not say that typing the variable makes it perfect, but say that typing the variable is far much better than "What, the hell, is this variable?".


7-2: "I Can Just Add Necessary Comments"?


Hypothesizer 7
A claim seems to be "I can just add necessary comments!".

Well, you may be able to, but will you really?

Probably, you are talking about adding some skimpy annotations here and there, but that is not what I call "necessary comments".

For example, when a function argument is a duckelatta, how exactly is the implicit interface like, which is what I call "necessary comment". . . . But writing it down really sufficiently will be no less tedious than writing the duckelatta interface explicitly as code, and I do not understand why someone will want to write it as a comment, instead of code, which will be much more useful, because the compiler can use it in order to check the consistency of the code.

And if you are serious, you will understand how it is hard to maintain the comments to accord to the code.

Sorry, but I have to guess that the reason why someone prefers "Duck Typing" is that he or she does not really have any intention of adding "necessary comments", however he or she insists that he or she can.


7-3: "I Can Just Do Necessary Tests"?


Hypothesizer 7
A claim seems to be "I can just do necessary tests!" or "As I have to do the tests anyway, there is no difference!".

Well, the problem is that "Duck Typing" enlarges the area of "necessary tests", much.

What would have been just automatically checked by the compiler in any statically-typed programming language are part of "necessary tests" in "Duck Typing".

In any statically-typed programming language, I can start testing at the point that there is some level of consistency in the whole code (at least, there is no type discrepancy), but in "Duck Typing", you start testing at the point "I'm not sure how helter-skelter this is . . . ". Certainly, there is much "difference".

In "Duck Typing", you are like "I don't know whether this argument accepts this type of datum, so, I dare try passing this. . . . Oh, the test shows that it does not take this! . . . Then, how about this one? . . . No, the test shows that also this is rejected! . . . ", which is unnecessary in any statically-typed programming language.

There are some people who make a false accusation that "Statically-typed programming language programmers think that compiling is the enough test", that accusation is simply against the fact; we do tests, of course, but deem testing what the compiler would have automatically checked is unwise.

And honestly, I do not particularly believe that Python programmers really do "necessary tests", because it does not match their psychobiography as I understand: they are lazy people who shun writing as useful things as datum types, and suddenly turn so diligent to write thorough test code? . . . I guess that some of them will, but not most of them.


7-5: "It Is Pleasant"?


Hypothesizer 7
A claim seems to be "It is pleasant! Nobody can deny that it is pleasant, at least for me!".

Well, I cannot deny it, certainly, but being pleasant does not necessarily mean being healthy.

I have to say that it is pleasant for you as an unhealthy snack is pleasant for you.

I understand why it is pleasant for you: being exonerated from writing the matter-of-course tedious things.

However, they are matter-of-course only for you and only at the moments the memories are vivid in your head.

If the code becomes complex or time passes, you will not remember those matter-of-course things, without their being recorded in the code, or anywhere usually.

So, the enigmatic code is left behind, and you have to sweat afterwards, because you have eaten the unhealthy snack.

That is the foreseeable future of enjoying the fleeting pleasantness.

Someone may say "I will certainly work out afterwards! So, what's the problem with eating this snack?!"

The dirk secret is that someone who is self-restrained enough to be able to work out, is usually self-restrained enough to have been able to resist the snack in the first place.


7-6: A Strong Tendency of the Python Community


Hypothesizer 7
A strong tendency of the Python community I find is rationalization.

Of course, almost every community or person has the vice more or less, but I cannot help but feel that it is rather strong in the Python community.

"Duck Typing" is a good thing? . . . Disgusting, I say.

I am not saying that Python is inferior as a whole, but just am saying it has its demerits as any other programming language has its own.

As the Python community rationalize "Duck Typing" as a good thing, I have to specifically denounce such rationalization.


8: After All, "Duck Typing" Is Only For One-Man Simple Throwaway Code


Hypothesizer 7
Is it not all right, if the code is one-man, simple, and throwaway?

Well, I guess it is OK, although I myself do not write any code as a throwaway, because I always expect that the code may be improved or reused somehow in future.

But if the code is one-man, simple, and throwaway, "Duck Typing" is efficient, without requiring you to write matter-of-course tedious things, is it not?

I guess so.


9: Or . . .


Hypothesizer 7
In fact, Python allows static types checking now, which is a game changer.

There is no more need to defend Python for lacking static types checking; now, it is about you, whether you are just too incontinent to resist immediate pleasure that entails future liabilities, or you do static types checking.

Let me see how I can do static types checking in Python in the next article.


References


<The previous article in this series | The table of contents of this series | The next article in this series>