www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - where to find Implements!

reply BLS <windevguy hotmail.de> writes:
Hope is was not a pipe dream...
I've no idea who has published it and where to find this snippet but in 
case that I am not completely wrong there should exist something like 
Implements!() for structures..
???
Bjoern
Sep 29 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 11:58:01 BLS wrote:
 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..
 ???
 Bjoern

And what would the implement? I thought that structs didn't work with interfaces. And if they did, you'd use is() with : to test that. So, what are you really looking for here? What would Implements!() do if it exists? - Jonathan M Davis
Sep 29 2010
parent reply BLS <windevguy hotmail.de> writes:
On 29/09/2010 21:19, Jonathan M Davis wrote:
 On Wednesday, September 29, 2010 11:58:01 BLS wrote:
 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..
 ???
 Bjoern

And what would the implement? I thought that structs didn't work with interfaces. And if they did, you'd use is() with : to test that. So, what are you really looking for here? What would Implements!() do if it exists? - Jonathan M Davis

Just because structures don't work with interfaces I am still hoping for Implements!(). What do I expect from Implements! A contract which ensures (at compile time) that a structure implements f.i. all functions required by a random access range. well, as said, I'm not even sure that Implements! exist at all. bjoern
Sep 29 2010
next sibling parent BLS <windevguy hotmail.de> writes:
On 29/09/2010 22:22, Steven Schveighoffer wrote:
 On Wed, 29 Sep 2010 16:14:27 -0400, BLS <windevguy hotmail.de> wrote:

 On 29/09/2010 21:19, Jonathan M Davis wrote:
 On Wednesday, September 29, 2010 11:58:01 BLS wrote:
 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..
 ???
 Bjoern

And what would the implement? I thought that structs didn't work with interfaces. And if they did, you'd use is() with : to test that. So, what are you really looking for here? What would Implements!() do if it exists? - Jonathan M Davis

Just because structures don't work with interfaces I am still hoping for Implements!(). What do I expect from Implements! A contract which ensures (at compile time) that a structure implements f.i. all functions required by a random access range. well, as said, I'm not even sure that Implements! exist at all. bjoern

Well, there are the isRandomAccessRange and friends, I think that's the standard mode of operation for testing if a struct implements a particular compile-time interface. The thing is, there's no syntax to *define* a compile-time interface except this way :) So Implements!(myStruct, ???) Where ??? is the compile time interface, what do you pass in there? -Steve

Implements!(*I*MyInterface) // where IMyInterface is a plain vanilla Interface This was at least my hope 'cause IMHO this could make just f.i. the range stuff more reliable. Unfortunately we are not able to use classes to implement the basic data-structures for collections/graphs. if we could use class Node, class Tree : IxRange, class Map : Tree ... Bjoern ps have send you an email
Sep 29 2010
prev sibling parent reply BLS <windevguy hotmail.de> writes:
On 29/09/2010 22:28, Jonathan M Davis wrote:
 Look in
 std.range for the whole list, but isRandomAccesRange() handles random access
 ranges. Since there is no interface for ranges, you can't check generically
 whether a particular type correctly implements a particular range type - e.g
 is(mystruct : RandomAccessRange) or implements!(RandomAccessRange, mystrucT).

Thanks ! This is already something. (not exactly what I am looking/hoping for) why we don't have /struct A implements IA {}/ by the way.
Sep 29 2010
next sibling parent =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

BLS wrote:
 On 29/09/2010 22:28, Jonathan M Davis wrote:
 Look in
 std.range for the whole list, but isRandomAccesRange() handles random
 access
 ranges. Since there is no interface for ranges, you can't check
 generically
 whether a particular type correctly implements a particular range type=


 - e.g
 is(mystruct : RandomAccessRange) or implements!(RandomAccessRange,
 mystrucT).

=20 Thanks ! This is already something. (not exactly what I am looking/hoping for) =20 why we don't have /struct A implements IA {}/ by the way.

