digitalmars.dip.ideas - Deprecate `!a == b`
- Timon Gehr (8/8) Aug 13 A bug that crops up now and then in D is that someone negates `a == b`
- Guillaume Piolat (2/7) Aug 13 Yes please!
- Quirin Schroll (4/13) Aug 13 I’m quite sure this requires no DIP. Yes, this is a breaking
- Lance Bachmeier (6/15) Aug 13 This should be done. The current behavior isn't likely something
- IchorDev (10/19) Aug 13 Doesn’t require a DIP, but I’ve also never seen anyone think this
- IchorDev (9/11) Aug 13 To rephrase my point a little: this is emergent behaviour with an
- Nick Treleaven (6/15) Aug 13 I think it's actually that they don't know the operator
- IchorDev (11/26) Aug 13 My point being that it’s a weird mistake to make, and one I’ve
- Patrick Schluter (2/16) Aug 19 Comparing bools is an anti-pattern.
- Nick Treleaven (3/7) Aug 19 Yes, but doing that does not need to require brackets. Brackets
- Dennis (20/25) Aug 13 It's easy to have a lapse of focus. Last hour, I accidentally
- IchorDev (32/51) Aug 14 When you write the wrong thing, you get the wrong result. The
- Dennis (20/26) Aug 14 If you've never made such silly programming mistakes, enjoy it
- IchorDev (20/41) Aug 14 Thanks. I’m surprised my knackered brain still manages not to
- Dennis (8/14) Aug 14 Oh, I thought the list represented things you _didn't_ want to
- IchorDev (19/30) Aug 14 What? No, I literally said that the only thing in that list that
- Dennis (9/13) Aug 14 'removing integer promotion' and 'requiring a cast' (or other
- IchorDev (8/14) Aug 16 Removing integer promotion would not be equivalent to this
- Nick Treleaven (4/11) Aug 16 Adding brackets to disambiguate does not introduce bugs, it makes
- Quirin Schroll (24/56) Aug 28 IMO, not an example. “Integer promotion” to me means not implicit
- Quirin Schroll (11/15) Aug 28 I can’t link something, but I have definitely written something
- Lance Bachmeier (23/32) Aug 13 It would make sense to allow it for only bools. However, we can
- Timon Gehr (24/48) Aug 15 The main issue is this is a typo that indeed happens now and then, not
- IchorDev (21/59) Aug 16 Sorry, I really had just never heard of people actually having
- Timon Gehr (109/115) Aug 16 The following message was sent to a board of the D programming language
- Nick Treleaven (9/18) Aug 13 I was a bit surprised that someone would write that (other than
- Nicholas Wilson (5/14) Aug 13 In my defence, I was half asleep and recovering from a cold, but
- user1234 (4/13) Aug 14 Well, just wanna say that this is an easy check to implement in
- IchorDev (5/8) Aug 14 Sounds like a better idea to do that. I’m not a fan of having
- Timon Gehr (4/12) Aug 15 I can't say I ever wanted `a & b==c`.
- IchorDev (9/10) Aug 16 In my dreams:
- Timon Gehr (3/13) Aug 16 To some extent, but that's just what you get from C-inspired languages.
- Nick Treleaven (2/5) Aug 14 That would error on `!bool == bool`, which is fine.
- Jonathan M Davis (10/18) Aug 16 I don't think that I have ever seen anyone do something like !a == b wit...
- IchorDev (5/9) Aug 17 Problem is that a lot of C libraries use `alias LibSpecificBool =
A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).
Aug 13
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members.Yes please!
Aug 13
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).I’m quite sure this requires no DIP. Yes, this is a breaking change. The fix is to write `(!a) == b` and it’s unlikely that anyone has boatloads of `!a == b` in their code.
Aug 13
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).This should be done. The current behavior isn't likely something that's used very often (testing equality of two bools). Breaking code isn't a problem because !a == b would fail to compile, and it's trivial to fix. Other changes to the language have been more annoying while providing less benefit.
Aug 13
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).Doesn’t require a DIP, but I’ve also never seen anyone think this would work? Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`? Maybe that seems harsh, but I have never even thought of doing this because it’s just so obviously wrong—if I wrote it then I must have meant what I wrote, and I was probably happy with how it looked too. Having to wrap it in parenthesis would just negate that and add to my code’s parenthesis hell. P.S. this isn’t a bug; and `!` is ‘logical not’, not ‘negation’.
Aug 13
On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`?To rephrase my point a little: this is emergent behaviour with an obvious cause—a logical not always comes before a comparison. A problem I have actually had is not being able to parse the operation order for expressions like `1 + 2 * 3`, but I don’t think we should require parenthesis there either. Also, here’s a nice case where I’d actually want to write this: `!myInt == myBool` Again, here the parenthesis would just be visual noise.
Aug 13
On Tuesday, 13 August 2024 at 20:40:32 UTC, IchorDev wrote:On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:I think it's actually that they don't know the operator precedence, or they just made a mistake.Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`?A problem I have actually had is not being able to parse the operation order for expressions like `1 + 2 * 3`, but I don’t think we should require parenthesis there either.Agreed, because that syntax comes from maths rather than a subset of programming languages.Also, here’s a nice case where I’d actually want to write this: `!myInt == myBool` Again, here the parenthesis would just be visual noise.The diagnostic doesn't need to fire when both sides are bool.
Aug 13
On Tuesday, 13 August 2024 at 21:02:28 UTC, Nick Treleaven wrote:On Tuesday, 13 August 2024 at 20:40:32 UTC, IchorDev wrote:My point being that it’s a weird mistake to make, and one I’ve never seen. Have you ever seen it before?On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:I think it's actually that they don't know the operator precedence, or they just made a mistake.Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`?I learned programming to learn programming, not to learn mathematics. A lot of concepts from mathematics are completely incompatible with programming because we work with numbers that have to be physically stored. You can’t store irrational numbers, you can’t even store recursive fractions without a special encoding system, and even then there’ll still be a fraction that’s too long to store in the universe.A problem I have actually had is not being able to parse the operation order for expressions like `1 + 2 * 3`, but I don’t think we should require parenthesis there either.Agreed, because that syntax comes from maths rather than a subset of programming languages.Well there’s still situations like ternary enums to account for.Also, here’s a nice case where I’d actually want to write this: `!myInt == myBool` Again, here the parenthesis would just be visual noise.The diagnostic doesn't need to fire when both sides are bool.
Aug 13
On Tuesday, 13 August 2024 at 21:02:28 UTC, Nick Treleaven wrote:On Tuesday, 13 August 2024 at 20:40:32 UTC, IchorDev wrote:Comparing bools is an anti-pattern.On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:I think it's actually that they don't know the operator precedence, or they just made a mistake.[...]A problem I have actually had is not being able to parse the operation order for expressions like `1 + 2 * 3`, but I don’t think we should require parenthesis there either.Agreed, because that syntax comes from maths rather than a subset of programming languages.Also, here’s a nice case where I’d actually want to write this: `!myInt == myBool` Again, here the parenthesis would just be visual noise.The diagnostic doesn't need to fire when both sides are bool.
Aug 19
On Monday, 19 August 2024 at 12:23:13 UTC, Patrick Schluter wrote:On Tuesday, 13 August 2024 at 21:02:28 UTC, Nick Treleaven wrote:Yes, but doing that does not need to require brackets. Brackets wouldn't make that any better.The diagnostic doesn't need to fire when both sides are bool.Comparing bools is an anti-pattern.
Aug 19
On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:But I’ve also never seen anyone think this would work?It's easy to have a lapse of focus. Last hour, I accidentally used `&&` for bit masking instead of `&`. I also sometimes write `if (x = 3)` by mistake, or forget a `return` statement like this: ```D bool f(int x) { x == 3; } ``` Luckily the D compiler catches these. It's not that I thought these things would work in D, but simple human error. It's also worth noting that things are different in other programming languages. In some languages the last expression is automatically returned. And in Python, the order of operations makes `!a == b` actually work like most (new) programmers intend:pythonTruenot (3 == 4)Truenot 3 == 4False ```(not 3) == 4
Aug 13
On Tuesday, 13 August 2024 at 21:13:17 UTC, Dennis wrote:On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:Wow you have some… strange problems.But I’ve also never seen anyone think this would work?It's easy to have a lapse of focus. Last hour, I accidentally used `&&` for bit masking instead of `&`. I also sometimes write `if (x = 3)` by mistake, or forget a `return` statement like this: ```D bool f(int x) { x == 3; } ```Luckily the D compiler catches these. It's not that I thought these things would work in D, but simple human error.When you write the wrong thing, you get the wrong result. The language doesn’t pull any punches when it comes to much more complex things, so why be pedantic with something so elementary? If you want something like this to have an anti-goof mechanism, let’s just add such a mechanism for all of the other situations that might trip up a beginner: - mutability attributes are transitive —> always require parenthesis after mutability attributes - integral to floating point conversion can occur implicitly —> require a cast - operator precedence is arbitrary —> require parenthesis around every operator - cast doesn’t always do the same thing —> require a cast keyword after the type to make sure the programmer knows what type of cast it is (e.g. `cast(long, signExtend)myInt`) - dereferencing `null` values —> require a cast to `typeof(null)` ;) - contracts shouldn’t have side effects —> treat contract code as `pure` - integer promotion is stupid —> require a castIt's also worth noting that things are different in other programming languages. In some languages the last expression is automatically returned.Other languages will always have things that work in contradictory ways, should we really shape the language around that? Also if we added last-expression return then it would generally be convenient, instead of inconvenient like the proposed feature. Not that I’m particularly for or against last-expression return, it is what it Is.And in Python, the order of operations makes `!a == b` actually work like most (new) programmers intendExceptions terminate for loops, numbers are immutable class instances, `+`, and now this too? This is no python, it’s more akin to Jörmungandr!
Aug 14
On Wednesday, 14 August 2024 at 13:26:44 UTC, IchorDev wrote:Wow you have some… strange problems.If you've never made such silly programming mistakes, enjoy it while it lasts!let’s just add such a mechanism for all of the other situations that might trip up a beginner:Interesting list. Some of them have been seriously suggested for D or implemented in other languages. Specifically, D's integer promotion rules get criticized a lot, and some languages are a lot stricter about it. I do agree with you generally: just because a combination of features is commonly used mistakenly, doesn't mean a special case should be added disallowing the combination. However, there are cases where the ratio of erroneous usage / intentional usage is so large, that a compiler error will in practice reduce the total amount of 'programmer rage' so to speak. Whether `!a == b` is such a case depends. You apparently have seen intentional use, so it makes sense you judge it as not worth adding an error for. I'm actually curious, can you link to real code using that pattern intentionally?Other languages will always have things that work in contradictory ways, should we really shape the language around that?All I'm saying is that it's possible for polyglot programmer's to make mixups, in response to you saying you couldn't imagine how someone could make a mistake like `!a == b`.
Aug 14
On Wednesday, 14 August 2024 at 14:36:50 UTC, Dennis wrote:On Wednesday, 14 August 2024 at 13:26:44 UTC, IchorDev wrote:Thanks. I’m surprised my knackered brain still manages not to make such mistakes if they’re so common.Wow you have some… strange problems.If you've never made such silly programming mistakes, enjoy it while it lasts!Yes and I’m sure people have suggested requiring parenthesis after mutability attributes. The only one of those things I seriously want is requiring an explicit cast before dereferencing `null`; but it would require the compiler to literally be magical since it needs to be a compile-time feature obviously, but it depends on a runtime value.let’s just add such a mechanism for all of the other situations that might trip up a beginner:Interesting list. Some of them have been seriously suggested for D or implemented in other languages. Specifically, D's integer promotion rules get criticized a lot, and some languages are a lot stricter about it.I do agree with you generally: just because a combination of features is commonly used mistakenly, doesn't mean a special case should be added disallowing the combination. However, there are cases where the ratio of erroneous usage / intentional usage is so large, that a compiler error will in practice reduce the total amount of 'programmer rage' so to speak.I feel like integer promotion is a much more pressing issue in that department. It’s one of the few things I wish we’d just bin because it’s so atrocious. And personally I’ve been screwed over by arithmetic operator precedence on many occasions.You apparently have seen intentional use [of `!a == b`], so it makes sense you judge it as not worth adding an error for. I'm actually curious, can you link to real code using that pattern intentionally?I don’t think I said that? I might’ve written something like that a long time ago in another language. I don’t usually read other people’s code for fun, but it’s the kind of thing I can see myself writing, although probably as `x == !y` because it looks nicer. Also C code often uses `int` for booleans, so code that interfaces with C could trigger this mechanism even if we add an exception for `bool`.
Aug 14
On Wednesday, 14 August 2024 at 15:04:13 UTC, IchorDev wrote:I feel like integer promotion is a much more pressing issue in that department. It’s one of the few things I wish we’d just bin because it’s so atrocious.Oh, I thought the list represented things you _didn't_ want to see in the language. But your point is rather that D is not consistent about this kind of error prevention?And personally I’ve been screwed over by arithmetic operator precedence on many occasions.Same, which is why I often defensively parenthesize expressions with binary operators.I don’t think I said that?My bad, I thought your `!myInt == myBool` example was based on something you wrote in the past.
Aug 14
On Wednesday, 14 August 2024 at 15:41:13 UTC, Dennis wrote:On Wednesday, 14 August 2024 at 15:04:13 UTC, IchorDev wrote:What? No, I literally said that the only thing in that list that I’d want in the language is the null cast thing, which is impossible to do. I also stated separately that in an ideal world we’d **completely remove** integer promotion. In the list, the idea was that the compiler would force you to manually write a cast whenever and wherever the compiler decides to promote an integer, which would be an abomination: ```d short x = 1, y = 2; int z = x + y; //warning: integer promotion must be explicit int w = cast(int)x + cast(int)y; int ohNo = cast(int)x * cast(int)x + cast(int)y * cast(int)y + z*z + w*w; ```I feel like integer promotion is a much more pressing issue in that department. It’s one of the few things I wish we’d just bin because it’s so atrocious.Oh, I thought the list represented things you _didn't_ want to see in the language. But your point is rather that D is not consistent about this kind of error prevention?I do that less and less. I think that learning the precedence and omitting the parenthesis makes the code a lot easier to sight-read. The tipping point for me is about 3 nested parenthesis, after which they all start to blur together.And personally I’ve been screwed over by arithmetic operator precedence on many occasions.Same, which is why I often defensively parenthesize expressions with binary operators.
Aug 14
On Wednesday, 14 August 2024 at 18:19:00 UTC, IchorDev wrote:I also stated separately that in an ideal world we’d **completely remove** integer promotion. In the list, the idea was that the compiler would force you to manually write a cast whenever and wherever the compiler decides to promote an integer'removing integer promotion' and 'requiring a cast' (or other explicit type conversion between integers) read as the same thing to me. I didn't know you meant mandating explicit promotion casts, that would be an abomination indeed. But that still makes me confused about the message of your list. I thought it was supposed to demonstrate that anti-goof mechanisms are silly, but if you deliberately make the mechanisms an abomination, then of course they are.
Aug 14
On Wednesday, 14 August 2024 at 20:14:01 UTC, Dennis wrote:I didn't know you meant mandating explicit promotion casts, that would be an abomination indeed. But that still makes me confused about the message of your list. I thought it was supposed to demonstrate that anti-goof mechanisms are silly, but if you deliberately make the mechanisms an abomination, then of course they are.Removing integer promotion would not be equivalent to this proposal. This proposal says that you should be more explicit so that the compiler can be sure you aren’t making a mistake. When applying the same methodology to integer promotion, it produces an abomination; so the methodology should come into question for producing an abomination when applied to a similarly human-error-prone area of the language.
Aug 16
On Friday, 16 August 2024 at 14:40:15 UTC, IchorDev wrote:Removing integer promotion would not be equivalent to this proposal. This proposal says that you should be more explicit so that the compiler can be sure you aren’t making a mistake. When applying the same methodology to integer promotion, it produces an abomination; so the methodology should come into question for producing an abomination when applied to a similarly human-error-prone area of the language.Adding brackets to disambiguate does not introduce bugs, it makes code clearer. Requiring casts is brittle when the underlying type changes. That can introduce far worse bugs than integer promotion.
Aug 16
On Wednesday, 14 August 2024 at 18:19:00 UTC, IchorDev wrote:On Wednesday, 14 August 2024 at 15:41:13 UTC, Dennis wrote:IMO, not an example. “Integer promotion” to me means not implicit conversions from smaller integer types to bigger ones (like `short` to `int`), but the fact that `typeof(x + y)` is `int`. What I’d bin immediately is signed integer types converting to unsigned ones in any way (except for compile-time known happens-to-be-nonnegative values). Why can I add a `uint` and `short`? The intuitive answer would be: Because the result can fit in a `long` and we’re good – but in D, `typeof(uint(0) + short(-1))` is `uint`. It should require a cast: Either of the result or of the unsigned operand to a signed type.On Wednesday, 14 August 2024 at 15:04:13 UTC, IchorDev wrote:What? No, I literally said that the only thing in that list that I’d want in the language is the null cast thing, which is impossible to do. I also stated separately that in an ideal world we’d **completely remove** integer promotion. In the list, the idea was that the compiler would force you to manually write a cast whenever and wherever the compiler decides to promote an integer, which would be an abomination: ```d short x = 1, y = 2; int z = x + y; //warning: integer promotion must be explicit int w = cast(int)x + cast(int)y; int ohNo = cast(int)x * cast(int)x + cast(int)y * cast(int)y + z*z + w*w; ```I feel like integer promotion is a much more pressing issue in that department. It’s one of the few things I wish we’d just bin because it’s so atrocious.Oh, I thought the list represented things you _didn't_ want to see in the language. But your point is rather that D is not consistent about this kind of error prevention?I can handle parentheses a lot better when they’re not adjacent. I sometimes wish for abbreviation constructs such as `static assert is(..)` and even `is typeof()` which just mean what they’d mean with the obvious parentheses added, so that instead of: ```d static assert(is(typeof(a * (b + (c ? 0 : 1))))); ``` you could write ```d static assert is typeof(a * (b + (c ? 0 : 1))); ``` I’d also love if `if`, `while` and `switch` allowed an arbitrary [`PrimaryExpression`](https://dlang.org/spec/grammar.html#PrimaryExpression) instead of requiring parentheses.I do that less and less. I think that learning the precedence and omitting the parenthesis makes the code a lot easier to sight-read. The tipping point for me is about 3 nested parenthesis, after which they all start to blur together.And personally I’ve been screwed over by arithmetic operator precedence on many occasions.Same, which is why I often defensively parenthesize expressions with binary operators.
Aug 28
On Wednesday, 14 August 2024 at 14:36:50 UTC, Dennis wrote:Whether `!a == b` is such a case depends. You apparently have seen intentional use, so it makes sense you judge it as not worth adding an error for. I'm actually curious, can you link to real code using that pattern intentionally?I can’t link something, but I have definitely written something like that at some point to implement a XOR for bools. There are loads of situations where you need to test that two bools are equal or unequal and `!a == b` is a way to say `a != b`. It’s not a good way, granted, but I can definitely see why beginner me would have written that: `a != b` could compare anything, `!a == b` compares bools. What I’m saying is not that it’s good code, but not wildly unrealistic code either. The language keeping someone from writing that is a good thing. It’s in the same ballpark as `x => {}` not being allowed.
Aug 28
On Tuesday, 13 August 2024 at 20:30:10 UTC, IchorDev wrote:Doesn’t require a DIP, but I’ve also never seen anyone think this would work? Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`? Maybe that seems harsh, but I have never even thought of doing this because it’s just so obviously wrong—if I wrote it then I must have meant what I wrote, and I was probably happy with how it looked too. Having to wrap it in parenthesis would just negate that and add to my code’s parenthesis hell. P.S. this isn’t a bug; and `!` is ‘logical not’, not ‘negation’.It would make sense to allow it for only bools. However, we can write this code: ``` import std; void main() { int z = 4; writeln(z == 2); writeln(!z == 2); writeln(!z == 0); writeln(z == 0); } ``` The output is ``` false false true false ``` It's hard to justify allowing something like that to slip through given that it's an easy mistake to make. A test might not even catch it.
Aug 13
On 8/13/24 22:30, IchorDev wrote:On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:The main issue is this is a typo that indeed happens now and then, not that people would think it works. E.g., when you have: `foo() || function_call_long_name() == c` Now you negate the entire thing: `!(foo() || function_call_long_name() == c)` Now you think it would be more readable with individual negations. !foo() && !function_call_long_name() == c` This could easily happen, particularly if you are tired and you write a lot of Python. Now you compile and it does not work. If you test well enough, you'll notice it. You debug for a few minutes and eventually come across this part of the code again and notice the mistake. This could all be dealt with a bit more efficiently.A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).Doesn’t require a DIP, but I’ve also never seen anyone think this would work?Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`?That's a strawman, and a bit insulting to anyone who has made this particular typo.Maybe that seems harsh, but I have never even thought of doing this because it’s just so obviously wrong—if I wrote it then I must have meant what I wrote, and I was probably happy with how it looked too.Your elitist attitude is somewhat common and I think used to make similar (if somewhat less strong) statements 10 years ago, but I think it was not particularly wise. In the end, most code you'll run is not written by you. And most readers of your code do not want to read `!a==b`.Having to wrap it in parenthesis would just negate that and add to my code’s parenthesis hell. P.S. this isn’t a bug;This is a DIP idea, not a bug report.and `!` is ‘logical not’, not ‘negation’.Those are in fact synonyms. https://en.wikipedia.org/wiki/Negation
Aug 15
On Thursday, 15 August 2024 at 16:40:31 UTC, Timon Gehr wrote:On 8/13/24 22:30, IchorDev wrote:Sorry, I really had just never heard of people actually having this problem before reading this thread.On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:The main issue is this is a typo that indeed happens now and then, not that people would think it works.[…][…]Do we really need to pander to people who don’t even understand that logical operators only *return* `bool`?That's a strawman, and a bit insulting to anyone who has made this particular typo.Maybe that seems harsh, but I have never even thought of doing this because it’s just so obviously wrong—if I wrote it then I must have meant what I wrote, and I was probably happy with how it looked too.Your elitist attitude is somewhat common and I think used to make similar (if somewhat less strong) statements 10 years ago, but I think it was not particularly wise.E.g., when you have: `foo() || function_call_long_name() == c` Now you negate the entire thing: `!(foo() || function_call_long_name() == c)` Now you think it would be more readable with individual negations. !foo() && !function_call_long_name() == c` This could easily happen, particularly if you are tired and you write a lot of Python.I don’t really use Python very often, but I have done my fair share of after-hours programming. Does being tired really impair everyone else’s faculties of reasoning so much, or are you all really really sleep deprived? I hope you're all getting enough sleep! Anyway, I myself have made my fair share of other weird errors when being tired, but I’m not sure I could blame the language’s design for that.In the end, most code you'll run is not written by you. And most readers of your code do not want to read `!a==b`.Eh? As if I said this was a bug report? I am of course responding to you saying that this a bug:Having to wrap it in parenthesis would just negate that and add to my code’s parenthesis hell. P.S. this isn’t a bug;This is a DIP idea, not a bug report.What you are describing is not a bug in D at all, it’s a programming error wherein the programmer misuses the logical not operator. Describing this arrangement as a bug in the language is misleading if not entirely erroneous.A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`.They are synonyms in Boolean logic, but not in programming, [or in D](https://dlang.org/spec/expression.html#unary-expression). This is why we place the prefix ‘logical’ before them, because these are concepts from another area of study that uses conflicting terms.and `!` is ‘logical not’, not ‘negation’.Those are in fact synonyms. https://en.wikipedia.org/wiki/Negation
Aug 16
ollama run mistral-largeThe following message was sent to a board of the D programming language discussing language improvement ideas: Subject: Deprecate `!a == b` Body: A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction). Using simple English, as unambiguously as possible and adding helpful context, please explain what this message is trying to say. """ The message is suggesting an improvement for the D programming language. Specifically, it points out a common mistake where programmers write `!a == b` instead of `!(a == b)`. This can lead to bugs because `!a == b` is interpreted as `(!a) == b`, which might not be what the programmer intended and could silently cause errors. The message suggests that the language should issue a warning or error when it encounters this pattern, requiring explicit parentheses to avoid confusion. This would help prevent bugs and make code more reliable by ensuring that programmers are clear about their intentions."""No, the message is not suggesting that there is a bug in the D programming language itself. Instead, it is highlighting a common mistake that programmers might make due to the way certain expressions are parsed and evaluated in the language. Specifically, when someone writes `!a == b`, they often mean `!(a == b)` but forget to include the parentheses, leading to unexpected behavior because D interprets it as `(!a) == b`. The message is proposing a change that would help prevent this kind of mistake by making the language issue a diagnostic (such as a warning or error) in such cases. This would encourage programmers to write their expressions more explicitly, reducing the likelihood of unintended behavior and potential bugs in their code.Is the message suggesting that there is a bug in the language itself?negates `a == b` by prepending a `!`" ? The phrase "someone negates `a == b` by prepending a `!`" refers to the common mistake where a programmer intends to negate the result of an equality comparison but does so incorrectly. Specifically, instead of writing `!(a == b)`, which correctly negates the entire expression `a == b`, they write `!a == b`. Here’s what happens in this case: - The programmer intends to check if `a` is not equal to `b`. - They mistakenly write `!a == b` instead of `!(a == b)`. - In D, the expression `!a == b` is parsed as `(!a) == b`, which means: - First, `a` is negated (which can involve a type conversion to `bool`). - Then, this boolean result is compared with `b`. This mistake can lead to bugs because the expression does not do what the programmer intended. The message is suggesting that the language should issue a diagnostic in such cases to help catch these mistakes early and make it clearer how expressions are being interpreted by the compiler.What is the message trying to bring across when it says "someoneIn the context of programming, the terms "negate" and "logical NOT" are closely related but can have slightly different nuances depending on the specific usage: 1. **Negate**: - To negate something generally means to invert its meaning or value. - In a broad sense, negation can apply to various types of values (e.g., arithmetic negation for number numbers) and logical operations. - When applied specifically to boolean values, negating a condition typically involves changing `true` to `false` and vice versa. 2. **Logical NOT**: - Logical NOT is a specific type of negation that applies strictly to boolean (logical) values. - It reverses the truth value of a logical expression or condition. For example, if `x` is `true`, then then `!x` will be `false`. - In many programming languages, including D, the exclamation mark (`!`) is used as the logical NOT ope operator. In summary, "negate" can refer to a general concept of reversing or denying something, while "logical NOT" specifically refers to the operation that inverts boolean values using the `!` operator. In the context of the original message, "negating `a == b` by prepending a `!`" means applying the logical NOT operation to the result of the equality comparison (i.e., turning `true` into `false` and vice versa).What is the relationship between the words "negate" and "logical not"?phrase "invert the boolean value using the logical not operator"? Someone might choose to use the verb "negate" instead of the phrase "invert the boolean value using the logical NOT operator" for several reasons: 1. **Conciseness**: - The term "negate" is shorter and more concise than "invert the boolean value using the logical NOT operator." This can make communication quicker and easier to read, especially in contexts where brevity is important, such as technical discussions or documentation. 2. **Familiarity**: - The term "negate" is commonly used in mathematical and logical contexts, so it may be more immediately recognizable and familiar to many programmers and mathematicians. It conveys the general idea of reversing a value or condition without needing additional explanation. 3. **Broad Applicability**: - "Negate" can be used in a broader range of contexts, including arithmetic negation (e.g., `-x` for numbers) and logical negation (e.g., `!x` for booleans). This versatility makes it a useful term when discussing different types of operations that involve reversing values or conditions. 4. **Simplicity**: - Using "negate" can simplify the language used in explanations, making them more accessible to readers who may not be familiar with specific programming terminology like "boolean value" and "operator." It provides a clear and straightforward way to describe the action without getting into the technical details. In summary, using "negate" is often preferred because it is concise, familiar, broadly applicable, and simple, making communication more efficient and accessible.Why would someone choose to use the verb "negate" instead of theSend a message (/? for help)
Aug 16
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members.I was a bit surprised that someone would write that (other than someone new to C-like syntax), but then I saw: https://github.com/dlang/dmd/pull/16778#discussion_r1715017456I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).Yes, it's consistent with other bug-prone patterns that dmd requires parentheses to disambiguate: https://dlang.org/spec/expression.html#conditional_expressions https://dlang.org/spec/expression.html#bitwise_expressions Also braces for dangling `else`.
Aug 13
On Tuesday, 13 August 2024 at 20:55:09 UTC, Nick Treleaven wrote:On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:In my defence, I was half asleep and recovering from a cold, but CI would have caught this. Having said that, I agree, it should be made an error. Well deprecation then error, it probably doesn't need to be a DIPA bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members.I was a bit surprised that someone would write that (other than someone new to C-like syntax), but then I saw: https://github.com/dlang/dmd/pull/16778#discussion_r1715017456
Aug 13
On Tuesday, 13 August 2024 at 10:14:29 UTC, Timon Gehr wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).Well, just wanna say that this is an easy check to implement in Dscanner. That does not require any context. Just match the pattern in the AST and issue a warning.
Aug 14
On Wednesday, 14 August 2024 at 14:48:42 UTC, user1234 wrote:Well, just wanna say that this is an easy check to implement in Dscanner. That does not require any context. Just match the pattern in the AST and issue a warning.Sounds like a better idea to do that. I’m not a fan of having more ‘it’s unintuitive therefore we’ll force the code to be unreadable’ features like bitwise operators requiring parenthesisation.
Aug 14
On 8/14/24 20:27, IchorDev wrote:On Wednesday, 14 August 2024 at 14:48:42 UTC, user1234 wrote:I can't say I ever wanted `a & b==c`. Anyway, this is indeed the same kind of thing, and it would be consistent to ban this case too.Well, just wanna say that this is an easy check to implement in Dscanner. That does not require any context. Just match the pattern in the AST and issue a warning.Sounds like a better idea to do that. I’m not a fan of having more ‘it’s unintuitive therefore we’ll force the code to be unreadable’ features like bitwise operators requiring parenthesisation.
Aug 15
On Thursday, 15 August 2024 at 16:12:50 UTC, Timon Gehr wrote:I can't say I ever wanted `a & b==c`.In my dreams: ```d if(x & Flags.flag && y & Flags.flag){ //… } ``` But reality we just put a bandage of frustration over C’s mistakes.
Aug 16
On 8/16/24 17:48, IchorDev wrote:On Thursday, 15 August 2024 at 16:12:50 UTC, Timon Gehr wrote:Well, your dreams are true. This works.I can't say I ever wanted `a & b==c`.In my dreams: ```d if(x & Flags.flag && y & Flags.flag){ //… } ```But reality we just put a bandage of frustration over C’s mistakes.To some extent, but that's just what you get from C-inspired languages.
Aug 16
On Wednesday, 14 August 2024 at 14:48:42 UTC, user1234 wrote:Well, just wanna say that this is an easy check to implement in Dscanner. That does not require any context. Just match the pattern in the AST and issue a warning.That would error on `!bool == bool`, which is fine.
Aug 14
On Tuesday, August 13, 2024 4:14:29 AM MDT Timon Gehr via dip.ideas wrote:A bug that crops up now and then in D is that someone negates `a == b` by prepending a `!`. The result is `!a == b`. This parses as `(!a) == b` and will often silently do the wrong thing because negation implies cast to `bool`, and `bool` can be compared with integral types and `enum` members. I think it would be better for this to give a diagnostic and require explicit parentheses, similar to bitwise operators (where the operator precedence is unintuitive in the other direction).I don't think that I have ever seen anyone do something like !a == b with any type other than bool, and it would be annoying if it were disallowed for bool. So, I don't really think that such a change would be particularly valuable, but I also wouldn't particularly care if it were made an error in cases where the types involved aren't bool. It wouldn't affect code that I would write, and if it fixed the occasional bug, then that's arguably a good thing. However, I definitely would rather not see this become an error for bool. - Jonathan M Davis
Aug 16
On Friday, 16 August 2024 at 19:23:19 UTC, Jonathan M Davis wrote:It wouldn't affect code that I would write, and if it fixed the occasional bug, then that's arguably a good thing. However, I definitely would rather not see this become an error for bool. - Jonathan M DavisProblem is that a lot of C libraries use `alias LibSpecificBool = int;`. Maybe we just need a nice way to make C programmers less stu—I mean—to give integer type aliases bool semantics: `alias boolean LibSpecificBool = int;`
Aug 17