digitalmars.D - Partial classes
- Manu (11/11) Jun 25 2012 I suspect this isn't possible in a compiled language like D, but I wonde...
- Regan Heath (21/32) Jun 25 2012 I thought that the various parts of partial classes in C# had to be
- Kapps (2/2) Jun 25 2012 Any reason that just using mixin(import("myclass.partial.d"))
- Regan Heath (56/58) Jun 26 2012 It /could/ work if you were careful about what you were mixing in, and
- Timon Gehr (10/21) Jun 25 2012 Ideally yes, but it should be possible to initialize the relevant data
- Walter Bright (9/15) Jun 25 2012 Are you talking about adding fields/functions to an arbitrary class with...
- Max Samukha (3/26) Jun 25 2012 He's talking about this:
- Manu (45/61) Jun 25 2012 But this is essentially no different than UFCS, except to me it feels li...
- Timon Gehr (21/89) Jun 25 2012 It is not fair to say it is not fair, because the interpretation he has
- Walter Bright (17/64) Jun 25 2012 Adding behavior into an existing class that was not designed for it is, ...
- Max Samukha (9/12) Jun 25 2012 That is not exactly the same. The important difference is that
- Jacob Carlborg (10/13) Jun 26 2012 I have only found it being very useful. I have never found it to be a
- Walter Bright (7/20) Jun 26 2012 Not much, but I've read accounts from people who have who say that
- Artur Skawina (16/21) Jun 26 2012 void poke(T)(size_t addr, T val) @safe pure {
- Timon Gehr (2/22) Jun 26 2012 This is not legal D code. (pointer indexing is unsafe)
- Walter Bright (3/30) Jun 26 2012 If the compiler doesn't give an error on that, it's a compiler bug, not ...
- Jacob Carlborg (5/19) Jun 26 2012 Isn't it the same with partial classes? What if the third party class
I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together. I often find myself wanting to add some extra pizazz to classes using template/mixin magic, but I may not have control over the original code where it is defined...
Jun 25 2012
On Mon, 25 Jun 2012 16:26:27 +0100, Manu <turkeyman gmail.com> wrote:I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together. I often find myself wanting to add some extra pizazz to classes using template/mixin magic, but I may not have control over the original code where it is defined...compiled together. For example, I once tried to put a partial class into plain wont let you do this. derived from a DataContext (in one file), which I can extend and/or modify by implementing the rest of the partial class (in another file), in the same project (exe or dll) and if I compile them together I actually just get one merged class. D could easily implement a partial class feature with the restriction that they need to be compiled together. But IMO unless this is a trivial feature to implement, I wouldn't think it would be high on the priority list just yet. Partial classes make customizing auto generated (especially repeatedly auto generated) code much easier. #c uses them in it's form designer, placing all the designed code in a partial class in one file, and all user code in another file (in the same partial class). R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jun 25 2012
Any reason that just using mixin(import("myclass.partial.d")) wouldn't work?
Jun 25 2012
On Tue, 26 Jun 2012 02:50:46 +0100, Kapps <opantm2+spam gmail.com> wrote:Any reason that just using mixin(import("myclass.partial.d")) wouldn't work?It /could/ work if you were careful about what you were mixing in, and [File1] partial class Foo { } [File2] partial class Foo { } And then, for example, the form builder gui would automatically add members and methods to File1 while user created content would be added by the user to File2. At compile time, the two files are compiled as one class. Alternately File1 may be produced by a tool like sqlmetal once, or multiple times while the user added content in File2 would remain completely under the users control. So, yes, in D we could have: [File1] partial class Foo { .. compiler/form builder content .. mixin(import("File2.d")) } [File2] void foo() { } But, note how File2 does not (cannot) have the class declaration, etc. Alternately you could go the other way.. [File1] partial class Foo { .. user content .. mixin(import("File2.d")) } [File2] .. compiler/form builder content .. So the compiler file has no class declaration, but then the user would have to be careful not to remove the mixin. i.e. 1. Partial classes must be in similarly named files i.e. foo_1.d and foo_2.d (where foo is user defined by _1 and _2 are mandatory). 2. Partial classes must be compiled on the same command line and produce foo.o (note _1 and _2 are dropped and only 1 object file is produced). .. and so on. I am no expert on compiling/linking so there may be complications to the feature, but essentially it could be as simple as compiling the first file, pretending you haven't seen the } ending the class definition, opening the next file and ignoring the "partial class" line and continuing as if they were 1 file. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jun 26 2012
On 06/25/2012 05:26 PM, Manu wrote:I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation?Ideally yes, but it should be possible to initialize the relevant data structures at program load time. (druntime is already able to locate class type infos by their fully qualified names, so it should be feasible.)I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together. I often find myself wanting to add some extra pizazz to classes using template/mixin magic, but I may not have control over the original code where it is defined...How can you declare the class as partial if you do not have control over the original code?I think the blocking issues are in the frontend: partial classes name spaces.
Jun 25 2012
On 6/25/2012 8:26 AM, Manu wrote:I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together.Are you talking about adding fields/functions to an arbitrary class without modifying the original definition of that class? If so, this would violate principles of encapsulation, and there'd be terrible consequences (as you could not rely on the class definition being the class definition without examining the entire code base). But, you can use UFCS to "add" member functions to an existing class. Adding data members can be done using the PIMPL technique, string mixins, or template mixins (but the original class needs to be designed for that).
Jun 25 2012
On Monday, 25 June 2012 at 20:31:18 UTC, Walter Bright wrote:On 6/25/2012 8:26 AM, Manu wrote:He's talking about this: http://msdn.microsoft.com/en-us/library/wa80x488(v=vs.80).aspx.I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together.Are you talking about adding fields/functions to an arbitrary class without modifying the original definition of that class? If so, this would violate principles of encapsulation, and there'd be terrible consequences (as you could not rely on the class definition being the class definition without examining the entire code base). But, you can use UFCS to "add" member functions to an existing class. Adding data members can be done using the PIMPL technique, string mixins, or template mixins (but the original class needs to be designed for that).
Jun 25 2012
On 25 June 2012 23:30, Walter Bright <newshound2 digitalmars.com> wrote:On 6/25/2012 8:26 AM, Manu wrote:But this is essentially no different than UFCS, except to me it feels like less of a hack than UFCS (which I personally find rather dirty by contrast). Additionally, often enough, that UFCS function depend on adding a piece of data to the object in addition to the functionality it implements. I don't think it's fair to say it would lead to terrible consequences, because it exists, and it's used very successfully in other languages. It's proven to be very useful. I have a recurring problem where, at the module level, using CTFE I can scan the module for information, and generate bindings of things to their related systems without lots of manual, messy, error-prone hook-up code. For me, I think this has been the single biggest advantage I've gotten from using D yet hands down. The problem is, it's limited to things in the global scope. Partial classes are the completion of that concept, allowing it to be applied to classes too. If when scanning a class I find it has relationships to given systems, I can't then magically add the appropriate binding to that system into the class. There are some fairly messy hack-arounds that kinda work, but they If it's not added to the class its self, all of the IDE features that I am always claiming are so critical don't really work. The self-documenting, self-writing, auto-completion, popup member/parameter helpers and stuff don't work. Also, quite to the contrary of what you say, separating the functionality that should be embedded in the class from the class, it breaks the encapsulation principle. The class should gain that property internally, not bolted on the side with some hacky mechanisms. But, you can use UFCS to "add" member functions to an existing class.I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together.Are you talking about adding fields/functions to an arbitrary class without modifying the original definition of that class? If so, this would violate principles of encapsulation, and there'd be terrible consequences (as you could not rely on the class definition being the class definition without examining the entire code base).Indeed, but it's not quite the same. Adding data members can be done using the PIMPL technique, string mixins,or template mixins (but the original class needs to be designed for that).And that's basically the limitation I'd like to overcome. The fact something needs to be designed for it in advance; that is completely unrealistic. No 3rd party can ever anticipate what you might want to do. Whether you want to unintrusively extend some existing code, or you provide a library which can extend things in a general way.. If you can craft your partial extension in such a way than it integrates neatly with the 3rd party stuff you're using, that seems like a much more sensible approach, since it leaves the customisation to you, rather than the original author to attempt to anticipate... I really hate it when I have to butcher 3rd party code to add my bits. It makes it hard to maintain, if the author updates the code. Much nicer to extend it with my bit as a partial, and keep my code clinically separated.
Jun 25 2012
On 06/25/2012 11:26 PM, Manu wrote:On 25 June 2012 23:30, Walter Bright <newshound2 digitalmars.com <mailto:newshound2 digitalmars.com>> wrote: On 6/25/2012 8:26 AM, Manu wrote: I suspect this isn't possible in a compiled language like D, but I wonder anyway, has anyone considered partial classes in D? Are they technically possible? How would they work? Would it depend on link-time code generation? I can imagine an implementation where each 'part' occupies a separate allocation, and some pointer in Object or somewhere like that (somewhere near the typeinfo pointer) binds them together. Are you talking about adding fields/functions to an arbitrary class without modifying the original definition of that class? If so, this would violate principles of encapsulation, and there'd be terrible consequences (as you could not rely on the class definition being the class definition without examining the entire code base). But this is essentially no different than UFCS, except to me it feels like less of a hack than UFCS (which I personally find rather dirty by contrast).UFCS is just syntax. There is nothing deep/hacky/dirty behind it.Additionally, often enough, that UFCS function depend on adding a piece of data to the object in addition to the functionality it implements. I don't think it's fair to say it would lead to terrible consequences, because it exists, and it's used very successfully in other languages. It's proven to be very useful.It is not fair to say it is not fair, because the interpretation he has given as a premise does not exist successfully in other languages. ;)I have a recurring problem where, at the module level, using CTFE I can scan the module for information, and generate bindings of things to their related systems without lots of manual, messy, error-prone hook-up code. For me, I think this has been the single biggest advantage I've gotten from using D yet hands down. The problem is, it's limited to things in the global scope. Partial classes are the completion of that concept, allowing it to be applied to classes too.What mechanism do you use? You cannot add symbols to a module without having dedicated code in the module that does it. Why is the mechanism insufficient for classes? How would partial classes change the situation?If when scanning a class I find it has relationships to given systems, I can't then magically add the appropriate binding to that system into the class. There are some fairly messy hack-arounds that kinda work, butIt would be useful if you showed some pseudocode.If it's not added to the class its self, all of the IDE features that I am always claiming are so critical don't really work. The self-documenting, self-writing, auto-completion, popup member/parameter helpers and stuff don't work.If the compiler can resolve symbols, in principle, an IDE should be able to list them.Also, quite to the contrary of what you say, separating the functionality that should be embedded in the class from the class, it breaks the encapsulation principle. The class should gain that property internally, not bolted on the side with some hacky mechanisms.It does not break the encapsulation principle. Embedded class functionality weakens data encapsulation.But, you can use UFCS to "add" member functions to an existing class. Indeed, but it's not quite the same. Adding data members can be done using the PIMPL technique, string mixins, or template mixins (but the original class needs to be designed for that). And that's basically the limitation I'd like to overcome. The fact something needs to be designed for it in advance; that is completely unrealistic.public class ImACSharpClass{ } How to extend this class without changing the code? What I don't get yet is why adding 'partial' to the class definition is any better than adding 'import myadditionalfunctionality; mixin MyAdditionalFunctionality'. Is it about the separate compilation? Or is this just too 'hacky'?No 3rd party can ever anticipate what you might want to do. Whether you want to unintrusively extend some existing code, or you provide a library which can extend things in a general way.. If you can craft your partial extension in such a way than it integrates neatly with the 3rd party stuff you're using, that seems like a much more sensible approach, since it leaves the customisation to you, rather than the original author to attempt to anticipate... I really hate it when I have to butcher 3rd party code to add my bits. It makes it hard to maintain, if the author updates the code. Much nicer to extend it with my bit as a partial, and keep my code clinically separated.You can always use aggregation or inheritance. An use case would be of help here.
Jun 25 2012
On 6/25/2012 2:26 PM, Manu wrote:On 25 June 2012 23:30, Walter Bright <newshound2 digitalmars.com Are you talking about adding fields/functions to an arbitrary class without modifying the original definition of that class? If so, this would violate principles of encapsulation, and there'd be terrible consequences (as you could not rely on the class definition being the class definition without examining the entire code base). But this is essentially no different than UFCS,Adding behavior into an existing class that was not designed for it is, to me, like Ruby's "monkey-patching", since you could look at a class definition and have no clue if members were added by arbitrary other code or not. UFCS does it in a hygienic, encapsulated way.except to me it feels like less of a hack than UFCS (which I personally find rather dirty by contrast). Additionally, often enough, that UFCS function depend on adding a piece of data to the object in addition to the functionality it implements. I don't think it's fair to say it would lead to terrible consequences, because it exists, and it's used very successfully in other languages. It's proven to be very useful.Monkey-patching has, in Ruby, been popular and powerful. It has also turned out to be a disaster. It does not scale, and is not conducive to more than one person/team working on the code base.I have a recurring problem where, at the module level, using CTFE I can scan the module for information, and generate bindings of things to their related systems without lots of manual, messy, error-prone hook-up code. For me, I think this has been the single biggest advantage I've gotten from using D yet hands down. The problem is, it's limited to things in the global scope. Partial classes are the completion of that concept, allowing it to be applied to classes too. If when scanning a class I find it has relationships to given systems, I can't then magically add the appropriate binding to that system into the class. There are some fairly messy hack-arounds that kinda work, but they don't very very If it's not added to the class its self, all of the IDE features that I am always claiming are so critical don't really work. The self-documenting, self-writing, auto-completion, popup member/parameter helpers and stuff don't work. Also, quite to the contrary of what you say, separating the functionality that should be embedded in the class from the class, it breaks the encapsulation principle. The class should gain that property internally, not bolted on the side with some hacky mechanisms. But, you can use UFCS to "add" member functions to an existing class. Indeed, but it's not quite the same.You're right, and I'd argue that UFCS is hygienic, monkey-patching is not.Adding data members can be done using the PIMPL technique, string mixins, or template mixins (but the original class needs to be designed for that). And that's basically the limitation I'd like to overcome. The fact something needs to be designed for it in advance; that is completely unrealistic. No 3rd party can ever anticipate what you might want to do. Whether you want to unintrusively extend some existing code, or you provide a library which can extend things in a general way.. If you can craft your partial extension in such a way than it integrates neatly with the 3rd party stuff you're using, that seems like a much more sensible approach, since it leaves the customisation to you, rather than the original author to attempt to anticipate...That violates encapsulation because the 3rd party library code may have subtle dependencies on it not being extended, like using a .sizeof. Or, what to do if two different pieces of source code extend a class in different ways? What to do if new overloads are added, and some code sees those overloads and some do not?I really hate it when I have to butcher 3rd party code to add my bits. It makes it hard to maintain, if the author updates the code. Much nicer to extend it with my bit as a partial, and keep my code clinically separated.anyway - isn't that the same as inserting a template/string/import mixin or pimpl? Adding functionality for classes is also straightforward - derive from it. Adding functionality to structs is done with alias this.
Jun 25 2012
On Monday, 25 June 2012 at 23:44:09 UTC, Walter Bright wrote:class definition anyway - isn't that the same as inserting a template/string/import mixin or pimpl?That is not exactly the same. The important difference is that partial definitions can have attributes, interfaces, nested partial definitions etc., which will be merged in the resulting definition. That is not achievable with mixins or pimpl in a satisfactory way. See http://msdn.microsoft.com/en-us/library/wa80x488(v=vs.80).aspx. Not arguing for this feature. Simply noting that it is NOT the same as mixins/pimpl.
Jun 25 2012
On 2012-06-26 01:43, Walter Bright wrote:Monkey-patching has, in Ruby, been popular and powerful. It has also turned out to be a disaster. It does not scale, and is not conducive to more than one person/team working on the code base.I have only found it being very useful. I have never found it to be a disaster. Have you ever used Ruby? Ruby on Rails has to be the most popular Ruby library/framework and it adds a lot of new functionality to existing classes in the standard library. But just as with everything else you have to be responsible. In Ruby you can replace arbitrary methods and classes, even in the standard library. In D you can overwrite an arbitrary piece of memory. -- /Jacob Carlborg
Jun 26 2012
On 6/26/2012 3:53 AM, Jacob Carlborg wrote:On 2012-06-26 01:43, Walter Bright wrote:Not much, but I've read accounts from people who have who say that monkey-patching doesn't scale.Monkey-patching has, in Ruby, been popular and powerful. It has also turned out to be a disaster. It does not scale, and is not conducive to more than one person/team working on the code base.I have only found it being very useful. I have never found it to be a disaster. Have you ever used Ruby?Ruby on Rails has to be the most popular Ruby library/frameworkPHP is popular, too.and it adds a lot of new functionality to existing classes in the standard library. But just as with everything else you have to be responsible.A language should not encourage bad behavior, nor should it make code unreasonably difficult to reason about.In Ruby you can replace arbitrary methods and classes, even in the standard library. In D you can overwrite an arbitrary piece of memory.Not when using safe code, you can't.
Jun 26 2012
On 06/26/12 20:21, Walter Bright wrote:On 6/26/2012 3:53 AM, Jacob Carlborg wrote:void poke(T)(size_t addr, T val) safe pure { T* ptr; ptr[addr/T.sizeof] = val; } int i = 42; void main() safe { writeln(i); auto whatever = cast(size_t)&i; poke(whatever, 666); writeln(i); poke(0, 0); } void writeln(A...)(A a) trusted { import std.stdio; writeln(a); } arturreplace arbitrary methods and classes, even in the standard library. In D you can overwrite an arbitrary piece of memory.Not when using safe code, you can't.
Jun 26 2012
On 06/26/2012 09:29 PM, Artur Skawina wrote:On 06/26/12 20:21, Walter Bright wrote:This is not legal D code. (pointer indexing is unsafe)On 6/26/2012 3:53 AM, Jacob Carlborg wrote:void poke(T)(size_t addr, T val) safe pure { T* ptr; ptr[addr/T.sizeof] = val; } int i = 42; void main() safe { writeln(i); auto whatever = cast(size_t)&i; poke(whatever, 666); writeln(i); poke(0, 0); } void writeln(A...)(A a) trusted { import std.stdio; writeln(a); } arturreplace arbitrary methods and classes, even in the standard library. In D you can overwrite an arbitrary piece of memory.Not when using safe code, you can't.
Jun 26 2012
On 6/26/2012 12:52 PM, Timon Gehr wrote:On 06/26/2012 09:29 PM, Artur Skawina wrote:If the compiler doesn't give an error on that, it's a compiler bug, not a language problem.On 06/26/12 20:21, Walter Bright wrote:This is not legal D code. (pointer indexing is unsafe)On 6/26/2012 3:53 AM, Jacob Carlborg wrote:void poke(T)(size_t addr, T val) safe pure { T* ptr; ptr[addr/T.sizeof] = val; } int i = 42; void main() safe { writeln(i); auto whatever = cast(size_t)&i; poke(whatever, 666); writeln(i); poke(0, 0); } void writeln(A...)(A a) trusted { import std.stdio; writeln(a); } arturreplace arbitrary methods and classes, even in the standard library. In D you can overwrite an arbitrary piece of memory.Not when using safe code, you can't.
Jun 26 2012
On 2012-06-25 23:26, Manu wrote:And that's basically the limitation I'd like to overcome. The fact something needs to be designed for it in advance; that is completely unrealistic. No 3rd party can ever anticipate what you might want to do. Whether you want to unintrusively extend some existing code, or you provide a library which can extend things in a general way.. If you can craft your partial extension in such a way than it integrates neatly with the 3rd party stuff you're using, that seems like a much more sensible approach, since it leaves the customisation to you, rather than the original author to attempt to anticipate... I really hate it when I have to butcher 3rd party code to add my bits. It makes it hard to maintain, if the author updates the code. Much nicer to extend it with my bit as a partial, and keep my code clinically separated.Isn't it the same with partial classes? What if the third party class hasn't been marked with "partial". -- /Jacob Carlborg
Jun 26 2012