Issue 9947 - reduce of an array of structs with an immutable field
Summary: reduce of an array of structs with an immutable field
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: x86 Windows
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-16 16:16 UTC by bearophile_hugs
Modified: 2024-12-01 16:17 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2013-04-16 16:16:16 UTC
Maybe this should work:


import std.algorithm: reduce;
struct Foo {
    immutable int x;
}
void main() {
    auto data = [Foo(0)];
    reduce!((a, b) => a)(data);
}



DMD 2.063alpha gives:

...\dmd2\src\phobos\std\algorithm.d(702): Error: cannot modify struct result Foo with immutable members
...\dmd2\src\phobos\std\algorithm.d(723): Error: template instance test.main.reduce!(__lambda3).reduce!(Foo,Foo[]) error instantiating
test.d(7):        instantiated from here: reduce!(Foo[])
test.d(7): Error: template instance test.main.reduce!(__lambda3).reduce!(Foo[]) error instantiating
Comment 1 Ryuichi OHORI 2013-05-16 03:19:35 UTC
Using DMD32 v2.061 on Windows 32bit, below doesn't work too.
I think this is the same issue:
-----
import std.stdio;
import std.algorithm : sort;

struct S
{
    immutable int x;
}

void main()
{
    auto arr = [S(0), S(2), S(1)];
    sort!((a, b) => a.x < b.x)(arr);
    arr.writeln();
}
-----

algorithm.d(1814):Error: cannot modify struct lhs S with immutable members
algorithm.d(1815): Error: cannot modify struct rhs S with immutable members
algorithm.d(7972): Error: template instance std.algorithm.swap!(S) error instantiating
algorithm.d(7908):   instantiated from here: swapAt!(S[])
algorithm.d(7993):   instantiated from here: getPivot!(__lambda3, S[])
algorithm.d(7712):   instantiated from here: quickSortImpl!(__lambda3, S[])
main.d(12):        instantiated from here: sort!(__lambda3, cast(SwapStrategy)0, S[])
algorithm.d(7908): Error: template instance std.algorithm.swapAt!(S[]) error instantiating
algorithm.d(7993):   instantiated from here: getPivot!(__lambda3, S[])
algorithm.d(7712):   instantiated from here: quickSortImpl!(__lambda3, S[])
main.d(12):        instantiated from here: sort!(__lambda3, cast(SwapStrategy)0, S[])
algorithm.d(7993): Error: template instance main.main.getPivot!(__lambda3, S[]) error instantiating
algorithm.d(7712):   instantiated from here: quickSortImpl!(__lambda3, S[])
main.d(12):        instantiated from here: sort!(__lambda3, cast(SwapStrategy)0, S[])
algorithm.d(7946): Error: cannot modify struct r[j] S with immutable members
algorithm.d(7949): Error: cannot modify struct r[j] S with immutable members
algorithm.d(8028): Error: template instance main.main.optimisticInsertionSort!(__lambda3, S[]) error instantiating
algorithm.d(7712):   instantiated from here: quickSortImpl!(__lambda3, S[])
main.d(12):        instantiated from here: sort!(__lambda3, cast(SwapStrategy)0, S[])
algorithm.d(7712): Error: template instance main.main.quickSortImpl!(__lambda3, S[]) error instantiating
main.d(12):        instantiated from here: sort!(__lambda3, cast(SwapStrategy)0, S[])
main.d(12): Error: template instance main.main.sort!(__lambda3, cast(SwapStrategy)0, S[]) error instantiating
Comment 2 monarchdodra 2014-02-25 12:27:55 UTC
(In reply to comment #0)
> Maybe this should work:
> 
> 
> import std.algorithm: reduce;
> struct Foo {
>     immutable int x;
> }
> void main() {
>     auto data = [Foo(0)];
>     reduce!((a, b) => a)(data);
> }
> 
> 
> 
> DMD 2.063alpha gives:
> 
> ...\dmd2\src\phobos\std\algorithm.d(702): Error: cannot modify struct result
> Foo with immutable members
> ...\dmd2\src\phobos\std\algorithm.d(723): Error: template instance
> test.main.reduce!(__lambda3).reduce!(Foo,Foo[]) error instantiating
> test.d(7):        instantiated from here: reduce!(Foo[])
> test.d(7): Error: template instance test.main.reduce!(__lambda3).reduce!(Foo[])
> error instantiating

I think it is acceptable to require that whatever the type being reduced be assignable? It would be more friendly if it asserts though.
Comment 3 monarchdodra 2014-02-25 12:29:47 UTC
(In reply to comment #1)
> Using DMD32 v2.061 on Windows 32bit, below doesn't work too.
> I think this is the same issue:
> -----
> import std.stdio;
> import std.algorithm : sort;
> 
> struct S
> {
>     immutable int x;
> }
> 
> void main()
> {
>     auto arr = [S(0), S(2), S(1)];
>     sort!((a, b) => a.x < b.x)(arr);
>     arr.writeln();
> }
> -----

Indeed. But in this case, `arr` is *simply* not sortable: Not without mutating the immutable.

This is fixed now though:
Error: template std.algorithm.sort cannot deduce function from argument types !((a, b) => a.x < b.x)(S[])
Comment 4 monarchdodra 2014-03-31 06:17:15 UTC
Yes, I think this is invalid, because the documentation states:
//----
Then, for each element $(D x) in $(D range), $(D result = fun(result, x)) gets evaluated.
//----

And here, the type is not assignable, even when unqualed.

That said, a recursive "divide and conquer" fold could support such a case. I'm leaving this open as en ER.
Comment 5 dlangBugzillaToGithub 2024-12-01 16:17:22 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/9970

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB