July 27, 2009
On Mon, Jul 27, 2009 at 7:48 AM, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote:
> Leandro Lucarella wrote:
>>
>> Andrei Alexandrescu, el 27 de julio a las 07:59 me escribiste:
>>>>
>>>> For example, should the author of a container library prefer classes or structs?
>>>
>>> I've been struggling with this forever. I don't know. I don't even know whether reference or value semantics are best for containers. I don't know whether abstract container interfaces and container-independent code are a net win; experience with STL seems to say "don't" and experience with Java seems to say "ho-hum".
>>
>> About values vs. reference semantics, I think reference is the best.
>> Containers usually are big, and you don't want to copy them arround.
>> I find myself using lots of references to pass containers arround in C++
>> and almost never use the copy() method of Python containers, so based on
>> *my* experience, I'd say that reference as the default is the best
>> approach.
>
> Sounds convincing.

That's exactly right except for the times when it isn't and what you want is value semantics.

I've just finished recently refactoring some C++ code that wasn't designed with copying in mind.  Changing all the "float* data; int data_length;" members into std::vectors did the trick.  The data they contained wasn't particularly large, and there was no real need to introduce the complexity that sharing it between copied instances would have created.

--bb
July 27, 2009
On Mon, Jul 27, 2009 at 9:54 AM, Bill Baxter<wbaxter@gmail.com> wrote:
> On Mon, Jul 27, 2009 at 7:48 AM, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote:
>> Leandro Lucarella wrote:
>>>
>>> Andrei Alexandrescu, el 27 de julio a las 07:59 me escribiste:
>>>>>
>>>>> For example, should the author of a container library prefer classes or structs?
>>>>
>>>> I've been struggling with this forever. I don't know. I don't even know whether reference or value semantics are best for containers. I don't know whether abstract container interfaces and container-independent code are a net win; experience with STL seems to say "don't" and experience with Java seems to say "ho-hum".
>>>
>>> About values vs. reference semantics, I think reference is the best.
>>> Containers usually are big, and you don't want to copy them arround.
>>> I find myself using lots of references to pass containers arround in C++
>>> and almost never use the copy() method of Python containers, so based on
>>> *my* experience, I'd say that reference as the default is the best
>>> approach.
>>
>> Sounds convincing.
>
> That's exactly right except for the times when it isn't and what you want is value semantics.
>
> I've just finished recently refactoring some C++ code that wasn't designed with copying in mind.  Changing all the "float* data; int data_length;" members into std::vectors did the trick.  The data they contained wasn't particularly large, and there was no real need to introduce the complexity that sharing it between copied instances would have created.

So if I didn't make it clear -- my opinion is that whether containers should be by value or by ref depends on the circumstances and that choice should be left to the programmer.

Thus the question becomes what's the easiest way to provide both? Three options I see:

1) Write ref classes and wrap them in structs
2) Write value structs and wrap them in classes
3) Write template mixins and mix them into both struct and class shells.

I think given the existence of "alias this" for structs, 1 is actually
the best-supported paradigm.
I think with that you should be able to value-ize a by-ref container
class just by writing a post-blitter to copy the contents.

--bb
July 27, 2009
Andrei Alexandrescu wrote:
> yigal chripun wrote:
>> Andrei Alexandrescu Wrote:
>>
>>> yigal chripun wrote:
>>>> Andrei Alexandrescu Wrote:
>>>>
>>>>>> Is it appropriate to define multiple classes, structs,
>>>>>> templates, etc within a single module? What considerations
>>>>>> should inform the decision regarding the placement of module
>>>>>> boundaries?
>>>>> I think it's appropriate because many pieces of functionality
>>>>> come as a bundle. The rule of thumb is, module provides the
>>>>> functionality, and it's up to the designer to decide what that
>>>>> entails.
>>>>>
>>>>> Andrei
>>>> The rule of thumb above is good in theory but in practice such a
>>>> given bundle of functionality can produce a 30_000 line file.
>>>> while all those lines should be "bundled" conceptually together,
>>>> D's restriction of module == file makes for a huge file that is a
>>>> hassle to work with.
>>>>
>>>> yes, a "module" should represent a conceptual bundle of
>>>> functionallity but forcing this into one huge file is wrong.
>>> I think public import can help with that.
>>>
>>> Andrei
>>
>> That is just a work-around and not a full solution.
> 
> Why?
> 
>> this is a weak
>> spot in D which I'd like to see fixed.
> 
> Why is it a weak spot? What problems mar its advantages?

I think the approach with public imports should work in principle (although would probably require making a package for such 'module bundles' to have package-level field visibility, since private members would not be accessible across modules), but currently the DMD frontend fails at circular dependencies making this approach impossible.


