Are the critiques in "All the things I hate about Python" valid?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Feb 20 07:24:39 EST 2018


On Tue, 20 Feb 2018 12:18:47 +0100, Antoon Pardon wrote:

> On 19-02-18 15:25, Steven D'Aprano wrote:
>>
>>> Ones like C++ has already tied itself itself up in knots just doing
>>> the basics; I'm not sure how it would handle even my 1,3,5,7,9 type.
>>>
>>> But Python has classes and can do some of this stuff; how would it
>>> handle a numeric type that is constrained to be whole numbers within
>>> 0..9 inclusive?
>> This becomes easy at run-time:
>>
>> class Digit(int):
>>     def __new__(cls, arg):
>>         instance = super().__new__(cls, arg)
>>         if not 0 <= instance <= 9:
>>             raise ValueError('argument is out of range')
>>         return instance
>>
>> The above is obviously not a full-blown production-ready class. But it
>> illustrates the basic concept. This is the sort of thing that dynamic
>> languages excel at: enforcing constraints at run-time which are hard to
>> enforce at compile-time.
> 
> I don't see how dynamic languages are excelling here. Writing code that
> ensures a number of constraints can be done just as easily in a static
> language.

*Just* as easily? Really?

Can you tell us which languages can enforce at compile-time that integer 
N is a multiple of four but not a multiple of 100 unless it is also a 
multiple of 400? (The same constraint as leap years.)

What type declaration would you write for that?

Its easy to make overblown claims about how great static typing is, but 
people didn't invent dynamically typed languages because they wanted to 
program in a worse language. They did it because dynamic typing allows us 
to do things which are hard, or impossible, in statically typed languages.


> Personnally I would prefer the type system of Pascal and Modula2 with
> their interval type
> above a Digit class in python. For the simple reason that once you had
> declared a variable
> like this:
>     x: 1 .. 10;


I agree that Pascal-style interval types are nice, but they're also 
limited to intervals, and *integer* intervals at that. Pascal doesn't 
support floating point ranges, such as "x is a Real between 0 and 1".

How would you write a type declaration for numbers like these:

    4, 6, 8, 24, 26, 48, 50, 124, 126, 342, 344, ... 3909821048582988050

in the language of your choice?

Yes, there is a pattern: one less than, and one more than, powers of 5 
and 7, up to a maximum of 2**64.

That is, 5±1, 25±1, 125±1, ... 7±1, 49±1, 343±1, ...

Its one thing to say that a type system could enforce this at compile-
time. Its another to demonstrate an existing type system which actually 
does.


> Each assignment to x would then implicitly do something like an assert
> to checks the constraint,
> so it would be impossible to ever assign 11 to x, without an error being
> thrown.

As I remember it, Pascal range checking is just dynamic typing in 
disguise. Statically, x is just an integer, with no interval checking 
performed at compile-time except for assignment by literals. Everything 
else is run-time range checking.

By which I mean, the compiler would complain if you tried:

var
  x: 1 .. 10;
begin
  x := 11;
end;

but it would allow this:

var
  a, b: integer;
  x: 1 .. 10;
begin
  a := 10;
  b := 1;
  x := a + b;
end;

However, the second would generate a runtime range check error and halt 
the program.

That at least is how the Lightspeed Pascal (later Think Pascal) compiler 
on the Apple Mac operated, and as far as I know all other Pascal 
compilers worked the same.

Now that was over 30 years ago, and I daresay that type checkers these 
days are more sophisticated and powerful than Pascal's pretty simple 
checker. But still, there's only so much you can do at compile-time.


> There is no such possibility in Python. You can off course start with x
> = Digit(5), but the language
> won't stop you from doing x = 11 later.


Of course you're right that Python won't stop you assigning (say) a float 
to x. On the other hand, Pascal and C won't allow you to assign a string 
to something which previously was an integer. The need to create new 
labels for things just to placate the compiler is one of the more 
annoying things about static typing. Yes, x was a number, now its a 
string. If *I* can keep track of that, why can't the compiler?


> I'm not proficient with C++, but IIUC, you could make a class in C++ and
> have the constructor and
> copy operator check for these kind of things. True it would be run-time
> checks but that would
> already be more than Python can give.

Sure. Its a different approach, and not without its merits.



-- 
Steve




More information about the Python-list mailing list