Thread overview
Interface problems
Jan 25, 2011
Mandeep Singh Brar
Jan 25, 2011
bearophile
Jan 26, 2011
Mandeep Singh Brar
Jan 26, 2011
Dmitry Olshansky
Jan 27, 2011
Stanislav Blinov
Jan 27, 2011
Mandeep Singh Brar
Jan 27, 2011
Stanislav Blinov
January 25, 2011
Hi,

Not a question but just raising a concern i am facing again and again. The current implementation of interfaces seem to be creating a number of problems.

I am not able to:

- find indexOf interface in an interface range using std.algorithm.
- compare interface objects
- assign interface to generic objects.

Does COM support warrant so much weight so as to break the interfaces implementation from D1 and all other languages. What is the way to get this addressed (is there a possibility at all).

Thanks
Mandeep
January 25, 2011
Mandeep Singh Brar:

> I am not able to:
> 
> - find indexOf interface in an interface range using std.algorithm.

I don't understand. Please explain better.


> - compare interface objects

What kind of comparisons do you need to perform and why?


> - assign interface to generic objects.

Why do you need to do this?

Bye,
bearophile
January 26, 2011
Mandeep Singh Brar:

> I am not able to:
>
> - find indexOf interface in an interface range using std.algorithm.

> I don't understand. Please explain better.

In the following snippet:
     Interface interfaceA{}
     class C:interfaceA{}
     class D:interfaceA{}

     interfaceA[] registry;
     register(interfaceA a) { registry ~= a; }
     unregister(interfaceA a) {idx = registry.indexOf(a); registry.replace(idx,
idx+1, null); }
In the above statement indexOf does not work.

> - compare interface objects

> What kind of comparisons do you need to perform and why?

Simple comparisons like in the below snippet
      class A {
          interfaceTest myInstance;
          setInstance(interfaceTest interfaceInstance) {
                 if(myInstance != interfaceInstance) //does not work
                 {
                      updateMyInstance;
                      doStuff;
                 }
          }
      }


> - assign interface to generic objects.

> Why do you need to do this?

      Just store various types of objects in a generic way like
           Object[] objects;
           objects ~= objA; objects~= interB and so on.

      I cant use Variant because interface can not be assigned to Variants and i
cant use Objects too.

> Bye,
> bearophile

Thanks
Mandeep
January 26, 2011
On 26.01.2011 8:12, Mandeep Singh Brar wrote:
> Mandeep Singh Brar:
>
>> I am not able to:
>>
>> - find indexOf interface in an interface range using std.algorithm.
>> I don't understand. Please explain better.
> In the following snippet:
>       Interface interfaceA{}
>       class C:interfaceA{}
>       class D:interfaceA{}
>
>       interfaceA[] registry;
>       register(interfaceA a) { registry ~= a; }
>       unregister(interfaceA a) {idx = registry.indexOf(a); registry.replace(idx,
> idx+1, null); }
> In the above statement indexOf does not work.
>

You should use 'is' for such kind of thing. The problem is that == uses opEquals or opCmp, there is no such thing for interfaces AFIKT. But for every pointer like type we can check if they are the same with 'is'. Here is your fixed snippet :

import std.algorithm;
import std.array;

interface interfaceA{}
     class C:interfaceA{}
     class D:interfaceA{}

     interfaceA[] registry;
     void register(interfaceA a) { registry ~= a; }
     void unregister(interfaceA a) {
    auto idx = indexOf!"a is b"(registry,a);
    registry.replace(idx,idx+1, null);

    }
void main(){
    auto b = new D();
    register(new C());
    register(b);
    unregister(b);
}


>> - compare interface objects
Yeah, here it sucks. 'is' is your best chance ;)
>> What kind of comparisons do you need to perform and why?
> Simple comparisons like in the below snippet
>        class A {
>            interfaceTest myInstance;
>            setInstance(interfaceTest interfaceInstance) {
>                   if(myInstance != interfaceInstance) //does not work
>                   {
>                        updateMyInstance;
>                        doStuff;
>                   }
>            }
>        }
>
>
Here just use '!is ' instead of !=

[snip]

>        Just store various types of objects in a generic way like
>             Object[] objects;
>             objects ~= objA; objects~= interB and so on.
>
>        I cant use Variant because interface can not be assigned to Variants and i
> cant use Objects too.
>

If you need to pile up different interfaces (no occasional Object ). The workaround would be to inherit all your interfaces from
a common base like:

