November 17, 2006
Antonio wrote:

> It's true:  the "correct" way is not to put "process" into "decission blocks".
> 
> But there is some cases where I prefer to do something like
> 
>    Recordset rd = new Recordset()
>    Recordset rd2 = new Recordset()
>    while( rd.Read() &&& rd2.Read() ) {
>      doSomething( rd, rd2 );
>    }
>    // at this point, the number of Read()'s MUST BE the same
>    // in rd and rd2
> 
> 
> it's equivalent to:
> 
>    RecordSet rd = new RecordSet()
>    RecordSet rd2 = new RecordSet()
> 
>    bool exists = rd.Read();
>    bool exists2 = rd2.Read();
>    while( exists && exists2 ) {
>      doSomething( rd, rd2 );
>      exists = rd.Read();
>      exists2 = rd2.Read();
>    }
> 
> 
> Ok... you say it could be wrote as
> 
>    while( rd.Read() & rd2.Read() ) {
> 
> But & is "bit" tester, not a Logic evaluator... We are talking about a hight level programming language... we can use "invariants" "preconditions" "postconditions" and.... SURPRISSE... I have to use a "bit test" for "logic comparations"... no thanks..

Well, for what it's worth - in Java, & | and ^ are called both "Integer Bitwise Operators" when used on integers and "Boolean Logical Operators", when used on booleans. && and || are called "Conditional And/Or".

Anyhow, when used on bools & is effectively a completely normal AND operator, equivalent to your &&&, nothing low-level about it, at least IMHO :) The only thing I'd change was that instead of always converting to integer (like the current spec says), if both sides are of bool type, the result is also bool.

> Otherwhise... bit test could be "optimized" (if left side is 0, "&" allways evaluates to 0).

I disagree.. a valid optimization never changes the meaning of code, so if the right side could have side-effects, it can't be optimized away (and if it doesn't have side effects, it doesn't matter anyway). Also note that short-circuit evaluation of && and || is not a matter of optimization, the two operators are defined to behave that way.


xs0
November 19, 2006
>Wouldn't it be nice to have an ''implies'' operator?

I'm not so sure: many people forget that in 'x imply y', if x is False then 'x imply y' is True, they use imply as an equivalent of and.

At least with !x || y, there is no such error.

In theory imply is not ambiguous, in practice it is, so we should avoid it.

RenoX
September 12, 2021

On Friday, 17 November 2006 at 13:24:01 UTC, xs0 wrote:

>

Mariano wrote:

>

One question about && and || optimization:

Is there some way to specify that I need to evaluate the 2 sides of the
comparer?

(something like &&& or ||| )

note: "if( And( left() , right() ) )" or similar is not a solution :-)

...

Other workarounds include

cast(bool)a & cast(bool)b
!!a & !!b
a?b?1:0:b?0:0 // just kidding

...

auto a = something();
auto b = somethingElse();
if (a && b) {
...
}

There is another way which I choose for bitwise-operable types:

if (a != 0 & b != 0) { ... }   // no short-circuit behaviour
if (a != 0 ^ b != 0) { ... }

For me it's better to read than cast(bool)a & cast(bool)b but it has same semantics.
This could probably generate better performing code than !!a & !!b.

September 12, 2021

On Tuesday, 14 November 2006 at 13:04:20 UTC, Mariano wrote:

>

Wouldn't it be nice to have an ''implies'' operator?

if(A -> B)

I know this can be written as

if(!A || B)

but the implication makes it far more clear for common day speach

if( check_boundaries -> a.length <= max_int )
process(a);

makes more sence than

if( !check_boundaries || a.length <= max_int )
process(a);

or

if( ! (check_boundaries && a.length > max_int ) )
process(a);

besides, I don't think the '->' notation should be a big problem for the parser, and the front end can easily convert this structure to the corresponding not + or/and.

There is, of course, still the issue of precedence, but I think it should match that of || and &&.

And since Walter likes Wikipedia links: http://en.wikipedia.org/wiki/ Logical_implication

Mariano

There is a cruel answer to this request.

For boolean type values, this operator exists in all C-like languages. The problem however only is, the arrow points into the wrong direction!

You might get what I'd like to say:

if (a implies b) { ... }

is

if (a <= b) { ... }

in C-derived languages. I wouldn't call Java to be C-derived.
It's opposite to logic which would write

if (a => b) { ... }

to mean the same thing.

You also could write

if (b >= a) { ... }
if (!a >= !b) { ... }
if (!(a > b)) { ... }

If you would define an "implies" operator like which is available in current generation programming languages then the definition would look like:

a => b   :=    !(cast(bool)a >= cast(bool)b)

Funny enough though, the IEC logic gate symbols use >= 0 to denote the OR-gate.

The bi-implication works better:

if (a == b) { ... }   // eqv. to  if (a >= b && a <= b) { ... }
if (a != b) { ... }   // negated bi-implication

We would need to get used to writing the arrow in the wrong direction! Probably possible, but I find the confusion pretty terrible. At least, there is a mnemonic to say, that the symbol => does not exist and therefore <= is reused instead and implication always is from left to right (in my university it really is).

Or we use this close notation instead:

if (a ? b : true)  { ... }

The best syntax for an implication probably would be

if (a ? b) { ... }

and less

if (a !| b) {}   :=   if (!a || b ) { }

which is equivalent.

Only dumb that the null-coalescing operator if (a ?? b) ... in other languages already has the meaning if (!a ? b) ... (which is equivalent to the or operator like in Python).

My guess is though, that rather C++ would come up with something like => than D would. C++ now introduced the spaceship operator which is useful when working with comparators:

a <=> b := (int(a > b) - int(a < b))

(Looks like >-< would have described the meaning better.)


A last solution would be adding this to your global utility functions:

```
pragma(inline) pure @safe @nogc nothrow
bool implies(in bool a, in bool b) {
    return a <= b;
}
unittest {
    static assert(false .implies (false));
    static assert(false .implies (true));
    static assert(! true .implies (false));
    static assert(true .implies (true));
}
```

The operator precedence is still wrong.

September 13, 2021

On Sunday, 12 September 2021 at 09:08:12 UTC, Elmar wrote:

>

On Friday, 17 November 2006 at 13:24:01 UTC, xs0 wrote:

>

Mariano wrote:

>

One question about && and || optimization:

Is there some way to specify that I need to evaluate the 2 sides of the
comparer?

(something like &&& or ||| )

note: "if( And( left() , right() ) )" or similar is not a solution :-)

...

Other workarounds include

cast(bool)a & cast(bool)b
!!a & !!b
a?b?1:0:b?0:0 // just kidding

...

auto a = something();
auto b = somethingElse();
if (a && b) {
...
}

There is another way which I choose for bitwise-operable types:

if (a != 0 & b != 0) { ... }   // no short-circuit behaviour
if (a != 0 ^ b != 0) { ... }

<source>(14): Error: num != 0 must be surrounded by parentheses when next to operator &

& ^ and | have higher prio than comparison ops. => parenthesis required.

>

For me it's better to read than cast(bool)a & cast(bool)b but it has same semantics.
This could probably generate better performing code than !!a & !!b.

September 13, 2021

On 9/12/21 7:36 AM, Elmar wrote:

>

On Tuesday, 14 November 2006 at 13:04:20 UTC, Mariano wrote:

FYI this thread is FIFTEEN years old. Please do not resurrect zombie threads. Instead, link to them (as the forum UI no doubt told you, and offered a button to click to actually fix it instantly).

-Steve

September 13, 2021
On Monday, 13 September 2021 at 13:45:51 UTC, Steven Schveighoffer wrote:
> FYI this thread is FIFTEEN years old. Please do not resurrect zombie threads. Instead, link to them (as the forum UI no doubt told you, and offered a button to click to actually fix it instantly).
>
> -Steve

I have not seen any other posts by this account in other threads. Could it be that the server just lagged half a generation with processing his post?
September 13, 2021

On Monday, 13 September 2021 at 19:00:44 UTC, Dukc wrote:

>

I have not seen any other posts by this account in other threads. Could it be that the server just lagged half a generation with processing his post?

Stupid me, can't be:

>
```
pragma(inline) pure @safe @nogc nothrow
bool implies(in bool a, in bool b) {
    return a <= b;
}
unittest {
    static assert(false .implies (false));
    static assert(false .implies (true));
    static assert(! true .implies (false));
    static assert(true .implies (true));
}
```

@nogc was accepted in 2014 according to https://wiki.dlang.org/DIP60. And pragma(inline) in 2015. So that's it, this was a necrobump of at least 9 years.

September 17, 2021

On Monday, 13 September 2021 at 13:45:51 UTC, Steven Schveighoffer wrote:

>

On 9/12/21 7:36 AM, Elmar wrote:

>

On Tuesday, 14 November 2006 at 13:04:20 UTC, Mariano wrote:

FYI this thread is FIFTEEN years old. Please do not resurrect zombie threads. Instead, link to them (as the forum UI no doubt told you, and offered a button to click to actually fix it instantly).

-Steve

Thanks Steve. Sorry for bothering you.
Is there a specific advantage in starting a new thread for an old thread, for a topic which might be relevant for different people from time to time?

September 17, 2021

On Friday, 17 September 2021 at 00:12:32 UTC, Elmar wrote:

>

Thanks Steve. Sorry for bothering you.
Is there a specific advantage in starting a new thread for an old thread, for a topic which might be relevant for different people from time to time?

It's Forum Etiquette 101. Many forums forbid it completely, others allow it under specific circumstances. Some even go so far as to automatically lock threads after a certain amount of time has passed.

The term "necroposting" refers to bumping old threads just to get them to the top again. That's probably the original motivation for such forum rules, but over time it has come to be viewed as a common courtesy not to resurrect old threads. Here's how I view it.

Generally, when people reply to a post they expect that they are replying to a current conversation and often don't pay attention to the date of the thread. Most of the time they are, because forum etiquette across the internet generally guarantees it. So it's extremely annoying to subsequently realize that a new post you just replied to is in a thread that is 15 years old. Were there other threads in the intervening years that made this one irrelevant? Was replying to the post that resurrected the thread a waste of time?

It's especially annoying when the old thread has several pages of posts. I can follow a current as it develops since I usually check the forums several times a day. For a resurrected thread, I have to go back through the whole thread for context. Even if it's a thread I participated in or read in the past, the discussion is long gone from my memory. If the thread is old enough, the web interface/newsreader/email client may show me several unread posts, clueing me in to check the dates. But if I've already marked the old posts as read at some point in the past, I can easily overlook it and not realize it until I've already invested time I wouldn't otherwise have invested.

By creating a new thread and linking to the original, it's clear from the beginning that you are continuing an old (in this case, very old) conversation, and readers can then make a conscious decision to view the older thread.

I think it's justifiable to resurrect an old thread if: the thread is no more than two or three years old; you are certain the topic is still relevant; the thread is not more than a couple of pages on the web interface. I mean, it's a fuzzy boundary and people will disagree on where it lies, and this is just where I think it lies. Some people will argue that it's a stupid bit of etiquette anyway. But I'm pretty sure many will agree that 15 years is much too old.