Bug 13981 – std.algorithm: inconsistent handling of static arrays

Status
NEW
Severity
enhancement
Priority
P4
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2015-01-14T20:47:41Z
Last change time
2024-12-01T16:23:36Z
Assigned to
No Owner
Creator
mfx
Moved to GitHub: phobos#10111 →

Comments

Comment #0 by markus — 2015-01-14T20:47:41Z
I'd guess this is a typical D newcomer issue as static arrays - are passed by value - are allocated on the stack (unless global) - are not real ranges because they lack popFront() Unfortunately I had to dig through various bugreports at issues.dlang.org before better understanding this issue, so I'd suggest adding a short comment to algorithms.d. In any case it's confusing that reduce() seems to work for static arrays while sum() does not. // dmd 2.066.1 import std.algorithm; void test_dynamic_array() { int[] arr1 = [1, 2, 3, 4, 5]; immutable int[] arr2 = [1, 2, 3, 4, 5]; filter!"a & 1"(arr1); // OK map!"a + 10"(arr1); // OK reduce!"a + b"(arr1); // OK sum(arr1); // OK filter!"a & 1"(arr2); // OK map!"a + 10"(arr2); // OK reduce!"a + b"(arr2); // OK sum(arr2); // OK } void test_static_array() { int[5] arr1 = [1, 2, 3, 4, 5]; static immutable int[5] arr2 = [1, 2, 3, 4, 5]; //filter!"a & 1"(&arr1); // Error: won't compile //map!"a + 10"(arr1); // Error: won't compile reduce!"a + b"(arr1); // OK ! //sum(arr1); // Error: won't compile //filter!"a & 1"(arr2); // Error: won't compile //map!"a + 10"(arr2); // Error: won't compile //reduce!"a + b"(arr2); // Error: won't compile ??? //sum(arr2); // Error: won't compile }
Comment #1 by markus — 2015-01-14T20:49:32Z
As metaprogramming in D is so much fun (esp. when coming from C++), I've hacked together some experimental code. Remember that I'm a D newcomer, so please be gentle :-) // dmd 2.066.1 import std.algorithm, std.traits; private auto _rangeForStaticArray(R)(const ref R r) if (isStaticArray!R) { // pseudo code - no idea if it is possible to express hasHeapStorage!R or hasStackStorage!R // - could also test for immutable, but no sure if that's the correct semantics ? // - could also test for something like isGC!R ??? static if (1 || hasHeapStorage!R) { return r[]; // safe } else static if (hasStackStorage!R) { static assert(false, "stack storage for static array not allowed - pass a slice"); return r[]; // possibly unsafe ??? } else { static assert(false, "unknown storage for static array - pass a slice"); } } auto sum(R)(const ref R r) if (isStaticArray!R) { return std.algorithm.sum(_rangeForStaticArray(r)); } auto sum(R)(R r) if (!isStaticArray!R) { return std.algorithm.sum(r); } void test_dynamic_array() { int[] arr1 = [1, 2, 3, 4, 5]; immutable int[] arr2 = [1, 2, 3, 4, 5]; sum(arr1); // OK sum(arr2); // OK } void test_static_array() { int[5] arr1 = [1, 2, 3, 4, 5]; immutable int[5] arr2 = [1, 2, 3, 4, 5]; sum(arr1); // seems OK sum(arr2); // seems OK }
Comment #2 by issues.dlang — 2015-01-15T10:57:11Z
In general, I think that it's a big mistake for anything in std.algorinthm or any other range-based functions to support static arrays. If you want to pass a static array to a range-based functions, then you slice it, and you get a dynamic array, which _is_ a valid range. So, we either need to look at removing support for static arrays for any functions in std.algorithm which support them, or we need to explicitly document the cases where they are supported.
Comment #3 by jack — 2015-10-22T15:35:35Z
(In reply to Jonathan M Davis from comment #2) > So, we either need to look at removing support for static arrays for any > functions in std.algorithm which support them, or we need to explicitly > document the cases where they are supported. Removing support, even though it breaks something, would probably be the best option here. Supporting static arrays in any form in range based code is just confusing.
Comment #4 by bearophile_hugs — 2015-10-22T18:58:50Z
The compile-time knowledge of the length of an array is a very precious information, throwing this information away is foolish, especially when the array is short: int[3] a = [1, 10, 30]; immutable total = a.sum;
Comment #5 by robert.schadek — 2024-12-01T16:23:36Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/phobos/issues/10111 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB