August 03, 2006
Hasan Aljudy wrote:
> 
> 
> Tom S wrote:
>> Hasan Aljudy wrote:
>>
>>>
>>>
>>> Tom S wrote:
>>>
>>>> Hasan Aljudy wrote:
>>>>
>>>>>
>>>>> a compiler generated .dup method would be nice.
>>>>
>>>>
>>>>
>>>>
>>>> Reflection and the ability to generate your own would be even better.
>>>
>>>
>>> well you already can create your own .dup
>>> I mean it's just a method that returns typeof(this)
>>
>>
>> There was a subtle difference in what I wrote :) 'generate' vs 'create'  - that is. Generating own .dup and/or serialization functions based on meta data is different than writing/creating your own routines to handle that by hand.
>>
>>
>> -- 
>> Tomasz Stachowiak
> 
> Sorry, what's the difference of writing code and "generating code by yourself"?

I didn't write 'generating code by yourself'. Anyway, in this context:

If you wanted the .dup to behave in such a way that e.g. it would do a binary copy of all structs and built-in types, and recursively call .dup on all object members of a given class that support the .dup method then... you'd have to write it by hand for each class. Also, you'd have to update the .dup method upon each modification of the class' members.

On the other hand, if D had good reflection support, it would be possible to e.g. define a mixin that detects what fields a given class contains and generates your custom-tailored .dup method.


--
Tomasz Stachowiak
August 03, 2006
On Thu, 03 Aug 2006 14:12:03 -0600, Hasan Aljudy wrote:

> Bruno Medeiros wrote:
>> Derek Parnell wrote:
>> 
> <Snip>
>>> And maybe one day (hoping against precedent) that Walter will actually
>>> see
>>> that an operator for copying stuff is not such a stupid idea.
>>>
>>>    auto backup := q; // invokes q.onCopy() if it exists.
>>>
>> 
>> Yes, I think that would be quite useful.
>> 
> 
> Oh please, I hate the := operator, it's too ugly.

I don't give a damn what operator is used, this was *JUST AN EXAMPLE*.

Please, feel free to suggest other things that might be suitable for a deep-copy operator. One that would be usable on all data types and meants that the information in the left-hand-side thingy would be copied and the right-hand thingy would 'hold' that copy.

For objects, it would invoke onDup/onCopy/onClone/onDeepCopy/onWhatever (the name doesn't matter) if it existed, otherwise its a compile time error. The function would return the same datatype as the object that owns the function, meaning that Foo.onDup can't return a Bar or its parent type or an interface - it must return a Foo object instance.

For arrays it is identical to the .dup property.

For basic datatypes it is identical to moving the bit value from one to another variable (no conversion or transformations allowed).

Therefore the lefthand side and righthand side thingy must be the same datatype.

-- 
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"
August 03, 2006
Derek wrote:
> On Thu, 03 Aug 2006 14:26:08 +0100, Bruno Medeiros wrote:
> 
>> Derek Parnell wrote:
>>> Currently there doesn't seem to be any standard D mechanism (read:
>>> operator) to take a copy of an object. So are there any suggestions for a
>>> name that we can all agree on; one that might become an unofficial
>>> standard? 
>>>
>>> For arrays we have the 'dup' property but for objects there is nothing that
>>> the compiler assumes. I'm partial to 'onDup' or 'onCopy', and maybe even a
>>> 'onDeepCopy' as an additional function.
>>>
>>> Example:
>>>
>>>   class Foo
>>>   {
>>>       int x;
>>>       Bar b;
>>>
>>>       this(int y)       {
>>>            x = y;
>>>            b = new Bar(y);
>>>       }
>>>
>>>       Foo onCopy()
>>>       {
>>>           Foo t;
>>>           t = new Foo(x);
>>>           return t;
>>>        }
>>>    }
>>>
>>>    . . . 
>>>
>>>    auto backup = q.onCopy();
>>>
>> What's the "on" prefix for? I think the name should be something like:
> 
> The 'on' prefix is a *hint* to Walter that I'd really like this function to
> be invoked via a new operator and not necessariliy called directly.


