I dont suppose there's any way to do logical and/or in C without coercing the result to 0 or 1?
I.e. `0 || 5` would result in 5, not 1
I dont suppose there's any way to do logical and/or in C without coercing the result to 0 or 1?
I.e. `0 || 5` would result in 5, not 1
@eniko hmm .. and what then something like 2 || 5 should give then ? 2 ? 5 ? the greater ? the smaller ?
It's so irritating that something as simple as logical and/or isn't the same in different languages :/
In some languages 0 or 5 is 1, in others 0 or 5 is 5
@eniko What context is this in/which problem are you trying to solve?
Certainly, short-circuiting and non-booleans might have some low-level utility, but I'm not seeing it off-hand. I'm curious about what you need to do (although that might not help provide a better answer :(
@yo posted about it here: https://peoplemaking.games/@eniko/113220657017389342
@eniko your question is very interesting, thanks- I'm having fun poking with Godbolt and learning that && and || seem to always generate branching (gcc and clang, x86 and aarch64), and now I'm wondering why they would define them to always return 0 and 1 and not make it implementation-dependant.
(But then, I know nothing about C, so what do I know.)
@eniko you may have found https://cs.stackexchange.com/questions/155125/in-c-why-limit-and-to-evaluate-to-booleans already, which I found interesting (esp. the use of __typeof__ to define the macro).
@eniko Thanks, sorry I wasn't able to see that when I read the thread.
Sorry, I don't have much to contribute- I think because I still don't understand *why* C defines the operators to return 0 or 1, which I guess is the key. (I don't quite grasp clar fon's explanation.)
Thanks for giving us something interesting to think about! I'm getting into doing lower-level stuff progressively, and this is didactic.
@yo the reason C defines logical operators to return 0 or 1 is because they're boolean operations. now, C doesn't have a dedicated boolean type, but even without that wrapper this is still desirable behavior
for example take `(A && B) == (C && D)`
you would expect this to be true if A, B, C, and D are all non-zero. but the equality comparer in C just checks two numbers for equality. so even if they're all non-zero, if you don't coerce to 1 for true, this would return false (or 0) if B and D had different non-zero values
this is why you'll often see `!!x` in javascript, because this coerces a truthy value to a true boolean and a falsey value to a false boolean
@eniko oh, yeah; I would've thought not coercing to 0 and 1 could be better for performance, but being able to use == != intuitively is good, I guess.
I think we're just screwed that in the end, low-level booleans don't "exist" (or at least, they didn't in the past), so low-level programming languages are always going to have rough edges around booleans.
Thanks for the explanation!
@eniko Sorry "I am TOO OLD SKOOL" ( and mostly C/C++/ASM only ) .. WHAT LANGUAGE on Earth has a 0 || 5 = 5 ??! 😱
Suppose I could make an inline function like
int or(int x, int y) {
if (x) return x;
return y;
}
ok i think this will work even if nested, without statement expressions (so will compile on MSVC)
ORV(x, y) (tmp = (x) ? tmp : (y))
ANDV(x, y) (tmp = (x) ? (y) : tmp)
the AND version felt dicey but i realized that if you get to the (y) expression the tmp value is never evaluated so it's fine if it gets clobbered
@eniko If you do you own function, why don't use if/then/else instead of 'risking' with the ? thing ? .. At this point I won't change too much I suppose.
@eniko so this is neat, but I'm mostly curious if you're able to provide a bit more insight into what you're using this for
I've gotten super Rust-brained lately so I'm having trouble understanding the benefits of mixing up integers and booleans like this
@clarfonthey i'm developing an IR for a virtual machine and when i was making and/or yesterday i was just treating zero as false and anything else as true
so `0 or 5` is 5, because 5 is true
then i realized that's inconvenient if you wanna do like `(a && b) == (c or d)` because im not coercing truthy values to 1 so this wouldn't work
i also kinda wanna make this transpilable to human-readable C and realized C's logical operators always coerce the result to 0 or 1 (likely for exactly this reason)
then i realized other languages like lua and javascript actually do it kinda the way i was doing it and i realized i kinda wanna support being able to do it both ways
but if i want value selecting logical operators, and C only has boolean logical operators, and i wanna transpile to C, then i have to find a way to make those work in C
@gilesgoat because you can't do if/then/else inline in an expression
@gilesgoat @eniko JavaScript 😬
@gilesgoat @eniko many languages say that "a or b" is the first "truthy" of the two expressions. What "falsy/truthy" is, is a different can of worms.
@Xarizzar @gilesgoat and lua
@Xarizzar @gilesgoat @eniko That is probably the most annoying feature of JavaScript I ever experienced. I am old-school and learned that "0 || 5 == 1 (true)", as defined by Boolean Algebra, but then I saw how it was used in some JavaScript-code and my brain exploded.
Using it instead of "0? 0:5" is really annoying, especially since JS has the "?"-op.
@gilesgoat To be fair, at that point, just use parenthesis, and/or maybe actual if statements, no? Sometimes programming is a work of art but damn if we all don't need to be a little bit more clear in our code at times, hahaha
@Xarizzar in other words KISS ( Keep It Simple and Stupid ) and don't use "exclusive features" that only some languages have ? 🙂
@eniko @Xarizzar @gilesgoat and python, and perl, and pretty much any of the "lisp but with syntax" languages.
@deshipu @eniko @Xarizzar At this point better those STRONG IMPERATIVE languages a la' VHDL/PASCAL where if you do a thing like NUMERIC OR NUMERIC the result is NUMERIC ( i.e. bitwise OR ) BOOLEAN OR BOOLEAN and result can be only TRUE or FALSE (0/1) and you CAN NOT do a thing like NUMERIC OR BOOLEAN ( or else ) unless you cast types so they are the same so "(BOOLEAN) a OR b" or instead "a OR (NUMERIC) b" and if b is BOOLEAN its cast can only be numerically 0 or 1 ( or something like that ).
@gilesgoat don't shout
@gilesgoat 2, because any non-zero value is truthy so the right hand side isn't evaluated
@eniko That's quite a weird problem to be solved in C .. if you really want the left-to-right precedence and AVOID the computation of the 'right side' if left is already seen as 'false' .. actually I don't even know if it can be solved because it would be something 'at compile time' ? 🤔
@gilesgoat @eniko
(x = 2) ? x : 5
avoids evaluating 2 twice, but needs a variable declaration