Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 16:01:29 UTC, Paul Backus wrote: On Tuesday, 16 June 2020 at 13:31:49 UTC, Atila Neves wrote: With a few changes, yes (added missing semicolons, changed IGeometry to Geometry in `measure`, passed the current module so tardy can find the UFCS functions, added `@safe pure` to the UFCS functions: [...] void main() { auto r = Rect(3.0, 4.0); auto c = Circle(5.0); Geometry.create!__MODULE__(r).measure; Geometry.create!__MODULE__(c).measure; } IMO this can be done more elegantly by separating out the code that looks up methods in the current module from the code that does the actual type erasure. A while ago, I collaborated briefly with Adam Kowalski from the Dlang discord server on some code to emulate C++-style argument-dependent lookup in D. Using that code, your example above would be written: Geometry.create(r.extended).measure; Geometry.create(c.extended).measure; Interesting. The issue I see here is you might not be able to control which module has the extension methods. I guess you could alias them in the module you want to use but that seems clumsy. In any case, this is trivial: template extended(string mod = __MODULE__) { auto extended(A...)(auto ref A args) { return create!mod(args); } }
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On 6/17/20 7:19 AM, Atila Neves wrote: On Wednesday, 17 June 2020 at 10:43:35 UTC, Stanislav Blinov wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: Tardy lets users have their cake and eat it too by not making them have to use classes for runtime polymorphism. I've got to ask though. Why "tardy"? Search engines be damned? :) Late binding ;) Love the name.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 16:01:29 UTC, Paul Backus wrote: A while ago, I collaborated briefly with Adam Kowalski from the Dlang discord server on some code to emulate C++-style argument-dependent lookup in D. Using that code, your example above would be written: Geometry.create(r.extended).measure; Geometry.create(c.extended).measure; Here's a gist with the code, along with a small example: https://gist.github.com/pbackus/0a70419eb8bece52f3a08edfe7b6019b If anyone thinks it's worthwhile, I can toss this up on Dub. Personally, I've never had much use for it in my own projects. Yeah I can see a use for this. If have had to refactor things before because I was hitting this restriction.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 16:01:29 UTC, Paul Backus wrote: [snip] IMO this can be done more elegantly by separating out the code that looks up methods in the current module from the code that does the actual type erasure. A while ago, I collaborated briefly with Adam Kowalski from the Dlang discord server on some code to emulate C++-style argument-dependent lookup in D. Using that code, your example above would be written: Geometry.create(r.extended).measure; Geometry.create(c.extended).measure; Here's a gist with the code, along with a small example: https://gist.github.com/pbackus/0a70419eb8bece52f3a08edfe7b6019b If anyone thinks it's worthwhile, I can toss this up on Dub. Personally, I've never had much use for it in my own projects. The syntax there looks nice (wouldn't hurt to make it even nicer!). Your moduleOf (and associated functions) looks like it shares similar functionality as some of what is in vtableImpl in poly.d (particularly importMixin).
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 13:31:49 UTC, Atila Neves wrote: With a few changes, yes (added missing semicolons, changed IGeometry to Geometry in `measure`, passed the current module so tardy can find the UFCS functions, added `@safe pure` to the UFCS functions: [...] void main() { auto r = Rect(3.0, 4.0); auto c = Circle(5.0); Geometry.create!__MODULE__(r).measure; Geometry.create!__MODULE__(c).measure; } IMO this can be done more elegantly by separating out the code that looks up methods in the current module from the code that does the actual type erasure. A while ago, I collaborated briefly with Adam Kowalski from the Dlang discord server on some code to emulate C++-style argument-dependent lookup in D. Using that code, your example above would be written: Geometry.create(r.extended).measure; Geometry.create(c.extended).measure; Here's a gist with the code, along with a small example: https://gist.github.com/pbackus/0a70419eb8bece52f3a08edfe7b6019b If anyone thinks it's worthwhile, I can toss this up on Dub. Personally, I've never had much use for it in my own projects.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 11:46:12 UTC, Atila Neves wrote: [snip] I think these questions are good motivators for making it interface-only since then I don't have to check for data definitions. Makes sense.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 11:31:09 UTC, jmh530 wrote: On Wednesday, 17 June 2020 at 10:04:59 UTC, Atila Neves wrote: [...] Cool. [...] If I'm understanding you correctly, you could modify Polymorphic (and a similar change to VirtualTable) to struct Polymorphic(Interface, InstanceAllocator = DefaultAllocator) if(is(Interface == interface) || is(Interface == class) || is(Interface == struct)) and the current functionality would still work. However, compared to normal inheritance, it would be missing the "base" class's member variables that don't exist in the "derived" one. You also couldn't call the "base" class member functions. Polymorphic is assuming the member functions are all implemented in the instance passed to it, correct? I think these questions are good motivators for making it interface-only since then I don't have to check for data definitions.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 10:04:59 UTC, Atila Neves wrote: [snip] I was going to say "it should work" but instead I wrote the code and... it does. It all falls out of how UFCS works and usual language rules. https://github.com/atilaneves/tardy/blob/feb26282608081098134c8846be87d398772ccb0/tests/ut/polymorphic.d#L102 https://github.com/atilaneves/tardy/blob/feb26282608081098134c8846be87d398772ccb0/tests/modules/ufcs/template_.d Cool. Am I right that the shared static constructor in vtable means that there is one vtable for all the instances? All instances of the same concrete type share the same vtable pointer, yes. Originally I built the vtable on the spot with `new` and assigned to each function pointer but then I realised that was a waste of time and allocations - the vtable is unique per concrete type. Are there any technical issues preventing Polymorphism from accepting a class in addition to an interface? None. It could even accept a struct, really. If I'm understanding you correctly, you could modify Polymorphic (and a similar change to VirtualTable) to struct Polymorphic(Interface, InstanceAllocator = DefaultAllocator) if(is(Interface == interface) || is(Interface == class) || is(Interface == struct)) and the current functionality would still work. However, compared to normal inheritance, it would be missing the "base" class's member variables that don't exist in the "derived" one. You also couldn't call the "base" class member functions. Polymorphic is assuming the member functions are all implemented in the instance passed to it, correct? I suppose I was more asking if there were any issues preventing the ability to get these things to work. In other words, Polymorphism works with interfaces now and the behavior is like inheriting from an interface. Could it work for classes (and by implication structs), such that the behavior is like inheriting from classes, and not just treating the class like an interface. In the case of structs, which may be a little simpler to implement than classes, something as simple as below might be able to get this functionality working. static if (Interface == struct) { Interface base; alias base this; } so that member variables and functions missing from the instance can get forwarded to the alias this. Though this wouldn't handle super constructors.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Wednesday, 17 June 2020 at 10:43:35 UTC, Stanislav Blinov wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: Tardy lets users have their cake and eat it too by not making them have to use classes for runtime polymorphism. I've got to ask though. Why "tardy"? Search engines be damned? :) Late binding ;)
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: Tardy lets users have their cake and eat it too by not making them have to use classes for runtime polymorphism. I've got to ask though. Why "tardy"? Search engines be damned? :)
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 15:50:07 UTC, jmh530 wrote: On Tuesday, 16 June 2020 at 13:31:49 UTC, Atila Neves wrote: [snip] Pretty cool, thanks for the fixups. It may make for a good documentation example, in that it may help make clear that you need to pass the module in somehow when dealing with non-member functions (AFAICT). You could include a comment about how it would be different if it were split into separate files. Good point. In your original example, is there any issue if we then make transform a templated non-member function that is generic over types like Adder (maybe there is an enum hasAddableMember that is true for Adder and false for Plus1)? I was going to say "it should work" but instead I wrote the code and... it does. It all falls out of how UFCS works and usual language rules. https://github.com/atilaneves/tardy/blob/feb26282608081098134c8846be87d398772ccb0/tests/ut/polymorphic.d#L102 https://github.com/atilaneves/tardy/blob/feb26282608081098134c8846be87d398772ccb0/tests/modules/ufcs/template_.d Am I right that the shared static constructor in vtable means that there is one vtable for all the instances? All instances of the same concrete type share the same vtable pointer, yes. Originally I built the vtable on the spot with `new` and assigned to each function pointer but then I realised that was a waste of time and allocations - the vtable is unique per concrete type. Are there any technical issues preventing Polymorphism from accepting a class in addition to an interface? None. It could even accept a struct, really.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 13:31:49 UTC, Atila Neves wrote: [snip] Pretty cool, thanks for the fixups. It may make for a good documentation example, in that it may help make clear that you need to pass the module in somehow when dealing with non-member functions (AFAICT). You could include a comment about how it would be different if it were split into separate files. I have a few more questions... In your original example, is there any issue if we then make transform a templated non-member function that is generic over types like Adder (maybe there is an enum hasAddableMember that is true for Adder and false for Plus1)? Am I right that the shared static constructor in vtable means that there is one vtable for all the instances? Are there any technical issues preventing Polymorphism from accepting a class in addition to an interface?
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 12:30:24 UTC, jmh530 wrote: On Tuesday, 16 June 2020 at 11:31:14 UTC, Atila Neves wrote: On Tuesday, 16 June 2020 at 11:24:05 UTC, jmh530 wrote: On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote: [snip] In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions? So does tardy. Sorry, I had not realized that. I took Go's interface example and converted it to D. Would this work with tardy? With a few changes, yes (added missing semicolons, changed IGeometry to Geometry in `measure`, passed the current module so tardy can find the UFCS functions, added `@safe pure` to the UFCS functions: import tardy; interface IGeometry { double area() @safe pure const; double perim() @safe pure const; } alias Geometry = Polymorphic!IGeometry; struct Rect { double width, height; } struct Circle { double radius; } double area(Rect r) @safe pure { return r.width * r.height; } double perim(Rect r) @safe pure { return 2 * r.width + 2 * r.height; } double area(Circle c) @safe pure { import std.math: PI; return PI * c.radius * c.radius; } double perim(Circle c) @safe pure { import std.math: PI; return 2 * PI * c.radius; } void measure(Geometry g) { import std.stdio: writeln; writeln(g); writeln(g.area); writeln(g.perim); } void main() { auto r = Rect(3.0, 4.0); auto c = Circle(5.0); Geometry.create!__MODULE__(r).measure; Geometry.create!__MODULE__(c).measure; }
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 12:30:24 UTC, jmh530 wrote: [snip] double area(Rect r) { return r.width * r.height } double perim(Rect r) { return 2 * r.width + 2 * r.height } double area(Circle c) { import std.math: PI; return PI * c.radius * c.radius } double perim(Circle c) { import std.math: PI; return 2 * PI * c.radius } These should be @safe pure.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 11:31:14 UTC, Atila Neves wrote: On Tuesday, 16 June 2020 at 11:24:05 UTC, jmh530 wrote: On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote: [snip] In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions? So does tardy. Sorry, I had not realized that. I took Go's interface example and converted it to D. Would this work with tardy? ``` import tardy; interface IGeometry { double area() @safe pure const; double perim() @safe pure const; } alias Geometry = Polymorphic!IGeometry; struct Rect { double width, height; } struct Circle { double radius; } double area(Rect r) { return r.width * r.height } double perim(Rect r) { return 2 * r.width + 2 * r.height } double area(Circle c) { import std.math: PI; return PI * c.radius * c.radius } double perim(Circle c) { import std.math: PI; return 2 * PI * c.radius } void measure(IGeometry g) { import std.stdio: writeln; writeln(g); writeln(g.area); writeln(g.perim); } void main() { auto r = Rect(3.0, 4.0); auto c = Circle(5.0); r.Geometry.measure; c.Geometry.measure; } ``` That is a little bit more similar to open methods. This requires the type inherit from the interface and implement member functions. There is no inheritance anywhere, otherwise that'd defeat the point of the library in the first place. I used interfaces because they exist and intuively make sense, and support classes because why not. Otherwise it could be just structs and other values with candidate UFCS functions. Sorry, that was me being hasty. I was just concerned about the member functions part of it, which you said above is not a concern.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 11:24:05 UTC, jmh530 wrote: On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote: [snip] In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions? So does tardy. That is a little bit more similar to open methods. This requires the type inherit from the interface and implement member functions. There is no inheritance anywhere, otherwise that'd defeat the point of the library in the first place. I used interfaces because they exist and intuively make sense, and support classes because why not. Otherwise it could be just structs and other values with candidate UFCS functions. I'm not that knowledgeable of Boost, but I see some similarities with Boost's type_erasure library. However, one main difference is that it is implemented with concepts, rather than the equivalent of interfaces. I would guess using interfaces has some benefits in terms of implementation since you know exactly what functions need to be called. Something like @models is very flexible, but that might be a downside. Using an interface means using familiar syntax with the added benefits of being able to write a signature like this: int* fun(int*, int) @safe @nogc pure return scope const; And then have all of those attributes and `this` modifiers used in the vtable function pointer declarations. Overloading and UFCS get dealt with naturally by usual language rules.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote: [snip] In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions? That is a little bit more similar to open methods. This requires the type inherit from the interface and implement member functions. Also how would it compare to Rust traits? Rust's traits are usually used like D's template contraints and Haskell's type classes. The only way they're relevant here are trait objects: https://doc.rust-lang.org/reference/types/trait-object.html [snip] Similar to above, aren't Rusts's trait objects defined using separate impl blocks, rather than as member functions. --- I'm not that knowledgeable of Boost, but I see some similarities with Boost's type_erasure library. However, one main difference is that it is implemented with concepts, rather than the equivalent of interfaces. I would guess using interfaces has some benefits in terms of implementation since you know exactly what functions need to be called. Something like @models is very flexible, but that might be a downside.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote: On Tuesday, 16 June 2020 at 03:56:52 UTC, Petar Kirov [ZombineDev] wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Looks interesting, nice work! How does it compare to: https://dlang.org/phobos/std_experimental_typecons#.wrap ? For starters, that uses a class and inheritance internally and therefore has all the drawbacks of that approach as laid out in tardy's README.md. Then there's the lack of allocator support. In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. Cool! Also how would it compare to Rust traits? Rust's traits are usually used like D's template contraints and Haskell's type classes. The only way they're relevant here are trait objects: Yes I meant trait objects actually. https://doc.rust-lang.org/reference/types/trait-object.html The main difference is that tardy is supposed to give the user choices over how the dispatch is actually implemented. Allocators alone are huge. Interesting! I guess the main difference, would be that Rust enforces a nominal type system like approach, where 2 differently named traits that otherwise define the same interface are not considered interchangeable. Yes, that's also a difference.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Tuesday, 16 June 2020 at 03:56:52 UTC, Petar Kirov [ZombineDev] wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Looks interesting, nice work! How does it compare to: https://dlang.org/phobos/std_experimental_typecons#.wrap ? For starters, that uses a class and inheritance internally and therefore has all the drawbacks of that approach as laid out in tardy's README.md. Then there's the lack of allocator support. In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Yes. Other than allowing multiple interfaces, I think it's already implemented. Also how would it compare to Rust traits? Rust's traits are usually used like D's template contraints and Haskell's type classes. The only way they're relevant here are trait objects: https://doc.rust-lang.org/reference/types/trait-object.html The main difference is that tardy is supposed to give the user choices over how the dispatch is actually implemented. Allocators alone are huge. I guess the main difference, would be that Rust enforces a nominal type system like approach, where 2 differently named traits that otherwise define the same interface are not considered interchangeable. Yes, that's also a difference.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Monday, 15 June 2020 at 20:47:16 UTC, 12345swordy wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...] Wouldn't a top type be a better way to achieve this? -Alex How?
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Looks interesting, nice work! How does it compare to: https://dlang.org/phobos/std_experimental_typecons#.wrap ? In the more longer-term, is the goal of the project to implement a Typescript / Go interfaces like structural type system in user space? Also how would it compare to Rust traits? I guess the main difference, would be that Rust enforces a nominal type system like approach, where 2 differently named traits that otherwise define the same interface are not considered interchangeable.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Monday, 15 June 2020 at 20:54:27 UTC, 12345swordy wrote: On Monday, 15 June 2020 at 20:51:38 UTC, Stefan Koch wrote: On Monday, 15 June 2020 at 20:47:16 UTC, 12345swordy wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...] Wouldn't a top type be a better way to achieve this? -Alex the Talias in type functions is a top type. (If I do understand correctly that it is something it's another word for an Any type.) it's a pain in the ass, to work with if you are not dynamically typed language. Speaking of type functions, have you been working on a dip for that? I am quite curious to see what it looks like currently. -Alex Oh no, I haven't. And I am not really a visionary. I am trying to solve a few concrete problems. To language addition is a means to an end, for a DIP which is is supposed to consider the language at large, I would need help. Furthermore, I have to see how the implementation plays out. It would be unwise to spec something that I couldn't implement.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Monday, 15 June 2020 at 20:51:38 UTC, Stefan Koch wrote: On Monday, 15 June 2020 at 20:47:16 UTC, 12345swordy wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...] Wouldn't a top type be a better way to achieve this? -Alex the Talias in type functions is a top type. (If I do understand correctly that it is something it's another word for an Any type.) it's a pain in the ass, to work with if you are not dynamically typed language. Speaking of type functions, have you been working on a dip for that? I am quite curious to see what it looks like currently. -Alex
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Monday, 15 June 2020 at 20:47:16 UTC, 12345swordy wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...] Wouldn't a top type be a better way to achieve this? -Alex the Talias in type functions is a top type. (If I do understand correctly that it is something it's another word for an Any type.) it's a pain in the ass, to work with if you are not dynamically typed language.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...] Wouldn't a top type be a better way to achieve this? -Alex
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Monday, 15 June 2020 at 14:12:17 UTC, Atila Neves wrote: [snip] Yep: https://github.com/atilaneves/tardy/blob/d5f1102a6a791e77e0a27ee1a7920166fba8fcc8/tests/ut/polymorphic.d#L222 Thanks, I missed that.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 18:39:14 UTC, Paul Backus wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Cool stuff! What's the reasoning behind implementing your own vtables instead of using D's built-in object system? Don't want to be stuck inheriting from Object? That's one reason, but even more importantly this gives the implementation more freedom and potentially more options for client code. I haven't added it yet (mostly due to laziness) but I considered compile-time policies to inline the vtable in the object, or to determine ordering of the vtable and the implementation (might have performance considerations), and a few other things. Also: more fun to implement, and shows that it can be done as a library.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 16:15:49 UTC, jmh530 wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [snip] This is pretty cool. Thanks for sharing. I have a few questions/comments: 1) It might make a good blog post at some point to discuss this and the performance (perhaps with reference to the earlier open methods blog post). I actually need to benchmark it though! 2) It looks like Polymorphic can only take one interface. Would you consider adding the ability to have more than one? I suppose a work-around would be to combine all the interfaces you would want to use into a new interface before combining. I... completely forgot about that, thanks for bringing it up. 3) Do arrays work, as in Transformer(Adder(2), Plus1()) or [Transformer(Adder(2)), Transformer(Plus1())] Yep: https://github.com/atilaneves/tardy/blob/d5f1102a6a791e77e0a27ee1a7920166fba8fcc8/tests/ut/polymorphic.d#L222
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy If this is what you say, it could be used for object-oriented programing with types that are not designed as objects. Not only that, in principle the design should work even at a bare-metal platform as I understand it. I know that practical corner cases would prevent doing the latter without extra work, but impressive nonetheless.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On 6/13/20 2:39 PM, Paul Backus wrote: On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Cool stuff! What's the reasoning behind implementing your own vtables instead of using D's built-in object system? Don't want to be stuck inheriting from Object? FWIW that could be avoided with extern(C++) classes.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Cool stuff! What's the reasoning behind implementing your own vtables instead of using D's built-in object system? Don't want to be stuck inheriting from Object?
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: Tardy lets users have their cake and eat it too by not making them have to use classes for runtime polymorphism. This is one of those things that is so obvious in hindsight. Genius.
Re: tardy v0.0.1 - Runtime polymorphism without inheritance
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [snip] This is pretty cool. Thanks for sharing. I have a few questions/comments: 1) It might make a good blog post at some point to discuss this and the performance (perhaps with reference to the earlier open methods blog post). 2) It looks like Polymorphic can only take one interface. Would you consider adding the ability to have more than one? I suppose a work-around would be to combine all the interfaces you would want to use into a new interface before combining. 3) Do arrays work, as in Transformer(Adder(2), Plus1()) or [Transformer(Adder(2)), Transformer(Plus1())]
tardy v0.0.1 - Runtime polymorphism without inheritance
https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy Tardy lets users have their cake and eat it too by not making them have to use classes for runtime polymorphism. No inheritance anywhere to be found, which means structs, ints, and arrays can be used with dynamic dispatch (classes as well). It uses the GC by default but users can specify their own allocator type for flexibility, including a built-in "small buffer optimisation" allocator. Sample usage code: import tardy; interface ITransformer { int transform(int) @safe pure const; } alias Transformer = Polymorphic!ITransformer; int xform(Transformer t) { return t.transform(3); } struct Adder { int i; int transform(int j) @safe pure const { return i + j; } } struct Plus1 { int transform(int i) @safe pure const { return i + 1; } } unittest { assert(xform(Transformer(Adder(2))) == 5); assert(xform(Transformer(Adder(3))) == 6); assert(xform(Transformer(Plus1())) == 4); }