View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000572 | LDMud 3.6 | General | public | 2008-09-11 09:06 | 2022-10-06 20:48 |
Reporter | warp | Assigned To | Gnomi | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | duplicate | ||
Product Version | 3.3.717 | ||||
Summary | 0000572: Assigning empty array to array slice in functions | ||||
Description | The behaviour for assigning to arrays which are not explicitely passed by reference in functions is inconsistent. Assigning to a single element will modify the passed array, assigning to a slice will not modify it. Example: public void var1( mixed tmp) { tmp[0] = "test1"; } public void var2( mixed tmp) { tmp[0..0] = ({ "test2" }); } public void var3( mixed tmp) { tmp[0..0] = ({}); } All examples assume: mixed arr= ({ 1, 2, 3 }); var1(arr); // arr is now "element", 2, 3 var2(arr); // arr is now "test2", 2, 3 var3(arr); // arr is now still 1, 2, 3 Assigning the empty array to delete the first element is not possible in a function. It works though, if no function calls are involved: mixed arr= ({ 1, 2, 3 }); arr[0..0]= ({}); // arr is no 2, 3 It would be nice if this could be made consistent (so that assigning empty arrays works inside the function, too) as this would e.g. allow to create shift/unshift/push/pull simul efuns without the need for reference-syntax | ||||
Tags | No tags attached. | ||||
|
Ah, it seems variant2 only works because [0..0] is effectively treated like [0] - assigning non-empty arrays would still copy the array instead of modifying the original array for [0..1] So this probably is no bug but actually a feature request whether [start..end] could modify the original array, too, like [index] does, without explicit pass-by-reference |
|
Yes, thats right. Everytime a new array is created in the process, the original one will be left unchanged. And a new array is created every time the array changes its length... I am not sure if that is easily changeable by tuning the compiler and the implementation of the slicing operator - I guess not. There is a feature request to improve the array implementation in a way that length changes do not alway involve the creation of a new array. But then we may introduce a non-deterministic behaviour for the LPC programmer, if some length changes involve the creation of a new array and some not and something relies on it.. And additionally: I am very sceptical if we _should_ change this behaviour. Because it was the standard array behaviour for many years, wizards got used to expect it - in MorgenGrauen I know several pieces of old code, which actually use return arr[0..] to return a shallow copy instead of the original array... (I know, I know...) This is not like changing a rarely used efun or its interface, because the code will work and there will be no warning - but data corruption which may be difficult to detect and trace. |
|
For the record, it's resizing the array that causes the reference to "break", because the array is copied: tmp[0..1] = ({ 0, 1 }); // modifies the original array. tmp[0..1] = ({ 0, 1, 2 }); // creates a copy of the array. I agree with Zesstra that it's too late to change this behaviour. (If we wanted to change anything, I'd vote for slice assignments to always copy the array.) |
|
I tend towards Fuchur, but that will probably also break enough code, which now trust on the slicing operator _not_ to copy in some circumstances. Difficult... Im pretty sure, some people used it to save a bit of execution time (but it may not be that tiny in case of big arrays, if we change it...) I would not like to change all the tmp[0..1] = ({ 0, 1 }); |
|
I see, this is of course understandable. From a consistency point of view, a change in one direction or the other would be nice, but of course, with all the large codebases around, I see that it's not that easily changed. |
|
I am transfering this to 3.5, because I do really recommend not to change the behaviour in the one or other direction in 3.3. There will be enough code to break in nasty ways by this... |
|
Next step: Add pragma (default on) to warn when array operations (slice assignment, operator assignments) create a new array and the original array has more than one reference (i.e. when the behavior would be different with an array with pure reference semantics). Also warn on comparisons with the empty array (==, !=, member, in, -=, &=, mapping lookup). |
|
We are closing this issue because it is a duplicate of the older 0000299. We will check for the feasibility of a change of behaviour in 3.7 and follow-up with 0000299. |
Date Modified | Username | Field | Change |
---|---|---|---|
2008-09-11 09:06 | warp | New Issue | |
2008-09-11 09:33 | warp | Note Added: 0000783 | |
2009-01-18 14:05 | zesstra | Note Added: 0000929 | |
2009-01-18 15:42 | fufu | Note Added: 0000930 | |
2009-01-18 16:56 | zesstra | Note Added: 0000931 | |
2009-01-19 05:21 | warp | Note Added: 0000932 | |
2009-05-10 15:37 | zesstra | Note Added: 0001098 | |
2009-05-10 15:37 | zesstra | Project | LDMud 3.3 => LDMud 3.5 |
2018-01-29 22:29 | zesstra | Project | LDMud 3.5 => LDMud 3.6 |
2018-01-29 22:29 | zesstra | Category | LPC Language => General |
2018-02-04 00:19 | Gnomi | Relationship added | duplicate of 0000299 |
2022-10-06 20:30 | Gnomi | Assigned To | => Gnomi |
2022-10-06 20:30 | Gnomi | Status | new => assigned |
2022-10-06 20:30 | Gnomi | Note Added: 0002700 | |
2022-10-06 20:36 | Gnomi | Note Edited: 0002700 | |
2022-10-06 20:48 | zesstra | Status | assigned => closed |
2022-10-06 20:48 | zesstra | Resolution | open => duplicate |
2022-10-06 20:48 | zesstra | Note Added: 0002701 |