-- 
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode
July 27, 2009
On Mon, Jul 27, 2009 at 10:01 AM, Bill Baxter<wbaxter@gmail.com> wrote:
> On Mon, Jul 27, 2009 at 9:54 AM, Bill Baxter<wbaxter@gmail.com> wrote:
>> On Mon, Jul 27, 2009 at 7:48 AM, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote:
>>> Leandro Lucarella wrote:
>>>>
>>>> Andrei Alexandrescu, el 27 de julio a las 07:59 me escribiste:
>>>>>>
>>>>>> For example, should the author of a container library prefer classes or structs?
>>>>>
>>>>> I've been struggling with this forever. I don't know. I don't even know whether reference or value semantics are best for containers. I don't know whether abstract container interfaces and container-independent code are a net win; experience with STL seems to say "don't" and experience with Java seems to say "ho-hum".
>>>>
>>>> About values vs. reference semantics, I think reference is the best.
>>>> Containers usually are big, and you don't want to copy them arround.
>>>> I find myself using lots of references to pass containers arround in C++
>>>> and almost never use the copy() method of Python containers, so based on
>>>> *my* experience, I'd say that reference as the default is the best
>>>> approach.
>>>
>>> Sounds convincing.
>>
>> That's exactly right except for the times when it isn't and what you want is value semantics.
>>
>> I've just finished recently refactoring some C++ code that wasn't designed with copying in mind.  Changing all the "float* data; int data_length;" members into std::vectors did the trick.  The data they contained wasn't particularly large, and there was no real need to introduce the complexity that sharing it between copied instances would have created.
>
> So if I didn't make it clear -- my opinion is that whether containers should be by value or by ref depends on the circumstances and that choice should be left to the programmer.
>
> Thus the question becomes what's the easiest way to provide both? Three options I see:
>
> 1) Write ref classes and wrap them in structs
> 2) Write value structs and wrap them in classes
> 3) Write template mixins and mix them into both struct and class shells.
>
> I think given the existence of "alias this" for structs, 1 is actually
> the best-supported paradigm.
> I think with that you should be able to value-ize a by-ref container
> class just by writing a post-blitter to copy the contents.

Doh!  I didn't realize classes could "alias this" too!
So that would put 1 and 2 on equal footing in that regard.

But maybe one argument in favor of structs is that it is easier to take value semantics and turn it into ref semantics.  You just need to take a pointer.

So this:

class RefContainer
{
     alias this valContainer_;
     this() { valContainer = new ValueContainer; }
private:
     ValueContainer *valContainer;
}

gets you a basic working ref container out of a value container.  To this you will probably want to add copy or clone type functionality.

In constrast:

struct ValueContainer
{
     alias this refContainer_;
     this() { refContainer = new RefContainer; }
     // must have add post-blit to get value semantics
private:
     RefContainer refContainer;
}

The requirement to add the post-blit is a little annoying.  If a ValueContainer is made fundamental and it is built initially out of components with value semantics, then no explicit post-blit will be necessary.  However if you go the other way and start with a RefContainer then a post-blit will be necessary when you implement the ValueContainer based on it.   So to me it seems a little better to go with the ValueContainer as the base implementation.

--bb
July 27, 2009
Bill Baxter wrote:
> On Mon, Jul 27, 2009 at 9:54 AM, Bill Baxter<wbaxter@gmail.com> wrote:
>> On Mon, Jul 27, 2009 at 7:48 AM, Andrei
>> Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote:
>>> Leandro Lucarella wrote:
>>>> Andrei Alexandrescu, el 27 de julio a las 07:59 me escribiste:
>>>>>> For example, should the author of a container library prefer classes or
>>>>>> structs?
>>>>> I've been struggling with this forever. I don't know. I don't even know
>>>>> whether reference or value semantics are best for containers. I don't
>>>>> know whether abstract container interfaces and container-independent
>>>>> code are a net win; experience with STL seems to say "don't" and
>>>>> experience with Java seems to say "ho-hum".
>>>> About values vs. reference semantics, I think reference is the best.
>>>> Containers usually are big, and you don't want to copy them arround.
>>>> I find myself using lots of references to pass containers arround in C++
>>>> and almost never use the copy() method of Python containers, so based on
>>>> *my* experience, I'd say that reference as the default is the best
>>>> approach.
>>> Sounds convincing.
>> That's exactly right except for the times when it isn't and what you
>> want is value semantics.
>>
>> I've just finished recently refactoring some C++ code that wasn't
>> designed with copying in mind.  Changing all the "float* data; int
>> data_length;" members into std::vectors did the trick.  The data they
>> contained wasn't particularly large, and there was no real need to
>> introduce the complexity that sharing it between copied instances
>> would have created.
> 
> So if I didn't make it clear -- my opinion is that whether containers
> should be by value or by ref depends on the circumstances and that
> choice should be left to the programmer.
> 
> Thus the question becomes what's the easiest way to provide both?
> Three options I see:
> 
> 1) Write ref classes and wrap them in structs
> 2) Write value structs and wrap them in classes
> 3) Write template mixins and mix them into both struct and class shells.
> 
> I think given the existence of "alias this" for structs, 1 is actually
> the best-supported paradigm.
> I think with that you should be able to value-ize a by-ref container
> class just by writing a post-blitter to copy the contents.
> 
> --bb

These thoughts are very much aligned with mine. Thanks Bill.