interface Base{}
interface A: Base{...}
interface B: Base{...}
class CA: A{.. }
Base[] pile;
pile ~= new CA();
>> Bye,
>> bearophile
> Thanks
> Mandeep


-- 
Dmitry Olshansky

January 26, 2011
On Wed, 26 Jan 2011 05:12:39 -0500, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:

> On 26.01.2011 8:12, Mandeep Singh Brar wrote:
>> Mandeep Singh Brar:
>>
>>> I am not able to:
>>>
>>> - find indexOf interface in an interface range using std.algorithm.
>>> I don't understand. Please explain better.
>> In the following snippet:
>>       Interface interfaceA{}
>>       class C:interfaceA{}
>>       class D:interfaceA{}
>>
>>       interfaceA[] registry;
>>       register(interfaceA a) { registry ~= a; }
>>       unregister(interfaceA a) {idx = registry.indexOf(a); registry.replace(idx,
>> idx+1, null); }
>> In the above statement indexOf does not work.
>>
>
> You should use 'is' for such kind of thing. The problem is that == uses opEquals or opCmp, there is no such thing for interfaces AFIKT. But for every pointer like type we can check if they are the same with 'is'.

This is hardly a solution.  He wants to do value comparison, not identity comparison.

The real fix is to make interface assume it is an Object, so it can be implicitly cast to Object, and find another way to implement COM interfaces.  The COM interface "hack" is way outdated and extremely harmful, esp. on OS' who *don't use COM*!  I can't see how the benefits it has outweigh the problems it causes.

-Steve
January 27, 2011
26.01.2011 16:54, Steven Schveighoffer пишет:
>
> This is hardly a solution.  He wants to do value comparison, not identity comparison.
>
> The real fix is to make interface assume it is an Object, so it can be implicitly cast to Object, and find another way to implement COM interfaces.  The COM interface "hack" is way outdated and extremely harmful, esp. on OS' who *don't use COM*!  I can't see how the benefits it has outweigh the problems it causes.
>
The recent discussion in D group about destructor order brought me to yet another question about interfaces.
Currently, functions that should accept classes as parameters, e.g. clear(), accept interfaces as well:

void clear(T)(T obj) if (is(T == class)) // note the constraint
{ /*...*/ }

interface I {}
class A : I {}
void main()
{
    I a = new A; // note that typeof(a) is I, not A
    clear(a);
}

This compiles. But raises a question: how come? If it is assumed that a reference to interface is not necessarily a D class instance, then it shouldn't. The fact that it compiles even more ambiguates the purpose and usage of interfaces.
I agree with Steven. Having a support for COM, CORBA and so on in the language is great, but wouldn't it be better to specify it explicitly? Maybe solidify the usage of 'extern' keyword?

interface D {} // instances are guaranteed to be D Objects
extern interface E {} // instances may or may not be D Objects (COM and alike)

I mean, it's already there in the language and is described in 'Interfacing to C++' in the documentation. Though currently, extern interfaces are accepted by is(T == class) constraint as well.
January 27, 2011
26.01.2011 16:54, Steven Schveighoffer пишет:
>
> This is hardly a solution.  He wants to do value comparison, not identity comparison.
>
> The real fix is to make interface assume it is an Object, so it can be implicitly cast to Object, and find another way to implement COM interfaces.  The COM interface "hack" is way outdated and extremely harmful, esp. on OS' who *don't use COM*!  I can't see how the benefits it has outweigh the problems it causes.
>
The recent discussion in D group about destructor order brought me to
yet another question about interfaces.
Currently, functions that should accept classes as parameters, e.g.
clear(), accept interfaces as well:

void clear(T)(T obj) if (is(T == class)) // note the constraint
{ /*...*/ }

interface I {}
class A : I {}
void main()
{
     I a = new A; // note that typeof(a) is I, not A
     clear(a);
}

This compiles. But raises a question: how come? If it is assumed that a
reference to interface is not necessarily a D class instance, then it
shouldn't. The fact that it compiles even more ambiguates the purpose
and usage of interfaces.
I agree with Steven. Having a support for COM, CORBA and so on in the
language is great, but wouldn't it be better to specify it explicitly?
Maybe solidify the usage of 'extern' keyword?

interface D {} // instances are guaranteed to be D Objects
extern interface E {} // instances may or may not be D Objects (COM and
alike)

I mean, it's already there in the language and is described in 'Interfacing to C++' in the documentation. Though currently, extern interfaces are accepted by is(T == class) constraint as well.