Somehow, 'on' doesn't sound like an operator. On the other hand 'op' does...
August 03, 2006

Tom S wrote:
> Derek wrote:
> 
>> On Thu, 03 Aug 2006 14:26:08 +0100, Bruno Medeiros wrote:
>>
>>> Derek Parnell wrote:
>>>
>>>> Currently there doesn't seem to be any standard D mechanism (read:
>>>> operator) to take a copy of an object. So are there any suggestions for a
>>>> name that we can all agree on; one that might become an unofficial
>>>> standard?
>>>> For arrays we have the 'dup' property but for objects there is nothing that
>>>> the compiler assumes. I'm partial to 'onDup' or 'onCopy', and maybe even a
>>>> 'onDeepCopy' as an additional function.
>>>>
>>>> Example:
>>>>
>>>>   class Foo
>>>>   {
>>>>       int x;
>>>>       Bar b;
>>>>
>>>>       this(int y)       {
>>>>            x = y;
>>>>            b = new Bar(y);
>>>>       }
>>>>
>>>>       Foo onCopy()
>>>>       {
>>>>           Foo t;
>>>>           t = new Foo(x);
>>>>           return t;
>>>>        }
>>>>    }
>>>>
>>>>    . . .
>>>>    auto backup = q.onCopy();
>>>>
>>> What's the "on" prefix for? I think the name should be something like:
>>
>>
>> The 'on' prefix is a *hint* to Walter that I'd really like this function to
>> be invoked via a new operator and not necessariliy called directly.
> 
> 
> 
> Somehow, 'on' doesn't sound like an operator. On the other hand 'op' does...

I think he meant op ..
heheh .. when I first read the specs on operator overloading I got confused and, in my mind, I read all the opXxxx functions as onXxxx
August 03, 2006

Derek wrote:
> On Thu, 03 Aug 2006 14:12:03 -0600, Hasan Aljudy wrote:
> 
> 
>>Bruno Medeiros wrote:
>>
>>>Derek Parnell wrote:
>>>
>>
>><Snip>
>>
>>>>And maybe one day (hoping against precedent) that Walter will actually see
>>>>that an operator for copying stuff is not such a stupid idea.
>>>>
>>>>   auto backup := q; // invokes q.onCopy() if it exists.
>>>>
>>>
>>>Yes, I think that would be quite useful.
>>>
>>
>>Oh please, I hate the := operator, it's too ugly.
> 
> 
> I don't give a damn what operator is used, this was *JUST AN EXAMPLE*. 
> 
> Please, feel free to suggest other things that might be suitable for a
> deep-copy operator. One that would be usable on all data types and meants
> that the information in the left-hand-side thingy would be copied and the
> right-hand thingy would 'hold' that copy.
> 
> For objects, it would invoke onDup/onCopy/onClone/onDeepCopy/onWhatever
> (the name doesn't matter) if it existed, otherwise its a compile time
> error. The function would return the same datatype as the object that owns
> the function, meaning that Foo.onDup can't return a Bar or its parent type
> or an interface - it must return a Foo object instance.
> 
> For arrays it is identical to the .dup property.
> 
> For basic datatypes it is identical to moving the bit value from one to
> another variable (no conversion or transformations allowed).
> 
> Therefore the lefthand side and righthand side thingy must be the same
> datatype.
> 

why an operator?
a method/property is more suitable, I think.
August 03, 2006
On Fri, 04 Aug 2006 00:04:32 +0100, Tom S wrote:


> Somehow, 'on' doesn't sound like an operator. On the other hand 'op' does...

LOL...my mistake. I've been coding too much in another language recently.

-- 
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"
August 03, 2006
On Thu, 03 Aug 2006 17:12:39 -0600, Hasan Aljudy wrote:

> why an operator?
> a method/property is more suitable, I think.

Where does this train of thought stop? Why an operator for anything? Do we need '=' '>=' '+=' etc... when we have all those useful opXXX functions handy? Of course we do, because it makes coding easier to read and write.

The action of cloning an item is quite a common action and having to use a method name is not as convenient as an operator. Also, an operator can act with objects, structs, arrays, and basic-types where as method names don't work so well with all types. This simplifies template construction.

-- 
Derek Parnell
Melbourne, Australia
"Down with mediocrity!"
August 03, 2006
Hasan Aljudy wrote:
> 
> 
> Derek wrote:
> 
>> On Thu, 03 Aug 2006 14:12:03 -0600, Hasan Aljudy wrote:
>>
>>
>>> Bruno Medeiros wrote:
>>>
>>>> Derek Parnell wrote:
>>>>
>>>
>>> <Snip>
>>>
>>>>> And maybe one day (hoping against precedent) that Walter will actually see
>>>>> that an operator for copying stuff is not such a stupid idea.
>>>>>
>>>>>   auto backup := q; // invokes q.onCopy() if it exists.
>>>>>
>>>>
>>>> Yes, I think that would be quite useful.
>>>>
>>>
>>> Oh please, I hate the := operator, it's too ugly.
>>
>>
>>
>> I don't give a damn what operator is used, this was *JUST AN EXAMPLE*.
>> Please, feel free to suggest other things that might be suitable for a
>> deep-copy operator. One that would be usable on all data types and meants
>> that the information in the left-hand-side thingy would be copied and the
>> right-hand thingy would 'hold' that copy.
>>
>> For objects, it would invoke onDup/onCopy/onClone/onDeepCopy/onWhatever
>> (the name doesn't matter) if it existed, otherwise its a compile time
>> error. The function would return the same datatype as the object that owns
>> the function, meaning that Foo.onDup can't return a Bar or its parent type
>> or an interface - it must return a Foo object instance.
>>
>> For arrays it is identical to the .dup property.
>>
>> For basic datatypes it is identical to moving the bit value from one to
>> another variable (no conversion or transformations allowed).
>>
>> Therefore the lefthand side and righthand side thingy must be the same
>> datatype.
>>
> 
> why an operator?
> a method/property is more suitable, I think.

People used to C++ are used to doing this with an operator overload. People used to some other languages (e.g. Python) will be more used to using a method (or even a library function, in the case of Python). I honestly don't think it matters.

One could also argue for the use of copy constructors, of course. This may be getting too close to C++ for some people's tastes, though. (The syntax is also more verbose than a simple .dup property.)

class Foo {
    int m_i;
    this(int i) { m_i = i; }
    this(Foo f) { m_i = f.m_i; }
}

Foo a, b;
a = new Foo(20);
b = new Foo(a);

This does have the advantage of using "new" to make it clear that we are allocating a new object (though I don't think this is really a problem with just using .dup).

With reflection support, we could even give Object a useful default copy constructor, as Tom S pointed out.

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://dsource.org/projects/pyd/wiki
August 04, 2006
On Thu, 03 Aug 2006 16:28:25 -0700, Kirk McDonald wrote:

> People used to C++ are used to doing this with an operator overload. People used to some other languages (e.g. Python) will be more used to using a method (or even a library function, in the case of Python). I honestly don't think it matters.
> 
> One could also argue for the use of copy constructors, of course. This may be getting too close to C++ for some people's tastes, though. (The syntax is also more verbose than a simple .dup property.)

Copy constructors and 'standard' functions would have to work with basic types, structs and arrays too for it to be really useful.


> class Foo {
>      int m_i;
>      this(int i) { m_i = i; }
>      this(Foo f) { m_i = f.m_i; }
> }
> 
> Foo a, b;
> a = new Foo(20);
> b = new Foo(a);
> 
> This does have the advantage of using "new" to make it clear that we are allocating a new object (though I don't think this is really a problem with just using .dup).
> 
> With reflection support, we could even give Object a useful default copy constructor, as Tom S pointed out.

Not everything is an object. <g>

  template backup(T)
  {
      void backup(inout T[] st, T dt)
      {
           st.length = st.length + 1;
           st[$-1] := dt;  // Invokes opDup for classes and structs,
                           // .dup for arrays,
                           // binary copy for everything else
      }
  }

  int[] istore;
  backup( istore, anInt);

  Foo[] foostore;
  backup( foostore, aFoo);


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
4/08/2006 10:40:00 AM
August 04, 2006
Derek Parnell wrote:
> On Thu, 03 Aug 2006 16:28:25 -0700, Kirk McDonald wrote:
> 
> 
>>People used to C++ are used to doing this with an operator overload. People used to some other languages (e.g. Python) will be more used to using a method (or even a library function, in the case of Python). I honestly don't think it matters.
>>
>>One could also argue for the use of copy constructors, of course. This may be getting too close to C++ for some people's tastes, though. (The syntax is also more verbose than a simple .dup property.)
> 
> 
> Copy constructors and 'standard' functions would have to work with basic
> types, structs and arrays too for it to be really useful.
> 

Of course. :-)

>  
> 
>>class Foo {
>>     int m_i;
>>     this(int i) { m_i = i; }
>>     this(Foo f) { m_i = f.m_i; }
>>}
>>
>>Foo a, b;
>>a = new Foo(20);
>>b = new Foo(a);
>>
>>This does have the advantage of using "new" to make it clear that we are allocating a new object (though I don't think this is really a problem with just using .dup).
>>
>>With reflection support, we could even give Object a useful default copy constructor, as Tom S pointed out.
> 
> 
> Not everything is an object. <g>
> 
>   template backup(T)
>   {
>       void backup(inout T[] st, T dt)
>       {
>            st.length = st.length + 1;
>            st[$-1] := dt;  // Invokes opDup for classes and structs,
>                            // .dup for arrays,
>                            // binary copy for everything else
>       }
>   }
> 
>   int[] istore;
>   backup( istore, anInt);
> 
>   Foo[] foostore;
>   backup( foostore, aFoo);
>  
> 

opDup appeals to me, but more consistent would probably be a standard .dup property. Despite what others have said, := is not a terrible operator. However, having := be overloaded with a "dup" function instead of an "opDup" function is inconsistent with the other operator overloads.

So let's get the problem clear before we go proposing solutions: We want a standard way of getting a copy of an object. We can either use an operator for this purpose (such as :=), or a standard method (such as .dup, as arrays currently use for the same purpose).

The := operator should work for classes, structs, arrays, and other primitive types. Arrays already have the .dup property, so := can use that. Remember that structs use value semantics. Assigning a struct the normal way copies its members. So, for structs and the various primitive types (that is to say, all of the types that use value semantics), := will be identical to a regular assignment.

I suggest a copy constructor as a way of overloading := for class objects. This is a C++ thing, but it is actually a fairly elegant solution, I think.

The complication, now, is getting a constant way of getting a copy of some object or value when we don't actually want to assign it to anything (say, in a function call). My initial thought is to use unary : to mean "copy-of" (this is consistent with the := operator), but (not knowing much about how the parser works), I can't help but think that this might interfere with labels or the trinary ?: operator or something. Someone care to comment on that? The syntax looks fine:

fn( i, j, :obj); // send a copy of obj to the function

So, for both the proposed := copy-assignment operator and unary : copy operator, the various copying mechanisms would be:

class instances:                copy constructor
arrays/AAs:                     dup property
structs, primitive types, etc:  by-value copy

We wouldn't even have to provide a copy constructor in Object, you know. Trying to use these operators on an instance of a class that doesn't define a copy constructor would just be a compiler error, like any other undefined operator overload or method you try to use.

Thoughts?

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://dsource.org/projects/pyd/wiki