May 24, 2010
Steven Schveighoffer wrote:
> All an interface does is give an abstract representation of functions that are *already there*.  Removing the interface does not remove the functions that implemented the interface.

Then why do interfaces need to be part of the collection component? Why can't the user add them if he wants them?
May 24, 2010
Walter Bright Wrote:

> Steven Schveighoffer wrote:
> > I'd ask the naysayers of interfaces for dcollections, and also the supporters: what is the point of having interfaces in D?  Are interfaces pretty much obsolete, and I am just nostalgic about their utility?
> 
> Interfaces are for runtime polymorphism, rather than compile time polymorphism. They are especially useful for things like:
> 
> 1. runtime plugin interfaces
> 2. designs where strict implementation hiding is desired
> 3. to have binary libraries (shared and static)
> 4. to support Java/C# style coding
> 5. reduced code memory footprint
> 6. experience shows they are an excellent fit for user interfaces

7. Compiler-assisted verification.


> Compile time polymorphism, such as what templates provide, are most useful for:
> 
> 1. maximum performance
> 2. minimal data memory consumption
> 3. better compile time checking
> 
> 
> I believe the tradeoffs for collection types favor compile time polymorphism because:
> 
> 1. performance is often critical for collections
> 2. C++ STL has shown the success of this approach
> 3. collections must fit in naturally with ranges, and ranges are compile time
> polymorphic

How does error message quality compare between failing to conform to an interface verse conforming to an isXXX template? Anything that increases the time gap between code writing and code verification is bad. Does Phobos consistently use an isXXX template-based self-check that other writers of ranges can copy? Certainly, inheritance syntax is easier in this regard.

May 25, 2010
Jason House wrote:
> 7. Compiler-assisted verification.

For interfaces, the compile time checking is limited to verifying that functions with the right signature are supplied. Templates can go considerably beyond that with the constraint checking.
May 25, 2010
Walter Bright wrote:
>  The extra complexity is in the container supporting very different ways to do the same thing.
> 

A I understand from the current discussion, interfaces meet a strong debate. And yes, I also understand that the interfaces are considered unnecessary bloat that makes execution speed slower which is critical for performance.
Personally, I think they should be accessible.

But, can there be a compromise to satisfy both sides?

To illustrate the idea:
C# has a feature called "Partial types".
A little excerpt from C# 4.0 specs(page 285):
> The partial modifier indicates that additional parts of the type declaration may exist elsewhere, but the existence of such additional parts is not a requirement;

I see as a potential benefit for the D to have some sort of it.

For those who need templates for speed, or any other motive:

1. Import .di header with needed partial declaration of the required type.
2. The compiler injects exactly the code generated from the implementation of the header and nothing more.

For those who need interfaces for the reasons of maintainability, compatibility and interoperability:

1. Import .di header with needed partial declaration of the required type interfaces.
2. The compiler injects exactly the code generated from the implementation of the header or links with the provided library with the exact implementation.

The user source includes required .di header, which declares partial type declarations. The specified partial types from the header may have the implementation, but this should not be a requirement. In case of partially not implemented type the user gets 'not implemented' error, linkage fault, or something similar.

Is there a possibility for such solution?


-- 
Alex Makhotin,
the founder of BITPROX,
http://bitprox.com
May 25, 2010
Recently I've hit a problem with collections in C#. Given classes
class A {}
class B {}
And two collections Collection<A> and Collection<B> it's possible to concat them into an array A[]. The efficient way to do it is to use CopyTo(T[],int) method, but it accepts only array of exact collection item's type, so I had to change the Collection<B> type to Collection<A>.
May 25, 2010
On Tue, 25 May 2010 02:26:02 -0400, Kagamin <spam@here.lot> wrote:

> Recently I've hit a problem with collections in C#. Given classes
> class A {}
> class B {}
> And two collections Collection<A> and Collection<B> it's possible to concat them into an array A[]. The efficient way to do it is to use CopyTo(T[],int) method, but it accepts only array of exact collection item's type, so I had to change the Collection<B> type to Collection<A>.