Lots of people have already answered why you can't have a struct "inheriting" from an interface, but there is nothing that prevents you from having a struct which includes all the functions defined by the interface. Given the capabilities of D for compile-time introspection, it should even be possible to write implements!(Interface, Struct) by having it enumerating the functions of the interface and checking for their presence in the struct. Kind of a duck-typing where the "duck" is defined by an interface: interface IFoo { void foo(); } struct SFoo { void foo() { writeln ("SFoo.foo"); } } template TFoo (T) if structImplements!(T, IFoo) { IFoo convert (T value) { return (IFoo)value; // Wrong because T does not inherit // from IFoo } void foo (T value) { value.foo(); // Right because T duck-implements IFoo } } This probably won't bring much above and over what would happen without the template constraint (after all, the compiler will already check that "value.foo()" is valid), but it can bring a lot in terms of documentation. Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Sep 30 2010
prev sibling parent reply BLS <windevguy hotmail.de> writes:
On 30/09/2010 00:40, Jonathan M Davis wrote:
 hich has the appropriate methods will work for any function that
 requires a particular API on the type or types that it's dealing with. There's
 no need to have any interfaces. They just work if they have the correct API and
 don't work if they don't. The isRandomAccessRange() template and its friends
are
 used in template constraints to improve the error messages you get when a type
 doesn't have the correct API, but they aren't strictly-speaking necessary.

Thanks you for taking the time to explain, Jonathan! It seems however, that these template constraints are just made for ranges. I maybe wrong but I can't see a general purpose value. I am also not able to see why an additional vtable entry is necessary to do ordinary /implements/ validation work. (Finally it is just a contract, which Mr compiler should negotiate) Bjoern
Oct 03 2010
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
I should probably add that using == as an addition to < was a poor example, 
since all types in D have ==. So, you can either imagine that I said some 
function other than == or that there are types which don't have ==. The basic 
principle still stands regardless.

- Jonathan M Davis
Oct 03 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 29 Sep 2010 16:14:27 -0400, BLS <windevguy hotmail.de> wrote:

 On 29/09/2010 21:19, Jonathan M Davis wrote:
 On Wednesday, September 29, 2010 11:58:01 BLS wrote:
 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..
 ???
 Bjoern

And what would the implement? I thought that structs didn't work with interfaces. And if they did, you'd use is() with : to test that. So, what are you really looking for here? What would Implements!() do if it exists? - Jonathan M Davis

Just because structures don't work with interfaces I am still hoping for Implements!(). What do I expect from Implements! A contract which ensures (at compile time) that a structure implements f.i. all functions required by a random access range. well, as said, I'm not even sure that Implements! exist at all. bjoern

Well, there are the isRandomAccessRange and friends, I think that's the standard mode of operation for testing if a struct implements a particular compile-time interface. The thing is, there's no syntax to *define* a compile-time interface except this way :) So Implements!(myStruct, ???) Where ??? is the compile time interface, what do you pass in there? -Steve
Sep 29 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 13:14:27 BLS wrote:
 On 29/09/2010 21:19, Jonathan M Davis wrote:
 On Wednesday, September 29, 2010 11:58:01 BLS wrote:
 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..
 ???
 Bjoern

And what would the implement? I thought that structs didn't work with interfaces. And if they did, you'd use is() with : to test that. So, what are you really looking for here? What would Implements!() do if it exists? - Jonathan M Davis

Hi Jonathan, Just because structures don't work with interfaces I am still hoping for Implements!(). What do I expect from Implements! A contract which ensures (at compile time) that a structure implements f.i. all functions required by a random access range. well, as said, I'm not even sure that Implements! exist at all. bjoern

There are specific eponymous templates for dealing with each range type. Look in std.range for the whole list, but isRandomAccesRange() handles random access ranges. Since there is no interface for ranges, you can't check generically whether a particular type correctly implements a particular range type - e.g is(mystruct : RandomAccessRange) or implements!(RandomAccessRange, mystrucT). There has to be a function specific to that range type. In this case, that's isRandomAccessRange(). - Jonathan M Davis
Sep 29 2010
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
BLS <windevguy hotmail.de> wrote:

 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in  
 case that I am not completely wrong there should exist something like  
 Implements!() for structures..

I wrote such a template about a year ago, when Leandro Lucarella asked for it: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=101673 Not sure it still works, but at least the code is there, and shouldn't be very hard to update. -- Simen
Sep 29 2010
parent BLS <windevguy hotmail.de> writes:
On 29/09/2010 23:02, Simen kjaeraas wrote:
 BLS <windevguy hotmail.de> wrote:

 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but
 in case that I am not completely wrong there should exist something
 like Implements!() for structures..

