D - [bug] line number in error message
- J C Calvarese (14/14) Mar 13 2004 Walter,
- Andrew Edwards (19/20) Mar 14 2004 I forget the reason why this is not authorized, but I rationalize it
- J C Calvarese (13/40) Mar 14 2004 I know it's not allowed. My purpose for the bug report is to get the
- Andrew Edwards (6/43) Mar 14 2004 This is a special case that can be handled much like the general case is...
- larry cowan (5/25) Mar 14 2004 It would seem that this is similar to an overloaded assignment operator ...
- Andrew Edwards (12/50) Mar 14 2004 .length is a member variable (property) of type uint. the ++ operator
- larry cowan (10/62) Mar 14 2004 Why should you be able to directly modify a property of an array? It re...
- Andrew Edwards (44/128) Mar 14 2004 The terms "directly modify" appears to mean two completely different
- Andrew Edwards (8/45) Mar 14 2004 One last thing... (pardon my spellings and gramatical errors)
- Manfred Nowak (14/18) Mar 15 2004 Not agreed. Because making a dynamic array longer is an expensive
- Scott Wood (10/18) Mar 16 2004 What about making "capacity" a separate property from "length", where
- J C Calvarese (12/35) Mar 16 2004 If you want a "capacity" for performance reasons, it's been suggested
- Ben Hinkle (14/21) Mar 16 2004 I wonder how/if this trick actually works since setting the length
- J C Calvarese (8/38) Mar 16 2004 I have no idea. I've never checked it. We were discussing the need for a...
- Ben Hinkle (24/24) Mar 16 2004 begin 644 lengthtest.d
- Matthew (7/25) Mar 17 2004 wrote:
- Scott Wood (49/54) Mar 17 2004 Why? Make growing array slices illegal without copying first.
- Ben Hinkle (26/81) Mar 17 2004 I'd expect the capacity to be write-only and be a minimum bound.
- Scott Wood (15/39) Mar 18 2004 Sounds like it could make for some fun behavior when code that used
- Manfred Nowak (39/40) Mar 15 2004 [...]
Walter, Genn Lewis has pointed out to me that this erroneous code produces an error message, but it leaves out the line number. Obviously, it would be helpful to new and existing users alike if the offending line number is included. void main() { char[] s; s.length++; // 's.length' is not an lvalue } Thanks. -- Justin http://jcc_7.tripod.com/d/
Mar 13 2004
On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself. If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...] They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint. Andrew -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Mar 14 2004
Andrew Edwards wrote:On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:I know it's not allowed. My purpose for the bug report is to get the line number included in the error message. It'd be helpful for newbies and anyone else who hasn't heard of this little oddity. Of course, if that code could be allowed that would be even better in my opinion. I forget the reason, too, but I know there's a reason.s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself.If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...]I agree.They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint.I think the reason has do with trying to use it in a slice: s[0..s.length++] Unknowable weirdness would happen behind the scenes, I suppose.Andrew-- Justin http://jcc_7.tripod.com/d/
Mar 14 2004
On Sun, 14 Mar 2004 14:31:11 -0600, J C Calvarese <jcc7 cox.net> wrote:Andrew Edwards wrote:This is a special case that can be handled much like the general case is currently handled; simply disallow the use of -- and ++ over slices. I don't know of any other usage that could cause a problem.On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:I know it's not allowed. My purpose for the bug report is to get the line number included in the error message. It'd be helpful for newbies and anyone else who hasn't heard of this little oddity. Of course, if that code could be allowed that would be even better in my opinion. I forget the reason, too, but I know there's a reason.s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself.If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...]I agree.They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint.I think the reason has do with trying to use it in a slice: s[0..s.length++] Unknowable weirdness would happen behind the scenes, I suppose.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Andrew
Mar 14 2004
It would seem that this is similar to an overloaded assignment operator which knows that the corresponding array must be adjusted, whereas the ++ (and others) operator doesn't know anything about the underlying array - thus its a non-lvalue which is especially recognized by "=". In article <opr4vasfyhs6zaqn news.digitalmars.com>, Andrew Edwards says...On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself. If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...] They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint. Andrew -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Mar 14 2004
On Sun, 14 Mar 2004 20:36:25 +0000 (UTC), larry cowan <larry_member pathlink.com> wrote:It would seem that this is similar to an overloaded assignment operator which knows that the corresponding array must be adjusted, whereas the ++ (and others) operator doesn't know anything about the underlying array - thus its a non-lvalue which is especially recognized by "="..length is a member variable (property) of type uint. the ++ operator already knows how to manipulate it. uint mylength; mylength++; // mylength = 1 mylength--; // mylength = 0 Maybe I'm missing the point, but I'm cannot understand what else the operator needs to know in order to manipulate a variable of integral type (i.e. int, uint, short, etc...).In article <opr4vasfyhs6zaqn news.digitalmars.com>, Andrew Edwards says...-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself. If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...] They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint. Andrew -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Mar 14 2004
In article <opr4vdw6lds6zaqn news.digitalmars.com>, Andrew Edwards says...On Sun, 14 Mar 2004 20:36:25 +0000 (UTC), larry cowan <larry_member pathlink.com> wrote:Why should you be able to directly modify a property of an array? It requires a reset (clip or reallocate) of the array itself, so the operation must be recognized as such. It is just a supplied convenience that assigning a length to a dynamic array is the method of specifying its (max)size. There is no reason why you should be able to use "++" or "--" which are different operations than assignment entirely. Calling it not-an-lvalue means that in the normal case it cannot be used on the left (the "to" operand) of a statement. In this case a value can be assigned to it - which allocates the array - but it cannot be otherwise modified.It would seem that this is similar to an overloaded assignment operator which knows that the corresponding array must be adjusted, whereas the ++ (and others) operator doesn't know anything about the underlying array - thus its a non-lvalue which is especially recognized by "="..length is a member variable (property) of type uint. the ++ operator already knows how to manipulate it.uint mylength; mylength++; // mylength = 1 mylength--; // mylength = 0 Maybe I'm missing the point, but I'm cannot understand what else the operator needs to know in order to manipulate a variable of integral type (i.e. int, uint, short, etc...).In article <opr4vasfyhs6zaqn news.digitalmars.com>, Andrew Edwards says...-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself. If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...] They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint. Andrew -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Mar 14 2004
On Sun, 14 Mar 2004 22:11:55 +0000 (UTC), larry cowan <larry_member pathlink.com> wrote:In article <opr4vdw6lds6zaqn news.digitalmars.com>, Andrew Edwards says...The terms "directly modify" appears to mean two completely different things for you and I. In my mind, to direct modify a variable is to explicitly change its value. This means that: s.length = 10; s.length++; are both means of "directly" affecting change to the value of length. My position is that if this form (first example) of "direct modification" is authorized, then why not allow all other forms of direct modification? Why allow some forms and prevent others? If we are not change some something "directly", then make it so. I'm quite positive that the .length property can be defined to grow and shrink dinamically (as is already the case). As a matter of fact, I personally favor a dynamic array (i.e. char[], int[], unit[], etc...) whose length property can only be implicitly modified by assigning a value larger/smaller than its current value or explicitly decreased with with --; Examples: char[] str; // str.length = 0 str = "information" // str.length = 11, str = "information" str = str[2..str.length]; // str.length = 9, str = "formation" str.length++; // illegal str.length = 10; // illegal str.length--; // str.length = 8, str = "formatio" str = ""; // OK, str.length = 0 This can prove quite helpful with implementing a stack or queue. class stack { char[][] stackmember; void push(char[] str){stackmember ~= str;} void pop(){stackmember--;} // LIFO ... } class queue { char[][] queuemember; void enqueue(char[] str){queuemember = str ~ queuemember;} void dequeue(){queuemember--}; // FIFO ... } Apart from these, I find little reasons to directly modify the length of a dynamic array. I find absolutely no reason for explicitly lengthen a dynamic array. Maybe someone else can provide an argument in favor of (I personally am against) it.On Sun, 14 Mar 2004 20:36:25 +0000 (UTC), larry cowan <larry_member pathlink.com> wrote:Why should you be able to directly modify a property of an array? ItIt would seem that this is similar to an overloaded assignment operator which knows that the corresponding array must be adjusted, whereas the ++ (and others) operator doesn't know anything about the underlying array - thus its a non-lvalue which is especially recognized by "="..length is a member variable (property) of type uint. the ++ operator already knows how to manipulate it.requires a reset (clip or reallocate) of the array itself, so the operation must be recognized as such. It is just a supplied convenience that assigning a length to a dynamic array is the method of specifying its (max)size. There is no reason why you should be able to use "++" or "--" which are different operations than assignment entirely. Calling it not-an-lvalue means that in the normal case it cannot be used on the left (the "to" operand) of a statement. In this case a value can be assigned to it - which allocates the array - but it cannot be otherwise modified.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/uint mylength; mylength++; // mylength = 1 mylength--; // mylength = 0 Maybe I'm missing the point, but I'm cannot understand what else the operator needs to know in order to manipulate a variable of integral type (i.e. int, uint, short, etc...).In article <opr4vasfyhs6zaqn news.digitalmars.com>, Andrew Edwards says...-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/On Sat, 13 Mar 2004 14:57:08 -0600, J C Calvarese <jcc7 cox.net> wrote:s.length++; // 's.length' is not an lvalueI forget the reason why this is not authorized, but I rationalize it myself. If I can do this: s.length = s.length + 1; s.length = s.length - 1; s.length = 0; Then why on earth wouldn't I be allowed to do this: s.length++; s.length--; s.length += 1; s.length -= 1; [etc...] They are all means to the same end. The .length property is simply a uint variable. As such, it should be able to be modified like any other variable of type uint. Andrew -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Mar 14 2004
On Sun, 14 Mar 2004 22:15:43 -0500, Andrew Edwards <remove_ridimz remove_yahoo.com> wrote:The terms "directly modify" appears to mean two completely different things for you and I. In my mind, to direct modify a variable is to explicitly change its value. This means that: s.length = 10; s.length++; are both means of "directly" affecting change to the value of length. My position is that if this form (first example) of "direct modification" is authorized, then why not allow all other forms of direct modification? Why allow some forms and prevent others? If we are not change some something "directly", then make it so. I'm quite positive that the .length property can be defined to grow and shrink dinamically (as is already the case). As a matter of fact, I personally favor a dynamic array (i.e. char[], int[], unit[], etc...) whose length property can only be implicitly modified by assigning a value larger/smaller than its current value or explicitly decreased with with --; Examples: char[] str; // str.length = 0 str = "information" // str.length = 11, str = "information" str = str[2..str.length]; // str.length = 9, str = "formation" str.length++; // illegal str.length = 10; // illegal str.length--; // str.length = 8, str = "formatio" str = ""; // OK, str.length = 0 This can prove quite helpful with implementing a stack or queue. class stack { char[][] stackmember; void push(char[] str){stackmember ~= str;} void pop(){stackmember--;} // LIFO ... } class queue { char[][] queuemember; void enqueue(char[] str){queuemember = str ~ queuemember;} void dequeue(){queuemember--}; // FIFO ... }One last thing... (pardon my spellings and gramatical errors) Because my desire for "--" only exist for these specific cases and can be easily satisfied with array slicing, I don't find it that important and can easily do without. Which is to say that I would readily support the decision to prevent all direct modifications to the .length property. Andrew
Mar 14 2004
Andrew Edwards wrote: [...]str = ""; // OK, str.length = 0Not agreed. Because making a dynamic array longer is an expensive operation any shortening should be mentioned explicitely. Except there is no actually returning of memory to a freeb list or the underlying os. [...]I find absolutely no reason for explicitly lengthen a dynamic array. Maybe someone else can provide an argument in favor of (I personally am against) it.[...] The reason is very simple: increasing the length of a dynamic array is expensive and I think you know the reasons for this expensiveness. Because of this expensiveness the requirement of explicitely mentioning a wanted lenghtening is justified. Remember also, that preallocating a big chunk of memory is more efficient than allocating several smaller pieces. So long!
Mar 15 2004
On Mon, 15 Mar 2004 13:33:19 +0100, Manfred Nowak <svv1999 hotmail.com> wrote:The reason is very simple: increasing the length of a dynamic array is expensive and I think you know the reasons for this expensiveness. Because of this expensiveness the requirement of explicitely mentioning a wanted lenghtening is justified. Remember also, that preallocating a big chunk of memory is more efficient than allocating several smaller pieces.What about making "capacity" a separate property from "length", where the former refers to the allocated storage and the latter refers to the number of currently valid elements? This way, you don't need to worry about filling in default initializers when allocating more capacity, and bounds checking would work on the actual number of used elements. The downside would be the need to store two values for each array, but that buys you saner array behavior. -Scott
Mar 16 2004
Scott Wood wrote:On Mon, 15 Mar 2004 13:33:19 +0100, Manfred Nowak <svv1999 hotmail.com> wrote:If you want a "capacity" for performance reasons, it's been suggested before (last time it was called ".reserve"). I was in favor of it until Walter mentioned this trick: "After setting .length to the max reasonable size, then set .length back to zero. You now have a reserve that is something like the max reasonable size rounded up to the next bucket size." (http://www.digitalmars.com/drn-bin/wwwnews?D/17688) More tricks are here: http://www.wikiservice.at/d/wiki.cgi?FaqRoadmap -- Justin http://jcc_7.tripod.com/d/The reason is very simple: increasing the length of a dynamic array is expensive and I think you know the reasons for this expensiveness. Because of this expensiveness the requirement of explicitely mentioning a wanted lenghtening is justified. Remember also, that preallocating a big chunk of memory is more efficient than allocating several smaller pieces.What about making "capacity" a separate property from "length", where the former refers to the allocated storage and the latter refers to the number of currently valid elements? This way, you don't need to worry about filling in default initializers when allocating more capacity, and bounds checking would work on the actual number of used elements. The downside would be the need to store two values for each array, but that buys you saner array behavior. -Scott
Mar 16 2004
If you want a "capacity" for performance reasons, it's been suggested before (last time it was called ".reserve"). I was in favor of it until Walter mentioned this trick: "After setting .length to the max reasonable size, then set .length back to zero. You now have a reserve that is something like the max reasonable size rounded up to the next bucket size." (http://www.digitalmars.com/drn-bin/wwwnews?D/17688)I wonder how/if this trick actually works since setting the length back to zero nulls out the data pointer which leaves the old "reserve" to be garbage collected. The next time the length is set it looks on the free list and the reserve will only be on the free list (first of all it might be on the wrong free list if the reserve size is significantly different than the requested length) after a garbage collect. I can see how it works if the length is set back to, say, 1. In that case the data pointer is not released. The key routine I'm looking at is _d_arraysetlength in src/phobos/internal/gc/gc.d This shouldn't be too hard to test using gcstats. I've attached a small test file to show what I mean. -Ben
Mar 16 2004
Ben Hinkle wrote:I have no idea. I've never checked it. We were discussing the need for a "reserve" and suddenly Walter chimes in with what he says will already work. I thought the issue was moot. But if this method doesn't work, then that might change everything...If you want a "capacity" for performance reasons, it's been suggested before (last time it was called ".reserve"). I was in favor of it until Walter mentioned this trick: "After setting .length to the max reasonable size, then set .length back to zero. You now have a reserve that is something like the max reasonable size rounded up to the next bucket size." (http://www.digitalmars.com/drn-bin/wwwnews?D/17688)I wonder how/if this trick actually workssince setting the length back to zero nulls out the data pointer which leaves the old "reserve" to be garbage collected. The next time the length is set it looks on the free list and the reserve will only be on the free list (first of all it might be on the wrong free list if the reserve size is significantly different than the requested length) after a garbage collect. I can see how it works if the length is set back to, say, 1. In that case the data pointer is not released. The key routine I'm looking at is _d_arraysetlength in src/phobos/internal/gc/gc.d This shouldn't be too hard to test using gcstats. I've attached a small test file to show what I mean. -Ben-- Justin http://jcc_7.tripod.com/d/
Mar 16 2004
begin 644 lengthtest.d M<')I;G1F*")P;V]L("5U('5S960 )74 9G)E92`E=2!F<F5E;&ES="`E=2!P M86=E("5U7&XB+`T*"2` <W1A=',N<&]O;'-I>F4L<W1A=',N=7-E9'-I>F4L M<W1A=',N9G)E96)L;V-K<RP-" D ('-T871S+F9R965L:7-T<VEZ92QS=&%T M<RYP86=E8FQO8VMS*3L-" T*("` :6YT6UT >#L-"B` (' N;&5N9W1H(#T M;"`E=2!U<V5D("5U(&9R964 )74 9G)E96QI<W0 )74 <&%G92`E=5QN(BP- M" D ('-T871S+G!O;VQS:7IE+'-T871S+G5S961S:7IE+'-T871S+F9R965B M=F5R<VEO;B`H4T547UI%4D\I('L-" D >"YL96YG=& /2`P.PT*("` ("` M=%-T871S*'-T871S*3L-"B` ("` ('!R:6YT9B B<&]O;"`E=2!U<V5D("5U M(&9R964 )74 9G)E96QI<W0 )74 <&%G92`E=5QN(BP-" D ("` ('-T871S ` end
Mar 16 2004
"Scott Wood" <nospam buserror.net> wrote in message news:slrnc5efdi.3af.nospam aoeu.buserror.net...On Mon, 15 Mar 2004 13:33:19 +0100, Manfred Nowak <svv1999 hotmail.com>wrote:It complicates slicing enormously, and will also likely impact on performance. I think it's got to stay as it is because slicing, as implemented in D, is such a huge win.The reason is very simple: increasing the length of a dynamic array is expensive and I think you know the reasons for this expensiveness. Because of this expensiveness the requirement of explicitely mentioning a wanted lenghtening is justified. Remember also, that preallocating a big chunk of memory is more efficient than allocating several smaller pieces.What about making "capacity" a separate property from "length", where the former refers to the allocated storage and the latter refers to the number of currently valid elements? This way, you don't need to worry about filling in default initializers when allocating more capacity, and bounds checking would work on the actual number of used elements.The downside would be the need to store two values for each array, but that buys you saner array behavior. -Scott
Mar 17 2004
On Wed, 17 Mar 2004 12:34:38 -0000, Matthew <matthew stlsoft.org> wrote:"Scott Wood" <nospam buserror.net> wrote in message news:slrnc5efdi.3af.nospam aoeu.buserror.net...[snip]What about making "capacity" a separate property from "length",It complicates slicing enormously,Why? Make growing array slices illegal without copying first. At worst, you'll get undefined behavior if you do it. You could also set the slice's capacity to zero, and throw an exception if the user tries to grow an array with zero capacity and non-zero length. You wouldn't be able to grow back to the original slice size, but would you be legally able to do so (and recover the original elements) currently? I'd think it'd be bad programming practice to assume that the array you've been given is a slice that you can shrink and regrow without losing data, even if it is legal. What would currently happen if you try to grow a slice past its original size? On a somewhat tangential note, non-slicing reference assignments seem a little vague too. Code that strictly adheres to copy-on-write wouldn't be a problem, but what about code that does this: char[] a, b; a.length = 10; <fill in values in a> b = a; b.length = 20; // b was unable to grow in place, and thus was copied <fill in values in b> Does a see the changes in b? As I understand it, the current answer is no, but would have been yes if b were able to grow in place. Some sort of true reference array type might be nice, where length (and capacity, if any) are pointed to rather than copied around. I suppose one could make a custom struct for it (and arrays with capacity, for that matter), but still... You could then make resizing non-slice assigned arrays illegal as well. What about function parameters? Does inout apply to the contents of an array, or the pointer/length combo itself?and will also likely impact on performance.It'll take slightly longer for things like assigning an array (one more word to copy), but growing arrays would be faster when doing a simple concatenation loop (and IMHO it's better to keep implementation details such as resizing policy out of the way when possible, so that the important stuff is more visible). It'd probably be faster than setting length up and then back down again as well, as I imagine the latter option requires calls into the allocator each time you increase length to determine if you really do need to grow the allocation. The alternative to both of the above is set length high and leave it there, keeping track of the actual end-of-array yourself (as the D spec's example code does), but that's rather ugly, and you lose full bounds checking. It also isn't going to be any faster (assuming the compiler implements a sane growth strategy; if the allocator rounds up to power-of-two, then the compiler could do the same when deciding how much to bump capacity when it's exceeded), except for the one-word-copy hit in assigning arrays. -Scott
Mar 17 2004
On Thu, 18 Mar 2004 01:09:34 +0000 (UTC), Scott Wood <nospam buserror.net> wrote:On Wed, 17 Mar 2004 12:34:38 -0000, Matthew <matthew stlsoft.org> wrote:I'd expect the capacity to be write-only and be a minimum bound. So setting the capacity to n means "this array should make space for at least n elements". That would be equivalent to setting the length to n and back as long as phobos changes to make that actually work."Scott Wood" <nospam buserror.net> wrote in message news:slrnc5efdi.3af.nospam aoeu.buserror.net...[snip]What about making "capacity" a separate property from "length",It complicates slicing enormously,Why? Make growing array slices illegal without copying first. At worst, you'll get undefined behavior if you do it. You could also set the slice's capacity to zero, and throw an exception if the user tries to grow an array with zero capacity and non-zero length.You wouldn't be able to grow back to the original slice size, but would you be legally able to do so (and recover the original elements) currently? I'd think it'd be bad programming practice to assume that the array you've been given is a slice that you can shrink and regrow without losing data, even if it is legal. What would currently happen if you try to grow a slice past its original size?The section on the length property says growing a slice that starts in the middle of a gc block copies always. Growing a slice that starts at the head of a gc block (ie - index 0) reallocates if the new size is longer than the space allocated.On a somewhat tangential note, non-slicing reference assignments seem a little vague too. Code that strictly adheres to copy-on-write wouldn't be a problem, but what about code that does this: char[] a, b; a.length = 10; <fill in values in a> b = a; b.length = 20; // b was unable to grow in place, and thus was copied <fill in values in b> Does a see the changes in b? As I understand it, the current answer is no, but would have been yes if b were able to grow in place.That's right - the examples in the section about setting the length property talk about this. It would be nice to document copy-on-write in more places than just the string module.Some sort of true reference array type might be nice, where length (and capacity, if any) are pointed to rather than copied around. I suppose one could make a custom struct for it (and arrays with capacity, for that matter), but still... You could then make resizing non-slice assigned arrays illegal as well. What about function parameters? Does inout apply to the contents of an array, or the pointer/length combo itself?inout applies to the pointer/length combo. If you change the length of the parameter it changes the length of the original variable passed in to the function.Looking at src/phobos/internal/gc/gcx.d the function size_t capacity(void*p) uses a cache so if you are increasing the length in a loop it caches the last lookup so it is fast. If you increase the length of multiple arrays in a loop then it will have to call findSize to do more work. I don't know if it is faster to compute the capacity like this or store the capacity in the array structure together with the length. It would also depend on the GC implementation.and will also likely impact on performance.It'll take slightly longer for things like assigning an array (one more word to copy), but growing arrays would be faster when doing a simple concatenation loop (and IMHO it's better to keep implementation details such as resizing policy out of the way when possible, so that the important stuff is more visible). It'd probably be faster than setting length up and then back down again as well, as I imagine the latter option requires calls into the allocator each time you increase length to determine if you really do need to grow the allocation.The alternative to both of the above is set length high and leave it there, keeping track of the actual end-of-array yourself (as the D spec's example code does), but that's rather ugly, and you lose full bounds checking. It also isn't going to be any faster (assuming the compiler implements a sane growth strategy; if the allocator rounds up to power-of-two, then the compiler could do the same when deciding how much to bump capacity when it's exceeded), except for the one-word-copy hit in assigning arrays. -Scott
Mar 17 2004
On Wed, 17 Mar 2004 22:42:31 -0500, Ben Hinkle <bhinkle4 juno.com> wrote:On Thu, 18 Mar 2004 01:09:34 +0000 (UTC), Scott Wood <nospam buserror.net> wrote:Sounds like it could make for some fun behavior when code that used to get a slice starts getting passed a whole array (or a slice at the beginning)...What would currently happen if you try to grow a slice past its original size?The section on the length property says growing a slice that starts in the middle of a gc block copies always. Growing a slice that starts at the head of a gc block (ie - index 0) reallocates if the new size is longer than the space allocated.Doh... I'm not entirely sure how I missed that. :-PDoes a see the changes in b? As I understand it, the current answer is no, but would have been yes if b were able to grow in place.That's right - the examples in the section about setting the length property talk about this.It seems a little asymmetric to be able to create such a reference through parameter passing but not by assignement...What about function parameters? Does inout apply to the contents of an array, or the pointer/length combo itself?inout applies to the pointer/length combo. If you change the length of the parameter it changes the length of the original variable passed in to the function.Looking at src/phobos/internal/gc/gcx.d the function size_t capacity(void*p) uses a cache so if you are increasing the length in a loop it caches the last lookup so it is fast.Hmm... In that case, there's not much need to carry it around in the array. Plus, a sufficiently optimizing compiler could cache the capacity on its own within the loop. BTW, there doesn't appear to be any synchronization in GC.capacity, so a thread could update the cache between when another thread reads p_cache and size_cache. If thread local storage is supported, this seems like an appropriate place to use it. -Scott
Mar 18 2004
Andrew Edwards wrote: [...]The .length property is simply a uint variable.[...] Not agreed. It is a property and therefore should be interpreted as an overloaded function to be consistent to the properties of structs and classes which _are_ functions. Did you notice that D also has module properties? private int num; public void f(int num){ .num=num;} // do not shout at me, that this is public int f(){ return num;} // example is somehow senseless void main(){ f++; // error: 'f' is not a scalar, it is a void(int num) f=f+1; // compiles okay } The error message is quite okay, because `f++' is equivalent to `f=f+1' and therefore the `(int)' overload is needed first, or because the `(int)' overload appears lexically first. D can however be made such that properties are treated as variables. Because of the syntactical equvivalence of properties to variables, this is recommended. But then D is at the point that also classes and structs, that have overloaded opCalls should be treated as variables, thereby imposing an ambiguity in the language: class C{ private int num; void opCall( int num1){ num= num1;} int opCall( return num;} private int foo, bar; .... } C foo, bar; .... foo= bar; What is meant by the assignment `foo= bar;'? Is only the value of `foo.num' changed to the value of `bar.num', beacuase the overloaded opCalls are called, or are all inetrnal values of `foo' set to the values `bar', because the calls variables are assigned? So long!
Mar 15 2004