Thread overview
Weird const behavior
Dec 20, 2018
Simón Oroño
Dec 20, 2018
Adam D. Ruppe
Dec 20, 2018
Marko
Dec 20, 2018
Andrea Fontana
Dec 20, 2018
Marko
Dec 20, 2018
Marko
December 20, 2018
I have the following piece of code:


``````````````````````
#!/bin/env dub
/+ dub.sdl:
    name: day2
+/
import std.algorithm.iteration : group;
import std.stdio;

void main() {
    const auto a = group("simon");
    auto b = group("simon");
    writeln(a == b);
    writeln();
    writeln(a);
    writeln();
    writeln(b);
}
``````````````````````

When I run it, it gives me this output:

``````````````````````
true

const(Group!("a == b", string))("imon", Tuple!(dchar, uint)('s', 1))

[Tuple!(dchar, uint)('s', 1), Tuple!(dchar, uint)('i', 1), Tuple!(dchar, uint)('m', 1), Tuple!(dchar, uint)('o', 1), Tuple!(dchar, uint)('n', 1)]
``````````````````````

The only difference (code-wise) is the `const` keyword. I've tried with both `ldc` and `dmd` with same result. Why is the output different when the variable is `const`?
December 20, 2018
On Thursday, 20 December 2018 at 01:37:59 UTC, Simón Oroño wrote:
> The only difference (code-wise) is the `const` keyword. I've tried with both `ldc` and `dmd` with same result. Why is the output different when the variable is `const`?

A const range cannot be iterated by a generic template (without additional work, at least), so writeln just sees it as a blob instead of something it can loop over.
December 20, 2018
On Thursday, 20 December 2018 at 02:05:53 UTC, Adam D. Ruppe wrote:
> On Thursday, 20 December 2018 at 01:37:59 UTC, Simón Oroño wrote:
>> The only difference (code-wise) is the `const` keyword. I've tried with both `ldc` and `dmd` with same result. Why is the output different when the variable is `const`?
>
> A const range cannot be iterated by a generic template (without additional work, at least), so writeln just sees it as a blob instead of something it can loop over.

I'm not the OP but I'd like to understand this:

When he is comparing "a == b" it returns true, but then it diverges on the usability.

So a == b compares just values without types?

But is this right? I mean if they are equal shouldn't they have the same behavior?

Marko.
December 20, 2018
On Thursday, 20 December 2018 at 14:49:10 UTC, Marko wrote:
> But is this right? I mean if they are equal shouldn't they have the same behavior?

I don't think so:

    float a = 1.0;
    long b = 1;

    writeln(a == b);
    writeln(a/2 == b/2);




December 20, 2018
On 12/20/18 9:49 AM, Marko wrote:
> On Thursday, 20 December 2018 at 02:05:53 UTC, Adam D. Ruppe wrote:
>> On Thursday, 20 December 2018 at 01:37:59 UTC, Simón Oroño wrote:
>>> The only difference (code-wise) is the `const` keyword. I've tried with both `ldc` and `dmd` with same result. Why is the output different when the variable is `const`?
>>
>> A const range cannot be iterated by a generic template (without additional work, at least), so writeln just sees it as a blob instead of something it can loop over.
> 
> I'm not the OP but I'd like to understand this:
> 
> When he is comparing "a == b" it returns true, but then it diverges on the usability.
> 
> So a == b compares just values without types?
> 
> But is this right? I mean if they are equal shouldn't they have the same behavior?
> 
> Marko.

It's really how opEquals is marked.

opEquals for structs (without a specific implementation), is marked as a combination of comparing all the fields, whatever they are marked. Any basic types are comparable whether they are const or not. So most likely the range struct's opEquals is marked const.

However, popFront is likely not const. In some rare cases it can be (i.e. an infinite range of a single value). If the range cannot be operated, isInputRange returns false.

-Steve
December 20, 2018
On Thursday, 20 December 2018 at 15:15:42 UTC, Andrea Fontana wrote:
> On Thursday, 20 December 2018 at 14:49:10 UTC, Marko wrote:
>> But is this right? I mean if they are equal shouldn't they have the same behavior?
>
> I don't think so:
>
>     float a = 1.0;
>     long b = 1;
>
>     writeln(a == b);
>     writeln(a/2 == b/2);

Of course you can play around:

    uint  positive_one = 1;
    short minus_one = -1;
    uint max_int = 4294967295;

    writeln(minus_one > positive_one); // true
    writeln(minus_one == max_int); // true

Because promotion and implicit casting. But like I said this is sometimes confusion, and on the OP example it's worth.

Marko.
December 20, 2018
On Thursday, 20 December 2018 at 15:17:31 UTC, Steven Schveighoffer wrote:
> It's really how opEquals is marked.
>
> opEquals for structs (without a specific implementation), is marked as a combination of comparing all the fields, whatever they are marked. Any basic types are comparable whether they are const or not. So most likely the range struct's opEquals is marked const.
>
> However, popFront is likely not const. In some rare cases it can be (i.e. an infinite range of a single value). If the range cannot be operated, isInputRange returns false.
>
> -Steve

I know about promotion / implicit casting, but I always find this is a but awkward when comparing objects or structs it's equal but acts differently.

But I'm may be the minority. :)

Marko.