What's the best way to minimize the need of run time checks?

Steve D'Aprano steve+python at pearwood.info
Sun Aug 28 00:30:36 EDT 2016


On Sun, 28 Aug 2016 12:31 pm, Juan Pablo Romero Méndez wrote:

> 2016-08-14 7:29 GMT-07:00 Steven D'Aprano <steve+python at pearwood.info>:
> 
>> On Thu, 11 Aug 2016 06:33 am, Juan Pablo Romero Méndez wrote:
>>
>> > I've been trying to find (without success so far) an example of a
>> > situation where the dynamic features of a language like Python provides
>> > a clear advantage over languages with more than one type.
>>
>> Python has more than one type. Don't confuse dynamic typing with weak
>> typing or untyped (typeless) languages. More on this below.
>>
> 
> 
> Sorry I was not clear, I was thinking in something along these lines:
> 
>
https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are-static-languages/
> 
> (Warning: his pov is very different from yours)

It is a great example of somebody suffering from the problem that when the
only tool he has is a hammer, everything looks like an nail.

He clearly is immersed in the world of formal type systems and understands
their power. But now he sees everything from that single perspective.

Now it is true that speaking in full generality, classes and types refer to
different things. Or to be perhaps more accurate, *subclassing* and
*subtyping* are different things:

http://c2.com/cgi/wiki?SubTypingAndSubClassing

Many languages treat them the same, but fundamentally they are different.

(Note: for veteran Python programmers who remember the language before types
and classes where unified in version 2.2, this is not the same thing! Prior
to 2.2, both "types" and "classes" related to *subclassing*, albeit in a
negative way for the built-in types: they couldn't be subclassed.)

But the author of this piece ignores that standard distinction and invents
his own non-standard one: to him, classes are merely different
representations of the same data. E.g. his example of complex numbers,
shown as Cartesian (x, y) values or polar (r, θ) values. These aren't two
different "kinds of things", but merely two different ways of representing
the same entity.

That's not a good way to think about (say) Python lists and Python bools.
Lists and bools are in no way the same kind of entity (except in the most
general category of "they're both objects").

It's not even a very good way of thinking about complex numbers.

Viewed from his perspective of type systems, the author makes what I call
the food processor error. Food processors, blenders and other similar
kitchen appliances are often advertised as having "five speeds", or ten
speeds, or however many the machine is capable of, usually labelled
as "chop", "dice", "whip", "puree", etc. And, far too often: "OFF".

Since when is "off" a speed? If a blender that is turned off counts as a
blending speed, then a simple bowl is a "one speed blender". You put food
in the bowl, and it doesn't blend at all. That counts as "off" speed.

The author is making the same mistake. He thinks that a language which lacks
static typing counts as static typing. "Off" is a speed! "Bald" is a hair
colour! "Raw" is a way of cooking food!

In truth though, static and dynamic typing are very different. The author is
fooled because you can emulate *one* part of dynamic typing in a statically
typed system by adding one extra type, "Any", or "Duck Type", or whatever
you want to call it. The static checker can then ignore anything declared
as Any type.

But deferring type checks to runtime is only part of dynamic typing. The
other fundamental difference is:

- statically typed languages associate types to variables;
- dynamically typed languages associate types to values.

This difference is more significant than the "run-time/compile-time" and its
one which often confuses people. That's not surprising: if I say "x is an
int", that's ambiguous whether I'm referring to the variable x or the value
currently assigned to x. If you don't see the ambiguity, then you're seeing
it purely from the perspective of either static or dynamic typing.

In static typing, I somehow associate the name "x" with a tag that
says "this may only be used with ints". Perhaps I have to declare it first,
like in C or Pascal, or perhaps the compiler can infer the type, like in
Haskell, but either way, "x" is now forever tagged as an int, so that the
compiler can flag errors like:

x = 1
# ... code can run here
x.upper()

The compiler knows that ints don't have a method "upper" and can flag this
as an error. In such static languages, it is invariably an error to try to
change the type of the variable (unless it has been tagged as "Anything"
or "Duck Typed").

x = 1
x = "hello"  # a type error, at compile time


But in dynamic typing, the type information isn't associated with the
name "x", but with the value 1 currently assigned to it. Change the
assignment, and the type changes. As a consequence, it is necessary to move
the type checks from compile time to runtime, but that's not the
fundamental difference between the two.

As further evidence that the author has missed the forest for all the trees,
consider languages which actually do have only a single type:

- in assembly language, everything is just bytes or words;

- in Forth, similarly, everything is just a 16-bit or 32-bit word;

- in Hypertalk, every value is stored internally as a string;

to say nothing of more esoteric languages like Oook, Whitespace and
BrainF*ck.


TL;DR: 

The author of that blog post ignores actual untyped languages, misses the
distinction between type information being associated with variables or
values, and invents his own idiosyncratic distinction between types and
classes while ignoring the standard one.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list