Did you mean

class B : A {} ?

According to this page, it says that an exception could be thrown if "Type T cannot be cast automatically to the type of the destination array."  This implies that a destination array type to which T could automatically be cast should work.

http://msdn.microsoft.com/en-us/library/0efx51xw%28v=VS.100%29.aspx

But the larger point that compile-time code generation can help with this is valid.

-Steve
May 25, 2010
Walter Bright Wrote:

> Jason House wrote:
> > 7. Compiler-assisted verification.
> 
> For interfaces, the compile time checking is limited to verifying that functions with the right signature are supplied. Templates can go considerably beyond that with the constraint checking.

constraints are more powerful, but they have downsides:
 • If a class is incorrectly defined, failure to use a type without a constraint check leads to errors in the code using it instead of the class definition. Usage isn't always guaranteed to be correct either, so the developer must spend extra time diagnosing the real error.
• If a class is incorrectly, initial usage without a constraint may completely miss the error. Easy examples would be a typo propogated with copy/paste, or neglecting to use save.
• If a class is incorrectly defined and usage uses a constraint, the developer will simply get an error that there is no matching call.
• If a constraint is incorrectly defined and usage uses the constraint, the developer will simply get an error that there is no matching call.

None of these scenarios are particularly helpful for a developer creating/expanding a family of objects.

PS: The use of the word class above is for clarity instead of using type or object. I could have said struct as well.
May 25, 2010
On Tue, 25 May 2010 09:03:34 -0400, Jason House <jason.james.house@gmail.com> wrote:

> Walter Bright Wrote:
>
>> Jason House wrote:
>> > 7. Compiler-assisted verification.
>>
>> For interfaces, the compile time checking is limited to verifying that functions
>> with the right signature are supplied. Templates can go considerably beyond that
>> with the constraint checking.
>
> constraints are more powerful, but they have downsides:
>  • If a class is incorrectly defined, failure to use a type without a constraint check leads to errors in the code using it instead of the class definition. Usage isn't always guaranteed to be correct either, so the developer must spend extra time diagnosing the real error.
> • If a class is incorrectly, initial usage without a constraint may completely miss the error. Easy examples would be a typo propogated with copy/paste, or neglecting to use save.
> • If a class is incorrectly defined and usage uses a constraint, the developer will simply get an error that there is no matching call.
> • If a constraint is incorrectly defined and usage uses the constraint, the developer will simply get an error that there is no matching call.
>
> None of these scenarios are particularly helpful for a developer creating/expanding a family of objects.

These all boil down to the fact that you must declare an interface up front, whereas constraints are not required.

You can get to about the same level as an interface by using static asserts, but this is optional (it probably should be a "best practice" though somewhere).

