5 ms·
Same reason we don't have to type `(((2int + 2int)int) / 8int)int`. Type inference already exists in any ALGOL-like. Modern languages just tend to remove the ar
by cobbal 3y ago
Same reason we don't have to type `(((2int + 2int)int) / 8int)int`. Type inference already exists in any ALGOL-like. Modern languages just tend to remove the arbitrary restriction that variables are the places where types must be added.
- Joker_vD 3y agoWell, technically int(int(int(2) +::<int> int(2)) /::<int> int(8)) We must disambiguate integer- and float-point arithmetic operators for sure.
- dragonwriter 3y ago> Same reason we don't have to type `(((2int + 2int)int) / 8int)int`. Type inference already exists in any ALGOL-like. That's not why you don't have to do that. Many (most statically typed?) Algol-likes have strict types for literals (e.g., 2 is always a signed int, if you if you want specifically unsigned you might say 2u and if you want a double you say 2.0, and if you want a single-precision float you say 2.0f, or something) and strict rules at how math between them works and what types it produces, this has been true since long before tyoe inference became common, and is why you don't have to say 2int+2int — 2 is syntactically defined as int. There is no inference
- goto11 3y agoIt is still type inference though. If 2 is an int, the compiler perform type inference to figure out that the expression 2 + 2 is also an int. It is just that traditional languages only use type inference for expressions, not declarations.
- dllthomas 3y agoIt's type propagation. Which can be seen as a form of inference or not, depending just where you draw the line.
- gpderetta 3y agoSo is auto, decltype and templates. In C++ we properly call it type deduction to distinguish it from actual H-M style inference which C++ lacks. The details of how it is called doesn't detract from parent's argument.
- dllthomas 3y agoYes. I hadn't meant my comment as argument on either side, just added context.
- gpderetta 3y agoWhat's the type of the binary + operator in C?
- trealira 3y agoIn C, there's no type inference. Integer literals have the type "int" by default, and they need a suffix to be unsigned or long. They get truncated and promoted implicitly for convenience's sake. /* 'a' : int * 'a' is truncated to char (self-evidently safe here( */ char c = 'a'; /* 1 : int * c : char * c is promoted to int * 1 + c : int * 1 + c is truncated to char */ char d = c + 1; /* d : char * c : char * d and c are promoted to int * d - c : int * d - c is truncated to char */ char e = d - c; If you want to avoid this behavior, you have to use the type suffixes explicitly, pretty much like that "(((2int + 2int)int) / 8int)int" expression you're making fun of. // Zero. 32-bit integer left shifted by 32 bits is always 0. 1 << 32; // 2^32. "U" makes it unsigned. // "LL" makes it "long long", 64-bits on Windows and Linux. 1ULL << 32; // -2147483648 (signed 32-bit) // i.e. 0x10000000 1 << 31; // 2147483648 (unsigned 32-bit) // i.e. 0x10000000 1U << 31; I don't think this is a good thing. It's very confusing. I prefer the type inference approach, e.g. in Rust, where they're i32 if the type cannot be inferred and the literal has no type suffix. And I like that no two integers can be used by the same binary operator unless they have the same type, so you need to explicitly cast them to the right type.
- cobbal 3y agoThe integer literals might be misleading from the real point here, which is that every node in an expression tree in C has a type. The compiler infers most of these types. It infers that (1 / 2) is an int and that (1 / 2.0) is a double. That is type inference, and it's exactly the same as the sort of type inference that figures out what "auto" means in C++.
- trealira 3y ago> that (1 / 2.0) is a double. That is not type inference. 1 has the type int. 2.0 has the type double. Then, 1 gets converted to double. Then the whole expression has the type double. This isn't type inference; this is like saying JavaScript has type inference because it deduces that the expression ('4' - true) has the "number" type (i.e. double precision floating point). Compare with Haskell, where a numeric literal like 32 has the type (Num a) => a, i.e., it's polymorphic, and the type is actually inferred based on the context it's used in (it could be Int, Integer, Double, Rational, whatever). If you ask it the type at a REPL, it just tells you "32 :: Num a => a", whereas C would tell you that 32 has the type int (if there were a REPL for C).