Comment #0 by bearophile_hugs — 2011-07-18T12:15:46Z
Currently (DMD 2.054) this is not allowed, but a vector op like this is sometimes useful to me:
struct Foo {
int x, y;
int[100] array;
}
void main() {
auto foos = new Foo[100];
foos[].y += 10; // ********
}
For the programmer I think the meaning of such code is easy enough to understand and use.
At the moment I don't see the need to define a operator overload for this too (I mean something like opSliceUnary).
Don notes:
> An interesting use case:
> void main()
> {
> cdouble[100] foos;
> foos[].re = 5.0;
> }
Wilfried Kirschenmann suggests:
> void main() {
> auto foos = new Foo[100];
> auto ints = new int[100]
> ints = foos[].y;
> }
>
> This would simplify the wrinting of numerous application, especially
> in the writing of image/video processing (eg. rgb2yuv conversions)
> This would also simplify the writing of template library transforming
> "array of struct" to "struct of arrays" in a transparent manner for
> the library user.
Andrej Mitrovic notes (I don't understand this):
> float[] buffers = malloc..;
> float*[] CBuffers = buffers[].ptr;
Comment #1 by kennytm — 2011-07-18T12:44:34Z
What if I define
ref int y(Foo[] f) {
return f[0].x;
}
?
Comment #2 by bearophile_hugs — 2011-07-27T13:56:06Z
Another possible purpose. Given this matrix:
auto M = new double[][](10, 20);
This:
M[][1] = 1.0;
Means:
foreach (row; p)
row[1] = 1.0;
This replaces some usages of std.range.transversal().
Comment #3 by clugdbug — 2011-07-28T00:36:12Z
All these operations require the use of strided slices, which would be a huge amount of work to implement. Also, there are a plethora of corner cases.
Comment #4 by bearophile_hugs — 2011-07-28T05:15:59Z
(In reply to comment #3)
> All these operations require the use of strided slices, which would be a huge
> amount of work to implement. Also, there are a plethora of corner cases.
I see. Those corner cases are bad. If you think this is too much work for the gain I'll close this enhancement request, to leave similar functionalities to matrix libraries.
Comment #5 by nick — 2023-07-05T13:52:44Z
List comprehensions would cover these and avoid any ambiguity. They are also more expressive and composable than vector ops:
> auto foos = new Foo[100];
> foos[].y += 10; // ********
[e.y += 10 for e in foos];
Note this doesn't need to allocate an array as the result is not used.
> cdouble[100] foos;
> foos[].re = 5.0;
[e.re = 5.0 for e in foos];
> auto foos = new Foo[100];
> auto ints = new int[100]
> ints = foos[].y;
ints = [e.y for e in foos];
> float[] buffers = malloc...;
> float*[] CBuffers = buffers[].ptr;
float*[] cBuffers = [e.ptr for e in buffers];
Also, type inference could be used `auto cBuffers = ` because the RHS is no longer ambiguous with `float*`.
(This would also solve Issue #2548).
> auto M = new double[][](10, 20);
> M[][1] = 1.0;
[e[1] = 1.0 for e in m];
And indexes mean they can cover vector ops too:
> a[] = b[] / c[];
a = [b[i] / e for i, e in c];
A benefit is that `b.length` can be larger than `c.length`.
Also we can use the index variable e.g. to index b in reverse order.
The key benefit however is that we can use expressions not supported by vector ops such as function calls, comparisons and the conditional operator - see issue #5636.
Comment #6 by nick — 2023-07-17T10:23:41Z
A less drastic change would be this syntax, which also solves the ambiguities:
float*[] CBuffers = buffers[#].ptr;
m[#][1] = 1.0;
c[#] = a[#] < b[#]; // issue #5636
Note: issue #5636 was fixed by simply documenting that comparisons, equality, etc make the operation not a vector op, just an array comparison.
Comment #7 by robert.schadek — 2024-12-13T17:55:49Z