www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to workaround assignment not allowed in a condition?

reply Steven Schveighoffer <schveiguy gmail.com> writes:
Porting some C code to D

This results in an error:

```d
int x;
while(!(x = 5)) { break; }
```
Error is: assignment cannot be used as a condition, perhaps `==` was meant?

OK, fine, I'll use `==`:

```d
int x;
while(!(x = 5) == true) { break; }
```

Nope, same error. I tried reversing the operands. I also tried using it 
in a boolean expression. As long as `=` appears in there, it gives me 
the error.

The only thing I can get to work is to make an immediately called lambda:

```d
while(!(() => x = 5)()) { break; }
```

Is this seriously the only way to get around this? With other linting 
errors, there's usually an easy workaround. like:

```d
if(x); // Error
if(x) {} // ok
```

Am I missing something?

-Steve
Oct 11 2022
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven 
Schveighoffer wrote:
 Porting some C code to D

 This results in an error:
I had the same issue, where the pattern was this: ```C void f() { int err; if (err = some_api_call()) { printCode(err); return; } if (err = some_other_api_call()) { printCode(err); return; } } ``` I would either declare the variable in the if statement: ```D void f() { if (auto err = some_api_call()) { printCode(err); return; } if (auto err = some_other_api_call()) { printCode(err); return; } } ``` Or take the assignment out of the condition: ```D void f() { int err; err = some_api_call(); if (err) { printCode(err); return; } err = some_other_api_call(); if (err) { printCode(err); return; } } ``` I haven't seen it used in a while condition yet, perhaps you can transform that into a for loop?
Oct 12 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/12/22 5:24 AM, Dennis wrote:
 On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven Schveighoffer wrote:
 Porting some C code to D

 This results in an error:
I had the same issue, where the pattern was this: ```C void f() {     int err;     if (err = some_api_call()) {         printCode(err);         return;     }     if (err = some_other_api_call()) {         printCode(err);         return;     } } ```
The code in question doesn't follow this pattern. The target in question is inside a struct that is passed in via pointer The original code looks like this: ```c static int sinfl_build_tbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, const int *cnt) { int tbl_end = 0; while (!(gen->cnt = cnt[gen->len])) { ++gen->len; } ``` So using `auto` isn't going to work here, I need to get the value out to the final destination. And I can't do that inside the loop because the condition may already have terminated it.
 I haven't seen it used in a while condition yet, perhaps you can 
 transform that into a for loop?
That also was suggested on discord, the issue with it is that then I have to repeat the assignment code for the iteration. As you are probably more aware than others, while porting code, you don't want to refactor at the same time. Simple syntax changes are ok, as long as the meaning stays the same. Using a for loop is a possible change that's equivalent, but I'd rather avoid it if possible. I was expecting there to be a way to write problematic code where the compiler says "OK, if you wrote it that way, you really mean it, I'll shut up". But there doesn't appear to be any way to do that in this case. I'm actually very surprised that just wrapping the statement in an == expression doesn't do the trick, what is the possible logic behind outlawing that? -Steve
Oct 12 2022
parent reply Dennis <dkorpel gmail.com> writes:
On Wednesday, 12 October 2022 at 10:09:31 UTC, Steven 
Schveighoffer wrote:
 I'm actually very surprised that just wrapping the statement in 
 an == expression doesn't do the trick, what is the possible 
 logic behind outlawing that?
I looked into it, there are actually two different places where dmd files the very same error: ```D void main() { int x; // Directly in loop conditions if (x = 3) {} while (x = 3) {} for (; x = 3; ) {} // when an assignment is implicitly cast to a boolean bool b = !(x = 3); assert(x = 3); true && (x = 3); } ``` Wrapping in `==` actually does do the trick, but you need to get rid of the `!` operator. So instead of `while(!(x=3) == true)` make it `while ((x=3) == false)`
Oct 12 2022
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/12/22 7:46 AM, Dennis wrote:
 On Wednesday, 12 October 2022 at 10:09:31 UTC, Steven Schveighoffer wrote:
 I'm actually very surprised that just wrapping the statement in an == 
 expression doesn't do the trick, what is the possible logic behind 
 outlawing that?
I looked into it, there are actually two different places where dmd files the very same error: ```D void main() {     int x;     // Directly in loop conditions     if (x = 3) {}     while (x = 3) {}     for (; x = 3; ) {}     // when an assignment is implicitly cast to a boolean     bool b = !(x = 3);     assert(x = 3);     true && (x = 3); } ``` Wrapping in `==` actually does do the trick, but you need to get rid of the `!` operator. So instead of `while(!(x=3) == true)` make it `while ((x=3) == false)`
Wow thanks! However, this is tricky, because what is happening is instead of the (x = 3) being converted to bool (which would have the same error), `true` is being converted to `int`. So if you had a condition like `while(x = 3)`, you would have to do `while((x = 3) != false)` and not `while((x = 3) == true)` Or, you can just say `while((x = 3) != 0)` But yes, this is the solution. -Steve
Oct 12 2022
prev sibling next sibling parent user1234 <user1234 12.de> writes:
On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven 
Schveighoffer wrote:
 Porting some C code to D

 This results in an error:

 ```d
 int x;
 while(!(x = 5)) { break; }
 ```
 Error is: assignment cannot be used as a condition, perhaps 
 `==` was meant?
 ...
I think D should relax the restriction and allows the AssignExp as condition they are enclosed between parentheses.
Oct 12 2022
prev sibling parent reply Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven 
Schveighoffer wrote:
 Am I missing something?
Perhaps I am, but why not turn it into a numeric comparison, like: ``` while((i = 5) == 0) ```
Oct 12 2022
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/12/22 9:17 AM, Rene Zwanenburg wrote:
 On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven Schveighoffer wrote:
 Am I missing something?
Perhaps I am, but why not turn it into a numeric comparison, like: ``` while((i = 5) == 0) ```
Yes, that is the answer, that was eluding me. What blinded me from it is that the original was `while(!(i = 5))`, and I couldn't see past that `!` operator. -Steve
Oct 12 2022