May 30, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 05/30/2013 10:38 AM, Steven Schveighoffer wroten :> On Thu, 30 May 2013 13:33:31 -0400, Ali Çehreli <acehreli@yahoo.com> wrote: > >> They are not dynamic in the sense that they are on the heap. (Both >> your and my examples have trivially shown that.) > > Dynamic arrays themselves do not have to be allocated on the heap. My wording have been off this morning. I meant what you said. Ali |
May 30, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On 05/30/2013 10:56 AM, Maxim Fomin wrote: > Really it is repetition of banana example. Mmm... Chocolate sauce over a banana slice would be pretty good now. :p Ali |
May 30, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On 5/30/13 1:44 PM, Maxim Fomin wrote:
> On Thursday, 30 May 2013 at 17:09:05 UTC, Steven Schveighoffer wrote:
>> On Thu, 30 May 2013 12:56:46 -0400, Steven Schveighoffer
>> <schveiguy@yahoo.com> wrote:
>>
>>> On Thu, 30 May 2013 12:46:39 -0400, Maxim Fomin
>>> <maxim@maxim-fomin.ru> wrote:
>>>
>>>> Please provide reasons why it is wrong (but without explanation how
>>>> druntime allocates memory which is irrelevant).
>>>
>>> It's wrong in that D's spec re-defines dynamic arrays from the
>>> traditional definition (I think for the sake of simplicity, but I
>>> didn't write the definition, so I'm not sure). D's slices aren't
>>> dynamic arrays, no matter how many specs say so.
>>
>> Oh, you were looking for an actual *functional* differences between
>> slices and dynamic arrays.
>>
>>
>> -Steve
>
> I was looking for explanation why after years of stable array definition
> one article abolish official spec (without changing it) and major
> implementation without any Walter or Andrei approval. I got an answer in
> previous comment but found it unsatisfactory: simply because somebody
> considers that D definitions contradict to some external notions is not
> a reason to change it. There are other places in D which do not
> correspond with names in other languages or with general terms. Also,
> there is as much opinions, as much people, so moving language toward
> some external definition is a problematic task.
>
> It would be good if Walter or Andrei comment on this.
Not sure I understand the context.
Andrei
|
May 30, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Thursday, May 30, 2013 16:15:36 Andrei Alexandrescu wrote:
> > It would be good if Walter or Andrei comment on this.
>
> Not sure I understand the context.
The D spec uses the terms dynamic array and slice interchangeably. TDPL and Phobos do the same. However, Steven has argued that using the term dynamic array for a slice is incorrect and goes against how the term is normally defined in computer science, because dynamic arrays own their memory, and slices don't. So, in his article on arrays which is on dlang.org, he basically uses the CS terminology and says that the spec is incorrect in calling T[] a dynamic array.
Some people around here (like Steven) are of the opinion that the spec is wrong in calling T[] a dynamic array (as it doesn't own its memory like a dynamic array would per CS). Others (like Maxim) are arguing in favor of the spec or at least that people should be using terms that follow the spec rather than trying to claim that T[] is not actually a dynamic array and that the dynamic array is the runtime-owned memory and T[] is merely a slice to it (in which case, D technically wouldn't even have dynamic arrays except as an implementation detail of druntime).
So, Maxim wants clarification from you and/or Walter on what the correct meaning for dynamic array is - is T[] both a dynamic array and a slice, or is the dynamic array only the chunk of memory owned by druntime, and T[] is only a slice? Maxim started the "Dynamic array and slices (need Walter and Andrei decision)" thread in order to try and get that clarification.
- Jonathan M Davis
|
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 30/05/13 16:21, Ali Çehreli wrote:
> On 05/29/2013 06:54 PM, Peter Williams wrote:
> > I find the mechanism described in the article a little disconcerting and
> > it certainly needs more publicity as it's a bug in waiting for the
> > unwary.
>
> It certainly is disconcerting. Performance have played a big role in the
> current semantics of slices.
I should have added that it was the non determinism that disconcerted me. It doesn't really affect me personally as a programmer now that I know about it as I can just avoid it. But it blows out of the water any hopes of having "proveably correct" non trivial code.
Peter
|
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 30/05/13 16:21, Ali Çehreli wrote:
> On 05/29/2013 06:54 PM, Peter Williams wrote:
> > Wouldn't a better rule for pass by value be that any changes to
> > the data part of the array (including assignment to an element) causes
> > reallocation of the entire data portion.
>
> The type of a slice parameter is not different than a local slice
> variable. Since we wouldn't want an entire copy of the elements due to
> an element mutation:
>
> int[] whole = // ...;
> int[] firstHalf = whole[0 .. $/2];
> firstHalf = 42; // this should affect whole
>
> Moving the last two lines to a new function should not change meaning:
>
> int[] whole = // ...;
> setFirstHalf(whole, 42); // should still affect whole
I think that setFirstHalf() should only effect whole if it's passed in by reference. I certainly intend to adopt that practice in my D code.
Peter
|
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Williams | On Thu, 30 May 2013 20:05:59 -0400, Peter Williams <pwil3058@bigpond.net.au> wrote:
> On 30/05/13 16:21, Ali Çehreli wrote:
>> On 05/29/2013 06:54 PM, Peter Williams wrote:
>> > I find the mechanism described in the article a little disconcerting and
>> > it certainly needs more publicity as it's a bug in waiting for the
>> > unwary.
>>
>> It certainly is disconcerting. Performance have played a big role in the
>> current semantics of slices.
>
> I should have added that it was the non determinism that disconcerted me. It doesn't really affect me personally as a programmer now that I know about it as I can just avoid it. But it blows out of the water any hopes of having "proveably correct" non trivial code.
I think this is an overstatement. It depends heavily on what you are doing, and most usages will be correct.
You can achieve deterministic behavior depending on what you are looking for. For certain, you can tell without any additional tools that an append will not reallocate if the capacity is large enough.
-Steve
|
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Attachments:
| Maybe this is too late replying, but I'd like to provide an information.
Current D does not provide generic way for deep copy of class object. But, you can use std.conv.to with adding a kind of copy constructor.
class C
{
int x;
this(int n) { x = n; }
// Do deep copy, this is used by to!(array-type)(array)
this(const C c) { this.x = c.x; }
}
void main()
{
const(C)[] carr = [new C(1), new C(2)];
// C[] marr = carr.dup;
// --> Error: cannot implicitly convert element type const(C) to
mutable in carr.dup
import std.conv;
C[] marr = carr.to!(C[]);
// For class arrays which need copy elements,
// std.conv.to returns [new C(carr[0]), new C(carr[1]), ...]
// modify element of returned array
marr[0].x = 5;
// Right now carr[0] and marr[0] are completely unrelated objects
assert(carr[0].x == 1);
assert(marr[0].x == 5);
}
Kenji Hara
2013/5/29 Peter Williams <pwil3058@bigpond.net.au>
> On 28/05/13 23:41, Steven Schveighoffer wrote:
>
>> On Sat, 25 May 2013 23:58:39 -0400, Peter Williams <pwil3058@bigpond.net.au> wrote:
>>
>> Is the inability to use dup and ~ with const arrays of class objects a
>>> deliberate design restriction? I couldn't find mention of it in the specification or Andrei's book and only discovered it the hard way.
>>>
>>
>> It has to be. There is no cdup.
>>
>> For any const(T)[] x, the type of x.dup is T[].
>>
>
> Yes, that's why I was doing the dup. I wanted a non const copy of the array.
>
>
> Because this would mean
>> that you would remove const, you cannot do that.
>>
>
> I find that dup works for const T[] when T is not a class (although I
> haven't tried it with pointers). This means I write two versions of my
> code - one for classes (which does (cast(T[])).dup) and one for the rest.
>
>
> Nor can you idup,
>> since implicit conversion to immutable is not possible.
>>
>> As far as I know, ~ works with const arrays of class objects. Can you give a case where it fails?
>>
>
> Looking at my code that caused me to ask this question, I've realised that I'm appending a const object onto a no const array. Once again this works for non class objects but not for classes.
>
> I can see why this might be the case as non class objects are probably copied by value where the class objects are pointers and the constness applies to the items in an array as well the array itself.
>
> If this behaviour is a deliberate design decision I'll accept that and
> (probably) modify my code to use (cast(T[])).dup in all cases. (At the
> moment, I'm using a single mixin template to handle this issue and the
> inability to use ==, !=, < and friends with constant class objects. When
> that problem goes away I'll do the above modifications.)
>
> This is the type of issue that can come as a surprise when you have a working/tested code that suddenly stops compiling when you use it with classes. So a heads up in the documentation would be useful.
>
> Thanks for your response,
> Peter
>
|
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 31/05/13 12:07, Steven Schveighoffer wrote: > On Thu, 30 May 2013 20:05:59 -0400, Peter Williams > <pwil3058@bigpond.net.au> wrote: > >> On 30/05/13 16:21, Ali Çehreli wrote: >>> On 05/29/2013 06:54 PM, Peter Williams wrote: >>> > I find the mechanism described in the article a little >>> disconcerting and >>> > it certainly needs more publicity as it's a bug in waiting for the >>> > unwary. >>> >>> It certainly is disconcerting. Performance have played a big role in the >>> current semantics of slices. >> >> I should have added that it was the non determinism that disconcerted >> me. It doesn't really affect me personally as a programmer now that I >> know about it as I can just avoid it. But it blows out of the water >> any hopes of having "proveably correct" non trivial code. > > I think this is an overstatement. It depends heavily on what you are > doing, and most usages will be correct. All uses have to be correct if you want "provably correct" otherwise you just get "mostly correct". > > You can achieve deterministic behavior depending on what you are looking > for. For certain, you can tell without any additional tools that an > append will not reallocate if the capacity is large enough. > That makes programming much easier, doesn't it. I'll just avoid it by using: a = a ~ b; instead of: a ~= b; where I think it might be an issue or is that broken too? I toy in my mind with the idea that the difference between dynamic arrays and slices should be that slices are read only and if you write to them they get reallocated and promoted to dynamic array (kind of like copy on write with hard linked files). But I'm sure that would just create another set of problems. Also I imagine that it's already been considered and discarded. BTW the slice "notation" could still be used for assigning to sections of an array. Peter |
May 31, 2013 Re: Inability to dup/~ for const arrays of class objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Peter Williams | On Fri, 31 May 2013 00:48:47 -0400, Peter Williams <pwil3058@bigpond.net.au> wrote: > On 31/05/13 12:07, Steven Schveighoffer wrote: >> On Thu, 30 May 2013 20:05:59 -0400, Peter Williams >> <pwil3058@bigpond.net.au> wrote: >> >>> On 30/05/13 16:21, Ali Çehreli wrote: >>>> On 05/29/2013 06:54 PM, Peter Williams wrote: >>>> > I find the mechanism described in the article a little >>>> disconcerting and >>>> > it certainly needs more publicity as it's a bug in waiting for the >>>> > unwary. >>>> >>>> It certainly is disconcerting. Performance have played a big role in the >>>> current semantics of slices. >>> >>> I should have added that it was the non determinism that disconcerted >>> me. It doesn't really affect me personally as a programmer now that I >>> know about it as I can just avoid it. But it blows out of the water >>> any hopes of having "proveably correct" non trivial code. >> >> I think this is an overstatement. It depends heavily on what you are >> doing, and most usages will be correct. > > All uses have to be correct if you want "provably correct" otherwise you just get "mostly correct". All *your* uses have to be correct. What I meant was, you have to know the pitfalls and avoid them. Because there are pitfalls, this doesn't mean you can't prove correctness. And the pitfalls are quite few. > >> >> You can achieve deterministic behavior depending on what you are looking >> for. For certain, you can tell without any additional tools that an >> append will not reallocate if the capacity is large enough. >> > > That makes programming much easier, doesn't it. I'll just avoid it by using: > > a = a ~ b; > > instead of: > > a ~= b; If you care nothing for performance, this certainly is a way to go. > where I think it might be an issue or is that broken too? This is a conservative "always reallocate" methodology, it should work just like you allocated a new array to hold a and b. If a is frequently large, and b is frequently small, you will kill your performance vs. a ~= b. > I toy in my mind with the idea that the difference between dynamic arrays and slices should be that slices are read only and if you write to them they get reallocated and promoted to dynamic array (kind of like copy on write with hard linked files). But I'm sure that would just create another set of problems. Also I imagine that it's already been considered and discarded. BTW the slice "notation" could still be used for assigning to sections of an array. This was a proposed feature (not the copy on write, but copy on append). It was so complex to explain that we simply didn't implement it. Instead, we improved array appending performance and semantics. The two largest differences between slices and proper dynamic arrays is that a slice does not own it's viewed data (read: is not responsible for the lifetime), and it's 'view' is passed by value. -Steve |
Copyright © 1999-2021 by the D Language Foundation