[Issue 15582] Slice returned by opSlice() not accepted as lvalue

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Fri Jan 22 11:03:58 PST 2016


https://issues.dlang.org/show_bug.cgi?id=15582

--- Comment #5 from hsteoh at quickfur.ath.cx ---
I believe you're misunderstanding what opSlice() does.

Contrary to what you seem to be thinking, opSlice() is *not* used for
implementing slicing notation. That was an older usage that is now deprecated
(though still supported for backward compatibility); with Kenji's
multidimensional array PR merged, opSlice() is used for implementing "a .. b"
notation for user-defined types. The correct function to use for implementing
"x[]" is opIndex() (with zero arguments), not opSlice().

Secondly, you seem to be confusing array-copying notation with slicing
notation. When you write `x[] = 10;` it does NOT mean "assign 10 to a slice of
x", because that makes no sense (how do you assign a scalar to an array?). It's
actually a special notation meaning "do an array copy of 10 into x".

Your code example shows how your misunderstanding compounded with deprecated
opSlice usage to produce something that looks wrong, but actually is entirely
consistent with how the language works:

Firstly, `s[]` by default tries to invoke S.opIndex() (with no arguments), but
since this is not defined, it falls back to backward-compatible behaviour by
translating `s[]` into `s.opSlice()`.

Secondly, in opSlice()'s implementation, the notation `data[]` means "take a
slice of the static array `data`", IOW, "make a dynamic array that points to
the elements of the static data `data`".

So what is returned by opSlice is a dynamic array (that happens to point to the
elements of s.data). So what you end up with, is that the LHS of the assignment
is a dynamic array, and you're trying to assign the scalar 10 to it. This is,
of course, invalid.  (The compiler's error message is not helpful, though.)

Finally, when you write `s[][]`, it gets translated to `<<dynamic_array>>[]`,
which is special notation for array copying, which just so happens to be what
you intended from the beginning, but looks weird.

So what you're asking for, really, has nothing to do with *slicing*.  What
you're asking for is for user-defined types to support array-copying notation. 
Currently the way to do this is to implement opIndexAssign, as another
commenter has already noted above.

Part of your confusion may have arisen from the arguably unfortunate design
choice of overloading slicing notation with array-copying notation. It *looks*
like slicing but really isn't, as proven by the following example:

-----
int[] a = [1,2,3,4,5];
int[] b = [6,7,8,9,0];

a[0 .. 2] = b[3 .. 4]; // array copying notation

auto x = a[0 .. 2]; // slicing notation
auto y = b[3 .. 4]; // slicing notation
x = y; // ** N.B.: NOT the same thing as the array copying notation above!
-----

If the line marked "array copying notation" is really the same thing as
slicing, then the line "x = y" ought to overwrite the first two elements of a
with the last two elements of b. However, this is NOT what happens. Instead,
what does happen is that the dynamic array x is assigned to point to what y
points to. The underlying arrays a and b are unchanged.  Therefore, array
copying notation cannot be the same thing as slicing, in spite of all
appearances. Q.E.D.

--


More information about the Digitalmars-d-bugs mailing list