News for hackers. Stuff that matters.
Re:Named Booleans prevent C++ bugs and save you time by Animats on Saturday February 18, 2023 @03:34AM (#34845144)
The only problem with this approach is that you evaluate all the conditions, even if you don't need to. Sometimes that's inefficient, and sometimes it's invalid, as in

    char *p = NULL;
    ...
    if (p && *p != ' ') { ... }
If you write

    bool p_non_null = (p != NULL);
    bool char_non_space = (*p != ' ');
    if p_non_null && char_ non_space { ... }
Oops.
Re:Named Booleans prevent C++ bugs and save you time by bandika on Saturday February 18, 2023 @04:30AM (#34845442)
The correct rewriting would be:

    bool char_non_space = p_non_null && (*p != ' ');
Re:Named Booleans prevent C++ bugs and save you time by tpoacher on Saturday February 18, 2023 @05:07PM (#34851609)
but then 'char_not_space' is a misleading name, as it could denote the presence of a space due to p being null
Re:Named Booleans prevent C++ bugs and save you time by wruza on Saturday February 18, 2023 @08:29AM (#34846798)
Back in mid-00s I was thinking about languages and features. One of the keywords I still miss in mainstream is “alias”. Alias is a symbol that only evaluates lazily.

  alias not_null = (bool)p;
  alias not_space = (*p != ' ');

  if (not_null && not_space) {
This may bite you in another way, but living in a world where everything gets evaluated asap-y isn’t syntactically easy either.

Would be also nice to have this:

  alias __cache foo = <heavy(expr())>;

  if (foo && foo.length && foo[0].x) {
`foo` only evaluates once.
Re:Named Booleans prevent C++ bugs and save you time by yunruse on Saturday February 18, 2023 @09:32AM (#34847191)
I was curious about the concept of inverting this – requiring that all variables lazily evaluate, and in the case that evaluation is needed now, some keyword obtains it. But when I think about it, that's sort of just `await`.

I'm curious as to if it's feasible to syncretise these two aspects of variable evaluation into a shared feature that makes async and sync code feel alike.

Re:Named Booleans prevent C++ bugs and save you time by cesarb on Saturday February 18, 2023 @09:49AM (#34847288)
> I was curious about the concept of inverting this – requiring that all variables lazily evaluate, and in the case that evaluation is needed now, some keyword obtains it.

That's how Haskell works. Everything is lazily evaluated, and in the case that evaluation is needed now, the "seq" function obtains it (https://wiki.haskell.org/Seq).

Re:Named Booleans prevent C++ bugs and save you time by jeremyjh on Saturday February 18, 2023 @10:39AM (#34847651)
It’s called lazy evaluation but it isn’t really anything like await. Await blocks on a computation that is already running; it doesn’t begin evaluation only when you await it.
Re:Named Booleans prevent C++ bugs and save you time by anlsh on Saturday February 18, 2023 @11:37AM (#34848221)
In any sane language you can just do this using a lambda. Unfortunately C is just broken so :(
Re:Named Booleans prevent C++ bugs and save you time by mjevans on Saturday February 18, 2023 @11:50AM (#34848357)
Isn't alias handled by the C pre-processor's #DEFINE operation?

  #DEFINE NOT_NULL(x) (bool)x
  #DEFINE NOT_SPACE(x) ( ' ' != *x )
  // ...
  if ( NOT_NULL(v) && NOT_SPACE(v) ) { ... }
Re:Named Booleans prevent C++ bugs and save you time by k0k0r0 on Saturday February 18, 2023 @02:46PM (#34850331)
Technically, this is true, but most C++ programmers are very reluctant to use macros except for stuff like include guards or stuff like NDEBUG.

The reason is mainly the many language construct of C++ cover most traditional use cases of macros when programming C while at the same time being much less error prone than macros.

A sibling show how one easily can achieve the very same thing using short lambdas instead. That variant is also bound to the scope one is currently in, and in order to have that safety with a macro one would need to undefine the macros afterwards. One would also need to check that they are not yet defined beforehand, and if so restore the previous macro afterwards in order to not break completely unrelated code in case of macro name clashes.

Re:Named Booleans prevent C++ bugs and save you time by wruza on Saturday February 18, 2023 @08:01PM (#34852949)
Yep, #defines are non-lexical and add way too much clutter to be useful in this case, even when you’re non-reluctant in general.
Re:Named Booleans prevent C++ bugs and save you time by greggyb on Saturday February 18, 2023 @12:03PM (#34848503)
It is not a direct implementation, and may end up being clunky, but I expect a fairly small library of helper functions could improve ergonomics quite a bit:

Define your booleans as functions of no args. A sample in Python:

    var = 'abc'
    var_contains_a = lambda: 'a' in var
    var_shorter_than_5 = lambda: len(var) < 5

    if var_contains_a() and var_shorter_than_5():
        print(var)
Re:Named Booleans prevent C++ bugs and save you time by greggyb on Sunday February 19, 2023 @11:05AM (#34858706)
One challenge with the chosen example language, Python, is that functions are truthy. So if you forget to call the function that computes your boolean test, you end up with a default true.

Taking the last top-level statement, the `if`:

    if var_contains_a() and var_shorter_than_5: #note the lack of parens for the second
        print(var)
This will print a string of any length that contains 'a' (or any other collection that implements `in` and does, in fact, contain an element, 'a'). The second function is passed directly as a boolean expression, and being a function, it resolves to true.
Re:Named Booleans prevent C++ bugs and save you time by injidup on Saturday February 18, 2023 @01:19PM (#34849430)
I do this in c++ quite often with short lambdas

  auto not_null = [&]{ return (bool)p; };
  auto not_space = [&]{ return (*p != ' '); };

  if (not_null() && not_space()) {
It's not quite as ergonomic but it works.

As an aside. I was curious if the compiler will optimize in the short circuit even if you extract the eagerly evaluated named booleans. However I was pretty sure the rules of c++ are against you and tests show this to be the case

But if you simulate the alias keyword with lambdas then the result after optimization are the same

https://godbolt.org/z/3cczcnK4s

Re:Named Booleans prevent C++ bugs and save you time by garaetjjte on Sunday February 19, 2023 @03:07PM (#34861299)
>I was curious if the compiler will optimize in the short circuit even if you extract the eagerly

It will optimize, but not necessarily what you wanted... Because null dereference is UB (with default compiler flags), it's allowed to elide null check.

Re:Named Booleans prevent C++ bugs and save you time by gdprrrr on Sunday February 19, 2023 @05:54AM (#34856425)
Scala has lazy val
Re:Named Booleans prevent C++ bugs and save you time by cbarrick on Saturday February 18, 2023 @01:29PM (#34849564)
I understand your "invalid" point. Your example dereferences a potentially null pointer.

But I don't understand your "inefficient" point. At the end of the day, everything gets turned into SSA. So expression-per-line and nested-expressions generates the same code, right?

Re:Named Booleans prevent C++ bugs and save you time by maccard on Saturday February 18, 2023 @01:37PM (#34849651)
It's the same idea, that the && short circuits.

    bool dirty = ...;
    bool success = doExpensiveCalculation(...);
vs

    if (dirty && doExpensiveCalculation)
    {
Re:Named Booleans prevent C++ bugs and save you time by saghm on Saturday February 18, 2023 @02:03PM (#34849934)
Not necessarily; in first case, the stuff after the `&&` will definitively not be run. In the second case, it depends on how the code is optimized, and there's no guarantee that things moved to intermediate variables won't still be evaluated even if they're never used. Since the compiler presumably can't know the value of the boolean at runtime, it would need to reorder things to avoid doing the unnecessary work, and I wouldn't think it's something that you could just assume.
Re:Named Booleans prevent C++ bugs and save you time by ComplexSystems on Saturday February 18, 2023 @02:20PM (#34850111)
This is a good point. I think that if you really want something like these named bools but which keeps the same lazy evaluation behavior, you'd have to use preprocessor macros then.
Re:Named Booleans prevent C++ bugs and save you time by MithrilTuxedo on Saturday February 18, 2023 @09:42PM (#34853701)
Don't they just want a function with a clear name that returns a boolean value, something to mask the implementation details so it's not part of your cognitive load at that level of abstraction.
Re:Named Booleans prevent C++ bugs and save you time by rajnathani on Sunday February 19, 2023 @02:04AM (#34855230)
Future programming languages could have (IIRC some current PLs allow for such syntax, some of them I believe using 'let'):

    if (p_non_null = (p != NULL)) && (char_non_space = (*p != ' ')) { ... }
But where the IDE only shows the LHS of the expression as:

    if p_non_null && char_ non_space { ... }
But also where the IDE makes it easier to write the earlier full expression above.

Also, the initial code:

    bool p_non_null = (p != NULL);
    bool char_non_space = (*p != ' ');
    if p_non_null && char_ non_space { ... }
This could simply be analyzed by the compiler to not store the named boolean variables in the first place, and to evaluate them inline in the if-condition so as to allow for the short-circuiting to occur fine.