Thread overview
Implicit conversions of head-const to tail-const ranges
Mar 23, 2021
Per Nordlöw
Mar 23, 2021
Per Nordlöw
Mar 23, 2021
Per Nordlöw
Mar 23, 2021
Paul Backus
Mar 24, 2021
Per Nordlöw
Mar 24, 2021
Paul Backus
Mar 25, 2021
Simen Kjærås
March 23, 2021
Has there been any attempts in dmd to generalize implicit conversions to allow implicit conversion of a head-const to tail-const range? Similar to what already happens for dynamic arrays (slices).

Are there any apparent show-stoppers?
March 23, 2021
On Tuesday, 23 March 2021 at 16:50:24 UTC, Per Nordlöw wrote:
> Has there been any attempts in dmd to generalize implicit

There's already toHeadMutable defined in dmd which is likely part of a potential solution.
March 23, 2021
On Tuesday, 23 March 2021 at 16:50:24 UTC, Per Nordlöw wrote:
> Has there been any attempts in dmd to generalize implicit conversions to allow implicit conversion of a head-const to tail-const range? Similar to what already happens for dynamic arrays (slices).
>
> Are there any apparent show-stoppers?

Do we want such a change to affect

@safe unittest
{
    import std.algorithm.iteration : map;
    import std.stdio;
    auto x = [1, 2];
    const y = x.map!(_ => _*_);
    writeln(y);
}

currently printing

    const(MapResult!(__lambda2, int[]))([1, 2])

to instead print

    [1, 4]

?

I guess not.
March 23, 2021
On Tuesday, 23 March 2021 at 16:50:24 UTC, Per Nordlöw wrote:
> Has there been any attempts in dmd to generalize implicit conversions to allow implicit conversion of a head-const to tail-const range? Similar to what already happens for dynamic arrays (slices).
>
> Are there any apparent show-stoppers?

As far as I know the main reason this hasn't been done is that it requires user-defined implicit conversions (something like "opHeadMutable"), which Walter is generally opposed to.

You can't do a naive `const(Range!T)` -> `Range!(const(T))` conversion, because there may be `static if` statements (or other reflection) inside the `Range` template that cause incompatible structs to be generated for `T` and `const(T)`.
March 24, 2021
On Tuesday, 23 March 2021 at 20:44:03 UTC, Paul Backus wrote:
> You can't do a naive `const(Range!T)` -> `Range!(const(T))` conversion, because there may be `static if` statements (or other reflection) inside the `Range` template that cause incompatible structs to be generated for `T` and `const(T)`.

I don't quite follow what this refers to. Can you give a code reference or sample?
March 24, 2021
On Wednesday, 24 March 2021 at 10:25:41 UTC, Per Nordlöw wrote:
> On Tuesday, 23 March 2021 at 20:44:03 UTC, Paul Backus wrote:
>> You can't do a naive `const(Range!T)` -> `Range!(const(T))` conversion, because there may be `static if` statements (or other reflection) inside the `Range` template that cause incompatible structs to be generated for `T` and `const(T)`.
>
> I don't quite follow what this refers to. Can you give a code reference or sample?

struct Example(T)
{
    static if (isMutable!T)
        T t;
    else
        T* ptr;
}

It would be incorrect to allow `const(Example!int)` to implicitly convert to `Example!(const(int))`.
March 25, 2021
On Tuesday, 23 March 2021 at 16:50:24 UTC, Per Nordlöw wrote:
> Has there been any attempts in dmd to generalize implicit conversions to allow implicit conversion of a head-const to tail-const range? Similar to what already happens for dynamic arrays (slices).
>
> Are there any apparent show-stoppers?

I presented a method that would be mostly drop-in on the blog last year:

https://dlang.org/blog/2020/06/25/a-pattern-for-head-mutable-structures/

It would require some (additive) changes to Phobos to be useful, and was intended as a DIP until I was informed there was a plan for these conversions. I believe any solution would look similar to my solution, but there could be other options. Maybe I should look into the DIP route again.

--
  Simen