From: cross@spitfire.i.gajendra.net   
      
   In article <108dlgm$2fi6h$3@dont-email.me>,   
   Arne Vajhøj wrote:   
   >On 8/20/2025 11:51 AM, Dan Cross wrote:   
   >> In article <1084drl$afbj$1@dont-email.me>,   
   >> Simon Clubley wrote:   
   >>> On 2025-08-19, Dan Cross wrote:   
   >>>> In article <68a493ec$0$710$14726298@news.sunsite.dk>,   
   >>>> Arne Vajhøj wrote:   
   >>>>>   
   >>>>> Kotlin is rather picky about mixing signed and unsigned.   
   >>>>>   
   >>>>> var v: UInt = 16u   
   >>>>>   
   >>>>> v = v / 2   
   >>>>>   
   >>>>> gives an error.   
   >>>>>   
   >>>>> v = v / 2u   
   >>>>> v = v / 2.toUInt()   
   >>>>>   
   >>>>> works.   
   >>>>>   
   >>>>> I consider that rather picky.   
   >>>   
   >>> I've not used Kotlin, but I consider that to be the really good type   
   >>> of picky. :-)   
   >>>   
   >>>> It's kind of annoying that it can't infer to use unsigned for   
   >>>> the '2' in the first example. Rust, for example, does do that   
   >>>> inference which makes most arithmetic very natural.   
   >>>   
   >>> I actually consider that to be a good thing. The programmer is forced   
   >>> to think about what they have written and to change it to make those   
   >>> intentions explicit in the code. I like this.   
   >>   
   >> I think the point is, that in cases like this, the compiler   
   >> enforces the explicit typing anyway: if the program compiles, it   
   >> is well-typed. If it does not, then it is not. In that   
   >> context, this level of explicitness adds little, if any,   
   >> additional value.   
   >>   
   >> That the literal "2" is a different type than "2u" is   
   >> interesting, however, and goes back to what you were saying   
   >> earlier about default signedness. As a mathematical object,   
   >> "2" is just a positive integer, but programming languages are   
   >> not _really_ a mathematical notation, so the need to be explicit   
   >> here makes sense from that perspective, I guess.   
   >>   
   >> In Rust, I might write this sequence as:   
   >>   
   >> let mut v = 16u32;   
   >> v = v / 2;   
   >>   
   >> And the type inference mechanism would deduce that 2 should be   
   >> treated as a `u32`. But I could just as easily write,   
   >>   
   >> let mut v = 16u32;   
   >> v = v / 2u32;   
   >>   
   >> Which explicitly calls out that 2 as a `u32`.   
   >>   
   >> Is this really better, though? This is where I'd argue that   
   >> matters of idiom come into play: this is not idiomatic usage in   
   >> the language, and so it is probably not better, and maybe worse.   
   >   
   >The practical difference for specific code is likely zero.   
   >   
   >But there is a difference in language principles and the   
   >confidence the developer can have in it.   
   >   
   >A rule that there is never any implicit conversion or   
   >literal inference no matter the context is simple to   
   >understand and gives confidence.   
      
   That conflates two separate things, and actually making two, not   
   one, rules.   
      
   Implicit type conversion is subtle, with often-confusing rules,   
   and programmers frequently mess it up; I agree. Even   
   programmers who feel very confident in the rules are not immune   
   here.   
      
   However, type inference is an entirely different matter. The   
   specific context is Rust, and there is no matter of "confidence"   
   at play here; either the inference rules work, and the program   
   type checks, or they the inference engine in the compiler can't   
   deduce the appropriate types (or makes a mistake) and the   
   program does not type check and fails to compile.   
      
   And that's the critical part: the program is either properly   
   typed or it is not; unlike weakly typed languages, there is no   
   middle ground. And if it is not properly typed, it will not   
   compile; period, end of story.   
      
   So if the program compiles, then that's all the "confidence" the   
   programmer needs; there's no need to decorate every literal with   
   an explicit type annotation, which is just noisy and clutters up   
   the program with extraneous detail.   
      
   >Exceptions even in cases where it does not matter adds   
   >the complexity of understanding when the exceptions apply   
   >and why they do not matter. Complexity that developers   
   >would rather avoid.   
      
   There are no exceptions. The program is either well-typed, in   
   which case (barring any other errors) the program compiles. Or   
   it is not, and the program fails to compile: again, there is no   
   middle ground.   
      
   Most experienced Rust programmers who saw a bunch of explicit   
   type annotations on literals, when the type system could   
   otherwise easily infer them, would find rightly find that   
   non-idiomatic, and thus confusing, and wonder what was so   
   special about the program that literals had to be so annotated.   
      
   _That_ adds complexity where there need not be any, and thus   
   increases cognitive load, which is never a desirable property   
   for a maintainable program.   
      
   This is why matters of idiom in a language are important.   
      
    - Dan C.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|