Andrei
July 27, 2009
Bill Baxter wrote:
> The requirement to add the post-blit is a little annoying.  If a
> ValueContainer is made fundamental and it is built initially out of
> components with value semantics, then no explicit post-blit will be
> necessary.  However if you go the other way and start with a
> RefContainer then a post-blit will be necessary when you implement the
> ValueContainer based on it.   So to me it seems a little better to go
> with the ValueContainer as the base implementation.

I think it's a matter of the most frequent use. I used to be a staunch supporter of values for containers, until Walter revealed to me that in STL you have value containers to constantly worry about adding the "&" everywhere. Implicitly copying containers is 95% of cases an error in C++ code. Witness all that advice about pass by reference etc. So why make that the default, one might ask? Better go with the flow and make the default case the easy case (reference), and if someone does want a value, have them write Value!Container.


Andrei
July 27, 2009
On Mon, Jul 27, 2009 at 10:58 AM, Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org> wrote:
> Bill Baxter wrote:
>>
>> The requirement to add the post-blit is a little annoying.  If a ValueContainer is made fundamental and it is built initially out of components with value semantics, then no explicit post-blit will be necessary.  However if you go the other way and start with a RefContainer then a post-blit will be necessary when you implement the ValueContainer based on it.   So to me it seems a little better to go with the ValueContainer as the base implementation.
>
> I think it's a matter of the most frequent use. I used to be a staunch supporter of values for containers, until Walter revealed to me that in STL you have value containers to constantly worry about adding the "&" everywhere. Implicitly copying containers is 95% of cases an error in C++ code. Witness all that advice about pass by reference etc. So why make that the default, one might ask? Better go with the flow and make the default case the easy case (reference), and if someone does want a value, have them write Value!Container.

Hmm.  Yeh, when passing containers around, 95% or more probably should
be by ref.
However when creating composite objects I'd say the percentage of time
you want by ref is much lower.
But I guess even then, by-ref composition isn't necessarily bad (as
most VM languages show).

--bb
July 27, 2009
On Mon, 27 Jul 2009, Andrei Alexandrescu wrote:

> Bill Baxter wrote:
> > The requirement to add the post-blit is a little annoying.  If a ValueContainer is made fundamental and it is built initially out of components with value semantics, then no explicit post-blit will be necessary.  However if you go the other way and start with a RefContainer then a post-blit will be necessary when you implement the ValueContainer based on it.   So to me it seems a little better to go with the ValueContainer as the base implementation.
> 
> I think it's a matter of the most frequent use. I used to be a staunch supporter of values for containers, until Walter revealed to me that in STL you have value containers to constantly worry about adding the "&" everywhere. Implicitly copying containers is 95% of cases an error in C++ code. Witness all that advice about pass by reference etc. So why make that the default, one might ask? Better go with the flow and make the default case the easy case (reference), and if someone does want a value, have them write Value!Container.
> 
> 
> Andrei

There's two layers to talk about, the container itself and the elements it contains.  I agree that the container itself should be ref given the above logic (which matches my experience).  The less obvious one, imho, is the default of the contained.  Again, c++ uses value containership, but an awful lot of the time people (including myself) use essentially a ref (by way of a smart pointer).  Often it's due to weak ownership semantics, and thus iffy design, but it is what it is.

Later,
Brad

July 27, 2009
Andrei Alexandrescu, el 27 de julio a las 12:58 me escribiste:
> Bill Baxter wrote:
> >The requirement to add the post-blit is a little annoying.  If a ValueContainer is made fundamental and it is built initially out of components with value semantics, then no explicit post-blit will be necessary.  However if you go the other way and start with a RefContainer then a post-blit will be necessary when you implement the ValueContainer based on it.   So to me it seems a little better to go with the ValueContainer as the base implementation.
> 
> I think it's a matter of the most frequent use. I used to be a staunch supporter of values for containers, until Walter revealed to me that in STL you have value containers to constantly worry about adding the "&" everywhere. Implicitly copying containers is 95% of cases an error in C++ code. Witness all that advice about pass by reference etc. So why make that the default, one might ask? Better go with the flow and make the default case the easy case (reference), and if someone does want a value, have them write Value!Container.

Another point for ref containers is that they allow to have a class
hierarchy of containers. I guess you can have it too using compile-time
"concepts", like ranges, but being able to do that with interfaces could
be nice (and you can still have the compile-time with classes too).
I don't know if the interfaces approach would be useful though...

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
We're rotten fruit
We're damaged goods
What the hell, we've got nothing more to lose
One gust and we will probably crumble
We're backdrifters
July 27, 2009
Leandro Lucarella wrote:
> About values vs. reference semantics, I think reference is the best.
> Containers usually are big, and you don't want to copy them arround.
> I find myself using lots of references to pass containers arround in C++
> and almost never use the copy() method of Python containers, so based on
> *my* experience, I'd say that reference as the default is the best
> approach.

I don't think the choice of reference vs value semantics has *anything*
to do with how often something is copied.  To me, the relevant questions
are:
  - Do you have strict ownership relationships?  (Usually you do.)
  - Do you want to avoid long-distance bugs?  (Yes you do, always.)

Orthogonal question: does copying *ever* make sense:
  - If yes, provide a copy operation.
  - If no, prevent copying.


-- 
Rainer Deyke - rainerd@eldwood.com