danluu, (edited )
@danluu@mastodon.social avatar

I can't quite put my finger on it, but there's something delightful about this list of "legitimate" uses of negative literals:

https://github.com/elm/compiler/issues/1773.

I think part of it is the circumstances that would compel users to construct such a list. Until that thread, it hadn't even occurred to me that someone would present a case against the existence of negative literals that required a rebuttal.

callionica,
@callionica@mastodon.social avatar

@danluu I saw this issue was 6 years old, so assumed that it was a temporary curiosity. But the issue is still open!?!?

pervognsen,
@pervognsen@mastodon.social avatar

@danluu Most languages don't have negative literals and users never even notice or care. What do they have is negation, which happens to work with number literals. And in languages with a semantic distinction between constant and non-constant expressions (including C), the negation of a constant is a constant, so -42 is a constant since 42 is a constant. One of the rare cases where the difference does manifest is in pattern matching, exactly as in the linked issue.

pervognsen, (edited )
@pervognsen@mastodon.social avatar

@danluu Rust doesn't have a concept of negative integer literals either. And it has pattern matching. So it actually added an ad-hoc special case in the pattern syntax so you can put - in front of a literal in patterns. But the - still isn't part of the literal. It's a good compromise to avoid user surprise, IMO, since in every non-language-nerd's mental model the literal is negative.

danluu,
@danluu@mastodon.social avatar

@pervognsen That seems preferable to the fix for the linked issue, which was to add an error message which reads "It is not possible to pattern match on negative numbers at this time. Try using an if expression for that sort of thing for now.": https://github.com/elm/compiler/commit/0e669b8ad076f64e450f2fa9b29ce93791466667.

I never looked into how this is handled in Scala, but I don't recall ever having run into this issue when pattern matching in Scala either.

soulthreads,
@soulthreads@mastodon.gamedev.place avatar

@danluu @pervognsen Oh man, it's always so funny (and frustrating) when the compiler screams at you instead of doing the actual thing you want the program to do.
Like, you already wrote the logic to handle this case, why not turn into something useful instead of making it an error?

E.g. I'm having a lot of mixed feelings about Zig, which recently made it an error if you declare a variable and don't change its value later — you are supposed to mark it as const instead. Just, why?

NohatCoder,
@NohatCoder@mastodon.gamedev.place avatar

@soulthreads @danluu @pervognsen What really gets me about this is that something not being declared const is such a non-event in the first place. If that is the worst sin one can find in a codebase then everything else must be top notch.

zeux,
@zeux@mastodon.gamedev.place avatar

@NohatCoder @soulthreads @danluu @pervognsen My (hot?) take is that two different ways to declare a const / mutable variable (Rust, Zig, TypeScript, Scala) or insistence on adding const to all locals (modern C++) is simply counterproductive and doesn’t improve code much. Local mutability is just fine actually.

pervognsen,
@pervognsen@mastodon.social avatar

@zeux @NohatCoder @soulthreads @danluu FWIW I think even some of the main people on the Rust lang team agree or at least Niko has alluded to it in a forward-looking keynote. It will probably get removed eventually in an edition. Of course &mut is a completely different thing (a unique reference) from declaring a variable that you own as mut, which I agree is pretty useless (and I feel the same thing about local const in C++).

floooh,
@floooh@mastodon.gamedev.place avatar

@zeux @NohatCoder @soulthreads @danluu @pervognsen an important difference between TS and Zig const is that in TS a const just prevents re-assigning (e.g. the 'interior' is mutable), while Zig disallows modifiying a const item alltogether (same as C basically).

floooh,
@floooh@mastodon.gamedev.place avatar

@zeux @NohatCoder @soulthreads @danluu @pervognsen ...I'm strictly in the "almost always const" camp though, especially in languages with "proper" compile time consts. I want the compiler to yell at me if I accidentially modify a const object (that's also why I dislike TS/JS's "mutable const").

soulthreads,
@soulthreads@mastodon.gamedev.place avatar

@floooh @zeux @NohatCoder @danluu @pervognsen yeah, being almost-always-const is fine, but not when the compiler forces you to do it for no reason.
I can only imagine how fun it is going to be to try to debug/iterate on something, and now you have to change var/const in an unrelated place all the time.
Having it as a warning would've been much better.

floooh,
@floooh@mastodon.gamedev.place avatar

@soulthreads @zeux @NohatCoder @danluu @pervognsen TBF at work we use linter rules for TS which essentially do the same thing as Zig (unused variables are errors, and 'prefer-const' as error), and these are part of the quite popular airbnb-base eslint ruleset (if I'm not mistaken). It's not as bad in practice as it sounds at first. Initially it's annoying for sure, but I don't notice a productivity hit compared to my C coding.

saagar,

@pervognsen @danluu Another case is of course when using twos complement and trying to represent INT_MIN

pervognsen,
@pervognsen@mastodon.social avatar

@saagar @danluu Oh yeah, how could I forget. That one almost feels like a practical joke the first time you run into it.

rygorous,
@rygorous@mastodon.gamedev.place avatar

@pervognsen @danluu It doesn't really work well to define it that way on two's complement targets though.

E.g. the canonical way to #define INT_MIN on 32-bit C targets is (-0x7fffffff - 1) or similar. You can't write (-0x80000000) since the 0x80000000 is too large for int32 so it forces the constant to be unsigned, and then you end up with the wrong type.

rygorous,
@rygorous@mastodon.gamedev.place avatar

@pervognsen @danluu Subtle caveats like this make me think that, even if it seems less elegant, it might be a good idea to make literal negation have actual productions in the grammar to avoid potholes like these.

pervognsen,
@pervognsen@mastodon.social avatar

@rygorous @danluu Another option that seems to have become more popular is to treat literals as mathematical (i.e. arbitrary-precision) integers and then deal with overflows only at the point of conversion to a specific fixed-width type.

pervognsen,
@pervognsen@mastodon.social avatar

@rygorous @danluu I believe Go's literals and their associated integer type is "only" guaranteed to be 256-bit precision but at least that's enough to fix the usual suite of issues involving u64/i64 or even u128/i128.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • DreamBathrooms
  • ngwrru68w68
  • modclub
  • magazineikmin
  • thenastyranch
  • rosin
  • khanakhh
  • InstantRegret
  • Youngstown
  • slotface
  • Durango
  • kavyap
  • mdbf
  • GTA5RPClips
  • JUstTest
  • tacticalgear
  • normalnudes
  • tester
  • osvaldo12
  • everett
  • cubers
  • ethstaker
  • anitta
  • provamag3
  • Leos
  • cisconetworking
  • megavids
  • lostlight
  • All magazines