-Steve
May 25, 2010
On 2010-05-24 21.08, Steven Schveighoffer wrote:
> On Mon, 24 May 2010 14:36:57 -0400, Walter Bright
> <newshound1@digitalmars.com> wrote:
>
>> Steven Schveighoffer wrote:
>>> On Mon, 24 May 2010 14:10:26 -0400, Walter Bright
>>> <newshound1@digitalmars.com> wrote:
>>>
>>>> Steven Schveighoffer wrote:
>>>>> I'd ask the naysayers of interfaces for dcollections, and also the
>>>>> supporters: what is the point of having interfaces in D? Are
>>>>> interfaces pretty much obsolete, and I am just nostalgic about
>>>>> their utility?
>>>>
>>>> Interfaces are for runtime polymorphism, rather than compile time
>>>> polymorphism. They are especially useful for things like:
>>>>
>>>> 1. runtime plugin interfaces
>>>> 2. designs where strict implementation hiding is desired
>>>> 3. to have binary libraries (shared and static)
>>>> 4. to support Java/C# style coding
>>>> 5. reduced code memory footprint
>>>> 6. experience shows they are an excellent fit for user interfaces
>>>>
>>>>
>>>> Compile time polymorphism, such as what templates provide, are most
>>>> useful for:
>>>>
>>>> 1. maximum performance
>>>> 2. minimal data memory consumption
>>>> 3. better compile time checking
>>>>
>>>>
>>>> I believe the tradeoffs for collection types favor compile time
>>>> polymorphism because:
>>>>
>>>> 1. performance is often critical for collections
>>>> 2. C++ STL has shown the success of this approach
>>>> 3. collections must fit in naturally with ranges, and ranges are
>>>> compile time polymorphic
>>> I'd counter point 2 by saying that 1. C++ classes are value-types by
>>> default and 2. C++ doesn't have interfaces, so it's not exactly fair
>>> to say that the STL author considered interfaces but rejected them.
>>
>> C++ certainly does have interfaces. The whole COM system is based on
>> them, for example. Technically, D interfaces are just a subset of C++
>> multiple inheritance.
>
> And if STL looked like COM, I think it would have been a miserable
> failure indeed.
>
>>
>>> and on point 3, why is it not OK to *also* provide interfaces in
>>> addition to ranges as dcollections does? That is, take away
>>> dcollections' interfaces, and you have essentially compile-time
>>> polymorphism, they all support ranges etc. Interfaces are also there
>>> in case you want to use them in things like runtime plugin interfaces.
>>
>> The best reason I can think of is to avoid kitchen-sink style
>> components. Components should do one thing well. Adding capability
>> should be done with aggregation by the user.
>
> What if it can do both things well (I would propose that dcollections
> does)?
>
>>
>>
>>> Basically, my point is, compile time interfaces does not mean you
>>> can't also have runtime interfaces. In fact, interfaces can be
>>> compile-time parameterized.
>>
>> Sure, but I'd argue that adding such runtime polymorphism should be
>> done with a separate add-on component. It should not be part of the
>> collection component.
>
> So I should specifically have to wrap a collection type in order to make
> it runtime polymorphic, forwarding all the operations to the collection?
> Essentially something like:
>
> class WrappedSet(Impl, V) : Set!V
> {
> Impl!V impl;
>
> bool contains(V v) { return impl.contains(v);}
> ...
> }
>
> For what reason? Why is it so bad to just stick Set!V on the end of the
> implementation class?
>
>>
>>
>>> Also, much of a user interface consists of various collections
>>> (listview, treeview, child widgets, etc.). Why is runtime
>>> polymorphism good there, but not on a generic collections package
>>> (not as the only means of access of course)?
>>
>> A user interface object is not a collection component, I think there's
>> a confusion in the design there.
>
> Don't user interface objects have data? If a UI component is an
> interface, how does it expose access to its data? For example, a .NET
> ListView control contains an Items property which you can use to access
> the elements in the list view. The Items property returns a
> ListViewItemCollection which implements IList, IContainer, and
> IEnumerable. I've found these types of abstractions useful when
> adding/iterating, etc.
> -Steve


I would say that is a bad design, I would go with the MVC pattern. For example, you have a ListView and when it's ready to display, say row 3, it calls your delegate and request you to return the item that should be visible on row 3. Then it's up to you to store the items in some appropriate data structure, like a list or array.

-- 
/Jacob Carlborg
May 25, 2010
On Mon, 24 May 2010 18:13:38 -0400, Walter Bright <newshound1@digitalmars.com> wrote:

> Steven Schveighoffer wrote:
>> All an interface does is give an abstract representation of functions that are *already there*.  Removing the interface does not remove the functions that implemented the interface.
>
> Then why do interfaces need to be part of the collection component? Why can't the user add them if he wants them?

How do you add an interface to a class?  Wrapping seems like it would add more overhead than just implementing the interface, especially since D's inliner has some strange restrictions.

-Steve