I wrote such a template about a year ago, when Leandro Lucarella asked for it: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=101673 Not sure it still works, but at least the code is there, and shouldn't be very hard to update.

(feel better now that I know it was not just a fantasy :) think the _traits(allMembers) stuff got a modification.
Sep 29 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Wed, Sep 29, 2010 at 23:02, Simen kjaeraas <simen.kjaras gmail.com> wrote:
 BLS <windevguy hotmail.de> wrote:

 Hope is was not a pipe dream...
 I've no idea who has published it and where to find this snippet but in
 case that I am not completely wrong there should exist something like
 Implements!() for structures..

I wrote such a template about a year ago, when Leandro Lucarella asked for it: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=101673 Not sure it still works, but at least the code is there, and shouldn't be very hard to update.

I see no reason why it shouldn't work, but I couldn't get it to compile. Some problem in allMembersToTypeTuple. Related to this, didn't dsimcha add something in Phobos recently, with InputRangeObject or so? Ah, here it is: http://digitalmars.com/d/2.0/phobos/std_range.html#OutputRange Philippe
Sep 29 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 13:58:05 BLS wrote:
 On 29/09/2010 22:28, Jonathan M Davis wrote:
 Look in
 std.range for the whole list, but isRandomAccesRange() handles random
 access ranges. Since there is no interface for ranges, you can't check
 generically whether a particular type correctly implements a particular
 range type - e.g is(mystruct : RandomAccessRange) or
 implements!(RandomAccessRange, mystrucT).

Thanks ! This is already something. (not exactly what I am looking/hoping for) why we don't have /struct A implements IA {}/ by the way.

Interfaces are reference types and involve the type's virtual table. structs are value types (though they can have reference semantics if they contain reference types and don't define a postblit constructor to do a deep copy), and I don't believe that they have a vtable. They can't have sub structs, so they're not polymorphic and so don't have virtual functions, so there's no need. With an interface, you're dealing with virtual functions, so you'd need a vtable. But the simple fact that passing around an interface would mean passing around a reference type means that it isn't going to work with structs. I believe that Andrei has said that it would be theoretically possible to make structs able to implement interfaces, but it would involve giving them virtual tables explicitly so that they could have interfaces (which would make structs less efficient in general, since using a vtable makes function calls slower, albeit negligibly) and making it so that you could have reference to a struct when that reference was an interface that the struct implemented. Both would be significant changes and could harm the overall performance of using structs. Phobos doesn't use interfaces. It uses duck typing. Any type - be it a struct or a class - which has the appropriate methods will work for any function that requires a particular API on the type or types that it's dealing with. There's no need to have any interfaces. They just work if they have the correct API and don't work if they don't. The isRandomAccessRange() template and its friends are used in template constraints to improve the error messages you get when a type doesn't have the correct API, but they aren't strictly-speaking necessary. If interfaces were used, it would mean less efficient code (since you'd have to use classes) and it would be far less flexible. As it is, any type - struct or class - with the appropriate API will work. - Jonathan M Davis
Sep 29 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, September 29, 2010 13:49:23 BLS wrote:
 Implements!(*I*MyInterface) // where IMyInterface is a plain vanilla
 Interface
 This was at least my hope 'cause IMHO this could make just f.i. the
 range stuff more reliable.

Except that there are no interfaces involved. Using isForwardRange(), isBidirectionalRange(), etc. works just fine and is quite reliable. Using interfaces wouldn't have helped any and would have been less flexible.
 
 Unfortunately we are not able to use classes to implement the basic
 data-structures for collections/graphs. if we could use class Node,
 class Tree : IxRange, class Map : Tree       ...

??? You can use both structs and classes to implement containers and ranges. And how the internals of a type work is completely up to the type. Now, structs are generally more efficient, so they're more likely to be used, but you can use classes just fine. - Jonathan M Davis
Sep 29 2010
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 03 October 2010 14:32:29 BLS wrote:
 On 30/09/2010 00:40, Jonathan M Davis wrote:
 hich has the appropriate methods will work for any function that
 requires a particular API on the type or types that it's dealing with.
 There's no need to have any interfaces. They just work if they have the
 correct API and don't work if they don't. The isRandomAccessRange()
 template and its friends are used in template constraints to improve the
 error messages you get when a type doesn't have the correct API, but
 they aren't strictly-speaking necessary.