Second this thought. Interface IMHO are far too basic for a functionality tweak. Would also like to understand the way to raise such requests and take them to their logical conclusion.

Regards
Mandeep

January 27, 2011
On 01/27/2011 09:27 PM, Mandeep Singh Brar wrote:
> 26.01.2011 16:54, Steven Schveighoffer пишет:
>>
>> This is hardly a solution.  He wants to do value comparison, not
>> identity comparison.
>>
>> The real fix is to make interface assume it is an Object, so it can be
>> implicitly cast to Object, and find another way to implement COM
>> interfaces.  The COM interface "hack" is way outdated and extremely
>> harmful, esp. on OS' who *don't use COM*!  I can't see how the
>> benefits it has outweigh the problems it causes.
>>
> The recent discussion in D group about destructor order brought me to
> yet another question about interfaces.
> Currently, functions that should accept classes as parameters, e.g.
> clear(), accept interfaces as well:
>
> void clear(T)(T obj) if (is(T == class)) // note the constraint
> { /*...*/ }
>
> interface I {}
> class A : I {}
> void main()
> {
>       I a = new A; // note that typeof(a) is I, not A
>       clear(a);
> }
>
> This compiles. But raises a question: how come? If it is assumed that a
> reference to interface is not necessarily a D class instance, then it
> shouldn't. The fact that it compiles even more ambiguates the purpose
> and usage of interfaces.
> I agree with Steven. Having a support for COM, CORBA and so on in the
> language is great, but wouldn't it be better to specify it explicitly?
> Maybe solidify the usage of 'extern' keyword?
>
> interface D {} // instances are guaranteed to be D Objects
> extern interface E {} // instances may or may not be D Objects (COM and
> alike)
>
> I mean, it's already there in the language and is described in
> 'Interfacing to C++' in the documentation. Though currently, extern
> interfaces are accepted by is(T == class) constraint as well.
>
>
> Second this thought. Interface IMHO are far too basic for a functionality tweak.
> Would also like to understand the way to raise such requests and take them to
> their logical conclusion.
>
> Regards
> Mandeep
>
There is bugzilla: d.puremagic.com/issues. You can create enhancement requests there along with bugreports.
January 28, 2011
On Thu, 27 Jan 2011 09:26:28 -0500, Stanislav Blinov <blinov@loniir.ru> wrote:

> 26.01.2011 16:54, Steven Schveighoffer пишет:
>>
>> This is hardly a solution.  He wants to do value comparison, not identity comparison.
>>
>> The real fix is to make interface assume it is an Object, so it can be implicitly cast to Object, and find another way to implement COM interfaces.  The COM interface "hack" is way outdated and extremely harmful, esp. on OS' who *don't use COM*!  I can't see how the benefits it has outweigh the problems it causes.
>>
> The recent discussion in D group about destructor order brought me to yet another question about interfaces.
> Currently, functions that should accept classes as parameters, e.g. clear(), accept interfaces as well:
>
> void clear(T)(T obj) if (is(T == class)) // note the constraint
> { /*...*/ }
>
> interface I {}
> class A : I {}
> void main()
> {
>      I a = new A; // note that typeof(a) is I, not A
>      clear(a);
> }
>
> This compiles. But raises a question: how come? If it is assumed that a reference to interface is not necessarily a D class instance, then it shouldn't. The fact that it compiles even more ambiguates the purpose and usage of interfaces.
> I agree with Steven. Having a support for COM, CORBA and so on in the language is great, but wouldn't it be better to specify it explicitly? Maybe solidify the usage of 'extern' keyword?
>
> interface D {} // instances are guaranteed to be D Objects
> extern interface E {} // instances may or may not be D Objects (COM and alike)
>
> I mean, it's already there in the language and is described in 'Interfacing to C++' in the documentation. Though currently, extern interfaces are accepted by is(T == class) constraint as well.

It's because everywhere in the compiler, an interface is considered a class (I think even the type representing an interface is derived from the type representing class).  Except one, and that's implicit casting to Object.

My thought is, we already have extern(C++) interface, why not extern(COM) interface?  But we could even leave the notion of interfaces deriving from IUnknown as COM interfaces and just have the compiler check if an interface derives from IUnknown.  In fact, it *ALREADY DOES THIS* because it has to treat the layout of an IUnknown interface differently from another interface.  The whole argument to have interfaces not derive from Object because of COM is standing on such poor footing that I can't see how it's taken this long to fix.

-Steve