www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling assumeSorted on const(std.container.Array)

reply Olivier Prat <o.prat free.fr> writes:
I'm trying to call assumeSorted on a const(Array) using this code 
snippet:

     void test(T)(const ref Array!T a)
     {
         auto b = a[].assumeSorted;
         writeln(b);
     }

     void main() {
         Array!int a = [1, 5, 7, 8, 15, 100];
         test(a);
     }

Unfortunately, I keep having a compilation error:
/dlang/dmd/linux/bin64/../../src/phobos/std/range/package.d(10871): Error:
cannot modify struct instance `result._input` of type
`RangeT!(const(Array!int))` because it contains `const` or `immutable` members
/dlang/dmd/linux/bin64/../../src/phobos/std/range/package.d(10918): Error:
cannot modify struct instance `result._input` of type
`RangeT!(const(Array!int))` because it contains `const` or `immutable` members
/dlang/dmd/linux/bin64/../../src/phobos/std/range/package.d(11500): Error:
template instance `std.range.SortedRange!(RangeT!(const(Array!int)), "a < b",
SortedRangeOptions.assumeSorted)` error instantiating
onlineapp.d(10):        instantiated from here: `assumeSorted!("a 
< b", RangeT!(const(Array!int)))`
onlineapp.d(17):        instantiated from here: `test!int`

Would someone explain the exact nature of this error as I fail to 
understand as how just telling that an Array ConstRange is 
assumed to be sorted actually modifies anything??
Mar 25 2023
next sibling parent reply Olivier Prat <o.prat free.fr> writes:
On Saturday, 25 March 2023 at 13:45:36 UTC, Olivier Prat wrote:
 I'm trying to call assumeSorted on a const(Array) using this 
 code snippet:

 [...]
In a similar fashion, a number of methods in SortedRange do not compile if called on a const(SortedRange) or immutable(SortedRange), such as length, or front. Is this on purpose?
Mar 25 2023
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 3/25/23 09:31, Olivier Prat wrote:
 On Saturday, 25 March 2023 at 13:45:36 UTC, Olivier Prat wrote:
 I'm trying to call assumeSorted on a const(Array) using this code 
 snippet:

 [...]
In a similar fashion, a number of methods in SortedRange do not compile if called on a const(SortedRange) or immutable(SortedRange), such as length, or front. Is this on purpose?
There are a number of interesting points in your original post but I couldn't find time to answer all of those. I can inject this for now: :) assumeSorted returns a range object. The concept of a const range object is flawed because by nature iteration of a range happens by mutating it: For example, popBack has to do that. So, it's normal that any range algorithm will assume a non-const object. Ali
Mar 25 2023
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/25/23 9:45 AM, Olivier Prat wrote:

 Would someone explain the exact nature of this error as I fail to 
 understand as how just telling that an Array ConstRange is assumed to be 
 sorted actually modifies anything??
It's because a Range keeps a copy of the array (Array is a reference counted type). Since that is labeled `const`, then editing the Range is forbidden. Inside SortedRange, it has this, which is causing the issue: ```d static if (isForwardRange!Range) property auto save() { // Avoid the constructor typeof(this) result = this; result._input = _input.save; return result; } ``` Overwriting the input isn't possible here, because it contains a const member. Now, this possibly could be fixed with something like: `return typeof(this)(_input.save);` But it might just push the error to another place. The whole thing is kind of ugly. There is a note inside the Array Range which says it's trying to work around some old bug that is now marked as "works for me", so maybe that can be reexamined. https://github.com/dlang/phobos/blob/17b1a11afd74f9f8a69af93d77d4548a557e1b89/std/container/array.d#L137 -Steve
Mar 25 2023
parent Olivier Prat <o.prat free.fr> writes:
On Sunday, 26 March 2023 at 02:16:15 UTC, Steven Schveighoffer 
wrote:
 On 3/25/23 9:45 AM, Olivier Prat wrote:

 [...]
It's because a Range keeps a copy of the array (Array is a reference counted type). Since that is labeled `const`, then editing the Range is forbidden. Inside SortedRange, it has this, which is causing the issue: ```d static if (isForwardRange!Range) property auto save() { // Avoid the constructor typeof(this) result = this; result._input = _input.save; return result; } ``` Overwriting the input isn't possible here, because it contains a const member. Now, this possibly could be fixed with something like: `return typeof(this)(_input.save);` But it might just push the error to another place. The whole thing is kind of ugly. There is a note inside the Array Range which says it's trying to work around some old bug that is now marked as "works for me", so maybe that can be reexamined. https://github.com/dlang/phobos/blob/17b1a11afd74f9f8a69af93d77d4548a557e1b89/std/container/array.d#L137 -Steve
Thanks to both of you for the answers. It confirms my investigation and my workaround is to cast the const ranges into their non const versions, when I encounter these issues. Not very pretty.
Mar 26 2023