Thanks you for taking the time to explain, Jonathan! It seems however, that these template constraints are just made for ranges. I maybe wrong but I can't see a general purpose value. I am also not able to see why an additional vtable entry is necessary to do ordinary /implements/ validation work. (Finally it is just a contract, which Mr compiler should negotiate) Bjoern

With an interface, you can declare a variable of that type. e.g. interface I { //... } class C : I { //... } void main() { I i = new C(); } The compiler then has to deal with the fact that a variable of an interface could be of any class that implements that interface. That requires a vtable. The duck typing that templates give you don't allow for anything of the sort. You can't declare a variable of type RandomAccessRange. A good example of templates and APIs would be a function that requires a particular type be compareable with the less-than operator: void func(T)(T a, T b) { //... if(a < b) //... } When func is instantiated with a given type, it will generate a copy of the template with that type. If the generated code is valid, it will compile. If it's not, it won't. So, func(5, 4) would create void func!int(int a, int b) { //... if(a < b) //... } which as far as we can see with the code given is legal and works. However, what if you have a struct S which doesn't implement opCmp() and therefore does not have a less-than operator? void func!S(S a, S b) { //.. if(a < b) //... } The generated code won't compile because a < b is not valid. And the error message may or may not be particularly clear. To improve the error message, we'd add a template constraint void func(T)(T a, T b) if(__traits(compiles, a < b)) { //... if(a < b) //... } Now the compiler won't even try and instantiate the template with a type that can't be compared with less-than. It will complain about the type not matching the template (because the template constraint isn't true). There is nothing here about implementing any sort of interface. There is nothing here about declaring variables of type CanBeComparedWithLessThan. There is no need for a vtable. Now, that's a fairly simple example, but what if you have a more complex one, that depending on the type either used == or <. void func(T)(T a, T b) if(__traits(compiles, a < b) || __traits(compiles, a == b)) { //... static if(__traits(compiles, a < b)) { //... if(a < b) //... } //... static if(__traits(compiles, a == b)) { //... if(a == b) //... } //... } The code that is generated and what the function actually does could change drastically depending on whether T has < or it has ==. You could even intermingle additional static ifs and/or static ifs that required both < and ==, so that the fact that T has both < and == could generate code that differed that much more. With that sort of power, you can do stuff way more complicated than require that a type have a particular function or set of functions. With an interface, the set of functions is fixed. With templates, it could vary. You could have two completely different set of APIs which both satisfy a particular template and there fore both have the "interface" that that template is looking for. Templates are all about code generation. They aren't implementing any kind of API or interface and they have no way to declare any kind of API in the same sense that D interfaces do. A D interface (or Java or C# or whatever) gives an _exact_ set of functions that a class implementing it must have in order to be of that interface type. You can then declare variables of that interface. templates, on the other hand, can use variable APIs, and you cannot declare variables of whatever "interface" their API represents. They're purely code generation. And how would you declare an "interface" for a template to test whether a type implements it? It's variable with the type. There could be several different APIs which would satisfy a template. Sure you could try and declare multiple interfaces, but you'd get a combinatorial explosion of them if you're talking about very many different functions. It could get ugly fast - _especially_ with ranges and all the different variations that you have there. Instead, all you have to do is create template or function which is used in a template constraint to check whether a given template argument will result in successful instantiation of that template. And really, what's worse about isForwardRange!(T) than is(T: ForwardRange) as far as writing your programs that use them goes? You don't gain anything by having the more generic syntax of is(T : ForwardRange). You'd still have to declare interface ForwardRange somewhere. Instead of declaring an interface that T is forced to implement, instead you declare a function which checks that T has the functions that it's supposed to. It's not even really more work if you're the one writing isForwardRange!() vs interface ForwardRange. It's just an eponymous template instead of an interface. The biggest difference is Interfaces are for declaring types with a certain API and allow variables of that type which use polymorphism. Templates with template constraints generate code given a particular set of template arguments as long as those template arguments result in the template's constraint being true. There is no type declared or polymorphism involved. - Jonathan M Davis
Oct 03 2010