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 -- https://mail.python.org/mailman/listinfo/python-list