
Steven D'Aprano writes:
I agree that treating weak/strong as a binary state is an over-simplification, but a weak/strong axis is perfectly reasonable. Count the number of possible mixed-type operations permitted by the language (for simplicity, limit it to built-in or fundamental types). What percentage of them succeed without explicit casts or conversions? If that percentage is 0%, then the language is entirely strong. If it is 100%, then the language is entirely weak. In practice, languages will likely fall somewhere in the middle rather at the ends. This is an objective test for degree of type strength.
Sure, but I think Masklinn's point here is that it's a partial order. I might very well consider a language with a D'Aprano index of 10% more strongly typed than one with an index of 5% (eg, if the 10% are all numeric coercions based on embeddings, while the 5% is various combinations). That said, I think Masklinn is being unreasonable. Although there surely are more folks like him who refuse to accept any notion of "strength of typing", I think most people would be in rough agreement as to which direction the axis points.
Automatically converting ints to floats is mathematically reasonable, because we consider e.g. 3 and 3.0 to be the same number.
I don't think we do consider them to be the *same*; substitutability is one-way. Yes, 3 can be used in place of 3.0 because the integers can be embedded in the reals, but in general not vice versa. We prefer counters (eg in loops) to *not* automatically convert floats to ints. Supplying a float where an int is expected is generally a logic error, not a notational convenience. This notational convenience is very great, however. It's not just a matter of eliding the ".0" from "3.0"; it's also used in contexts like # enumerate the labels on the y-axis y-labels = list(0.50 + 0.05*i for i in range(10)) and in the cake-division problem below. (A hairy mathematician would point out that this can be justified as a notation for repeated addition rather than coercion to float for multiplication, but I'm too bald to bother, besides being an economist anyway.) Note that you cannot write "list(range(0.5,1.0,0.05))" to compute y-labels, though that spelling seems very plausible to me. I would argue that a language that coerces integer to float (or the singleton 'nil' to list, to give another common example) is only slightly more weakly typed than one that doesn't, because of the embedding. But one that coerces float to integer is much more weakly typed than one that doesn't, because there is no embedding.
Do we? Given 3/2 and 3.0/2 don't necessarily give the same answer (some languages don't even consider the first operation valid), I'm not sure we do.
Ask a mathematician, and he'll say that they are the same. The underlying concept of number treats 3 and 3.0 as the same thing (until you get to some extremely hairy mathematics,
No, even naive non-mathematicians may tell you they're different. If you ask any reasonably competent (but non-programmer) sixth grader, they will tell you that 3/2 is "1 with a remainder of 1" (and we have to play scissor-paper-stone to decide who gets the last piece of hard candy), while 3.0/2 is "1.5" (and we split the third piece of cake in half with a fork).