4 ms·
If it is because of overflow, the idea was that there could be size classes at compile time. A bit like sub/supertyping but for numeric types. A simple type poi
by aatd86 1y ago
If it is because of overflow, the idea was that there could be size classes at compile time. A bit like sub/supertyping but for numeric types.
A simple type pointer check would be sufficient.
- kbolino 1y agoSize classes would save some space and speed up like-to-like comparisons, but wouldn't really do much for unlike comparisons (especially vs. float or complex). Looking only at type pointers fails to account for custom types (e.g., type Foo int); remember that an untyped integer constant can be compared with these. If you want the same semantics at runtime as you get at compile time, I don't see how you can get much simpler than what I wrote, in terms of the high-level logic. Though there are undoubtedly ways to optimize it, both because Go's compiler favors speed of compilation over efficiency of generated code, and because if this were the real code, it could poke at internals while my (probably working) example has to rely on the public reflect package, which is more abstract.
- aatd86 1y agoBut the LHS can determine how it compares to the RHS when the RHS is determined to be an untyped constant? Or instead of saying RHS (my mistake), let's say the typed side since comparisons are symmetric. A bit like having a special method attached to the type strictly for comparisons? That would be much less expensive than such a type switch if I am not mistaken. Would handle custom types as well. If promotable from the underlying type, that would not even bloat the executable. Unless I'm confused...
- kbolino 1y agoOk, I think I follow. Instead of putting the comparison logic on the untyped side, you'd put it on the typed side. In code, reusing imports and untypedInt declaration, but replacing the method from before, you'd have: type intType interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 } func equals[I intType](x I, y any) bool { switch val := y.(type) { case I: return x == val case untypedInt: return val.i.IsInt64() && val.i.Int64() == int64(x) default: return false } } And this would need a separate specialization for unsigned integers, floats, and complex numbers. This approach saves us from having to introspect the underlying type at runtime, but the example is incomplete. We also have float and complex untyped constants, so now each concrete type has to switch on all of the untyped constant forms it compares with. Still, it might be faster, though I'm not sure how much it reduces code bloat in practice (it's nice to not need the reflect package though). [edit: side note, I was trying to actually write out all the code that would be needed, and I discovered that you can't call real or imag on generic types: https://github.com/golang/go/issues/50937 https://github.com/golang/go/issues/50937]