Thread overview
How to workaround assignment not allowed in a condition?
Oct 12, 2022
Dennis
Oct 12, 2022
Dennis
Oct 12, 2022
user1234
Oct 12, 2022
Rene Zwanenburg
October 11, 2022

Porting some C code to D

This results in an error:

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

Error is: assignment cannot be used as a condition, perhaps == was meant?

OK, fine, I'll use ==:

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:

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:

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

Am I missing something?

-Steve

October 12, 2022

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:

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:

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:

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?

October 12, 2022
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
October 12, 2022

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:

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)

October 12, 2022

On Wednesday, 12 October 2022 at 02:15:55 UTC, Steven Schveighoffer wrote:

>

Porting some C code to D

This results in an error:

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.

October 12, 2022

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)
October 12, 2022
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
October 12, 2022
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