digitalmars.D.announce - tardy v0.0.1 - Runtime polymorphism without inheritance
- Atila Neves (29/29) Jun 13 2020 https://code.dlang.org/packages/tardy
- jmh530 (12/15) Jun 13 2020 This is pretty cool. Thanks for sharing.
- Atila Neves (5/21) Jun 15 2020 I... completely forgot about that, thanks for bringing it up.
- jmh530 (2/5) Jun 15 2020 Thanks, I missed that.
- Sebastiaan Koppe (3/5) Jun 13 2020 This is one of those things that is so obvious in hindsight.
- Paul Backus (5/7) Jun 13 2020 Cool stuff!
- Andrei Alexandrescu (2/12) Jun 13 2020 FWIW that could be avoided with extern(C++) classes.
- Atila Neves (10/18) Jun 15 2020 That's one reason, but even more importantly this gives the
- Dukc (7/9) Jun 14 2020 If this is what you say, it could be used for object-oriented
- 12345swordy (3/6) Jun 15 2020 Wouldn't a top type be a better way to achieve this?
- Stefan Koch (5/12) Jun 15 2020 the Talias in type functions is a top type. (If I do understand
- 12345swordy (4/18) Jun 15 2020 Speaking of type functions, have you been working on a dip for
- Stefan Koch (7/26) Jun 15 2020 Oh no, I haven't. And I am not really a visionary.
- Atila Neves (2/9) Jun 16 2020 How?
- Petar Kirov [ZombineDev] (10/12) Jun 15 2020 Looks interesting, nice work!
- Atila Neves (15/30) Jun 16 2020 For starters, that uses a class and inheritance internally and
- Petar Kirov [ZombineDev] (4/36) Jun 16 2020 Yes I meant trait objects actually.
- jmh530 (16/27) Jun 16 2020 I'm not familiar with what Typescript does, but doesn't Go allow
- Atila Neves (13/33) Jun 16 2020 There is no inheritance anywhere, otherwise that'd defeat the
- jmh530 (47/68) Jun 16 2020 Sorry, I had not realized that. I took Go's interface example and
- jmh530 (2/18) Jun 16 2020 These should be @safe pure.
-
Atila Neves
(45/62)
Jun 16 2020
- jmh530 (16/17) Jun 16 2020 Pretty cool, thanks for the fixups.
- Atila Neves (13/29) Jun 17 2020 I was going to say "it should work" but instead I wrote the code
- jmh530 (30/46) Jun 17 2020 If I'm understanding you correctly, you could modify Polymorphic
- Atila Neves (4/20) Jun 17 2020 I think these questions are good motivators for making it
- jmh530 (2/6) Jun 17 2020 Makes sense.
- Paul Backus (15/26) Jun 17 2020 IMO this can be done more elegantly by separating out the code
- jmh530 (6/20) Jun 17 2020 The syntax there looks nice (wouldn't hurt to make it even
- Sebastiaan Koppe (3/13) Jun 17 2020 Yeah I can see a use for this. If have had to refactor things
- Atila Neves (11/38) Jun 19 2020 Interesting.
- Stanislav Blinov (2/4) Jun 17 2020 I've got to ask though. Why "tardy"? Search engines be damned? :)
- Atila Neves (3/8) Jun 17 2020 Late binding ;)
- Andrei Alexandrescu (2/11) Jun 18 2020 Love the name.
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); }
Jun 13 2020
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())]
Jun 13 2020
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:I actually need to benchmark it though!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.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
Jun 15 2020
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#L222Thanks, I missed that.
Jun 15 2020
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.
Jun 13 2020
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote:https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyCool 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?
Jun 13 2020
On 6/13/20 2:39 PM, Paul Backus wrote:On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote:FWIW that could be avoided with extern(C++) classes.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyCool 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?
Jun 13 2020
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: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyCool 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?
Jun 15 2020
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote:https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyIf 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.
Jun 14 2020
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
Jun 15 2020
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: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...]Wouldn't a top type be a better way to achieve this? -Alex
Jun 15 2020
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:Speaking of type functions, have you been working on a dip for that? I am quite curious to see what it looks like currently. -AlexOn Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...]Wouldn't a top type be a better way to achieve this? -Alex
Jun 15 2020
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: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.On Monday, 15 June 2020 at 20:47:16 UTC, 12345swordy wrote:Speaking of type functions, have you been working on a dip for that? I am quite curious to see what it looks like currently. -AlexOn Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...]Wouldn't a top type be a better way to achieve this? -Alex
Jun 15 2020
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:How?https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardy [...]Wouldn't a top type be a better way to achieve this? -Alex
Jun 16 2020
On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote:https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyLooks 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.
Jun 15 2020
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: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyLooks 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?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.
Jun 16 2020
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:Cool!On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote: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.https://code.dlang.org/packages/tardy https://github.com/atilaneves/tardyLooks 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?Yes. Other than allowing multiple interfaces, I think it's already implemented.Yes I meant trait objects actually.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.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.
Jun 16 2020
On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote:[snip]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.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.[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.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
Jun 16 2020
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:So does tardy.[snip]I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions?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.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.
Jun 16 2020
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: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; } ```On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote:So does tardy.[snip]I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions?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.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.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.
Jun 16 2020
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.
Jun 16 2020
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:<snip> 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; }On Tuesday, 16 June 2020 at 11:24:05 UTC, jmh530 wrote:Sorry, I had not realized that. I took Go's interface example and converted it to D. Would this work with tardy?On Tuesday, 16 June 2020 at 09:15:10 UTC, Atila Neves wrote:So does tardy.[snip]I'm not familiar with what Typescript does, but doesn't Go allow interfaces to be implemented by free-standing functions?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.
Jun 16 2020
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?
Jun 16 2020
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:Good point.[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.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_.dAm 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.
Jun 17 2020
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_.dCool.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.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.
Jun 17 2020
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:I think these questions are good motivators for making it interface-only since then I don't have to check for data definitions.[...]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?
Jun 17 2020
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.
Jun 17 2020
On Tuesday, 16 June 2020 at 13:31:49 UTC, Atila Neves wrote:<snip> 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.
Jun 17 2020
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).
Jun 17 2020
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.
Jun 17 2020
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: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); } }<snip> 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;
Jun 19 2020
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? :)
Jun 17 2020
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:Late binding ;)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? :)
Jun 17 2020
On 6/17/20 7:19 AM, Atila Neves wrote:On Wednesday, 17 June 2020 at 10:43:35 UTC, Stanislav Blinov wrote:Love the name.On Saturday, 13 June 2020 at 15:11:49 UTC, Atila Neves wrote:Late binding ;)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? :)
Jun 18 2020