digitalmars.D.bugs - Access rights of mixins
- Stewart Gordon (45/45) Mar 07 2005 Should a mixin have the access rights of the scope where it's defined,
- Regan Heath (7/12) Mar 07 2005 Used.
- Stewart Gordon (19/29) Mar 07 2005 Why not? As in, it's one way in which someone would expect mixins to be...
- Regan Heath (28/52) Mar 07 2005 I didn't expect this. Interestingly, template functions:
- Stewart Gordon (13/44) Mar 08 2005 Aren't module members public by default?
- Regan Heath (11/45) Mar 08 2005 It still works if I change it to:
- Stewart Gordon (21/76) Mar 09 2005 As should be expected, since the template is in the module scope. But
- Regan Heath (66/136) Mar 09 2005 Indeed. And the mixin has it's own scope. Another example:
- Stewart Gordon (37/81) Mar 10 2005 What's that to do with your snippet?
- Regan Heath (22/89) Mar 10 2005 My first example, didn't use a mixin, and worked. This snippet, used a ...
- Stewart Gordon (15/39) Mar 11 2005 I guess we've come to an agreement on this then.
Should a mixin have the access rights of the scope where it's defined, or of the scope where it's used? The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this. Take this: ----- mixin1.d ----- module mixin1; private int qwert; template Yuiop() { int asdfg() { return qwert; } int hjkl() { return zxcvb; } } ----- mixin2.d ----- module mixin2; import mixin1; private int zxcvb; mixin Yuiop; ---------- D:\My Documents\Programming\D\Tests\bugs\mixin2.d: module mixin2 mixin1.qwert is private ---------- So the mixin cannot access qwert, even though the mixin is defined in the same module. OTOH, it can access zxcvb, which is private to another module. My thought is that a mixin should have full access to the scope in which it is defined. It should also still have access to at least the protected members of the scope where it is used, but I'm not sure if it should be able to access the private and package members thereof. The spec doesn't seem to clarify, though it does say: "Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined." Since "evaluated" need not coincide with "access-checked", this isn't a sure sign of anything. Moreover, considering it is pointed out that mixins aren't just like C preprocessor macros, is there any reason this shouldn't join the repertoire of differences? (Where does implementation ease fit into the equation, FTM?) Notice also that the error is missing a line number. And gives the name of the file where it's used - it ought be pinpointing where the mixin member is defined. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 07 2005
On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Should a mixin have the access rights of the scope where it's defined, or of the scope where it's used?Used.The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.How were you actually using this? As in, why did you design it this way? why does the mixin rely on a global var? I think I need these details to see where you're coming from. Regan
Mar 07 2005
Regan Heath wrote:On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:<snip>Why not? As in, it's one way in which someone would expect mixins to be usable, intuitively following the principle that what is defined in a module has access to the module's private members, and correspondingly having its practical uses.The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.How were you actually using this? As in, why did you design it this way?why does the mixin rely on a global var?The way I'm using it, it actually relies on would-be private members of a class defined in the mixin's module. But the argument would apply equally if a real-world application relied on a global var.I think I need these details to see where you're coming from.I'm using it to implement MDI for SDWF 0.5. I have two classes, MDIFrameWindow and MDIClientPane, and a template MDIChildWindow that child windows mixin in order to do the special handling that MDI child windows need. OTTOMH, I think one of these would-be private members is the child window list on the SDWF side.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 07 2005
On Mon, 07 Mar 2005 11:52:09 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote:I didn't expect this. Interestingly, template functions: [a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:<snip>Why not? As in, it's one way in which someone would expect mixins to be usable, intuitively following the principle that what is defined in a module has access to the module's private members, and correspondingly having its practical uses.The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.How were you actually using this? As in, why did you design it this way?I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct? It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way. I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought. Reganwhy does the mixin rely on a global var?The way I'm using it, it actually relies on would-be private members of a class defined in the mixin's module. But the argument would apply equally if a real-world application relied on a global var.I think I need these details to see where you're coming from.I'm using it to implement MDI for SDWF 0.5. I have two classes, MDIFrameWindow and MDIClientPane, and a template MDIChildWindow that child windows mixin in order to do the special handling that MDI child windows need. OTTOMH, I think one of these would-be private members is the child window list on the SDWF side....
Mar 07 2005
Regan Heath wrote: <snip>[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.Aren't module members public by default? <snip>I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?Yes, though in this case it would be totally expected.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.I certainly don't see any disadvantages.I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 08 2005
On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>It still works if I change it to: private int g = 5;[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.Aren't module members public by default?<snip>That's just it though, to me what you encountered was totally expected. Due to how I understood mixins to work, as if you were pasting the code.I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?Yes, though in this case it would be totally expected.Is the mixin itself protected, or can anyone choose to mix it in and thus get access to your privates.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.I certainly don't see any disadvantages.I see.. so the mixin code is a 'helper' for creating 'custom' windo classes? ReganI can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
Mar 08 2005
Regan Heath wrote:On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:As should be expected, since the template is in the module scope. But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used? I'd like to say a bit of both.Regan Heath wrote: <snip>It still works if I change it to: private int g = 5;[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.Aren't module members public by default?Mixins already aren't just like pasting the code. http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.<snip>That's just it though, to me what you encountered was totally expected. Due to how I understood mixins to work, as if you were pasting the code.I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?Yes, though in this case it would be totally expected.Anyone can mix it in. It's the way it works - one creates an MDI child class by mixing it into the application-specific subclass of Window or FrameWindow. Whether someone can abuse it to this extent, I'm not sure. An alternative would be to have ready-mixed child window classes corresponding to these, each of which mixes it in, and keep the template private. I wonder....Is the mixin itself protected, or can anyone choose to mix it in and thus get access to your privates.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.I certainly don't see any disadvantages.Not quite. A 'necessity' for creating MDI child window classes. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.I see.. so the mixin code is a 'helper' for creating 'custom' windo classes?I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
Mar 09 2005
On Wed, 09 Mar 2005 10:27:42 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote:Indeed. And the mixin has it's own scope. Another example: [a.d] (same as before) module a; private int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; mixin A!(int) fn; void main() { fn(2); } C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:As should be expected, since the template is in the module scope.Regan Heath wrote: <snip>It still works if I change it to: private int g = 5;[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.Aren't module members public by default?But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?Currently, a mixin creates a new scope.I'd like to say a bit of both.Perhaps. Is there a problem with collision resolution? eg. [a.d] module a; private int g = 5; template M(T) { void foo() { writef(g); } } [b.d] module b; class A { private int g = 2; mixin M!(int); } You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g. Assuming of course the real-life usage is more complex and cannot simply be re-written: template M(alias T) { void foo() { writef(T); } } mixin M!(g); i.e. pass the var you want to use.The important one (in this case) seems to be: "Mixins create a scope, macros do not."Mixins already aren't just like pasting the code. http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.<snip>That's just it though, to me what you encountered was totally expected. Due to how I understood mixins to work, as if you were pasting the code.I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?Yes, though in this case it would be totally expected.I think it can potentially 'weaken' the protection on the 'private' int. Whether we want to allow that, or not, I don't know.Anyone can mix it in. It's the way it works - one creates an MDI child class by mixing it into the application-specific subclass of Window or FrameWindow. Whether someone can abuse it to this extent, I'm not sure.Is the mixin itself protected, or can anyone choose to mix it in and thus get access to your privates.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.I certainly don't see any disadvantages.An alternative would be to have ready-mixed child window classes corresponding to these, each of which mixes it in, and keep the template private. I wonder....Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface. In D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}Right. I think I follow now. :) ReganNot quite. A 'necessity' for creating MDI child window classes.I see.. so the mixin code is a 'helper' for creating 'custom' windo classes?I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
Mar 09 2005
Regan Heath wrote: <snip>C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.What's that to do with your snippet?Then the point becomes: what is this new scope a subscope of?But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?Currently, a mixin creates a new scope.<snip>I'd like to say a bit of both.Perhaps. Is there a problem with collision resolution? eg.You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g.Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used. It doesn't seem to address the issue of access rights though. <snip>Similarly, classes create a scope. So do functions. And yet classes have no trouble accessing private members in their modules, and functions have no trouble accessing private members in their classes. <snip>http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.The important one (in this case) seems to be: "Mixins create a scope, macros do not."Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface.But in Java you can't (directly at least) share implementation details between classes that implement an interface.In D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}<snip> At the moment I have class Window : WindowBase { ... } class FrameWindow : Window { ... } class MDIFrameWindow : FrameWindow { ... } class MDIClientPane : WindowBase { ... } template MDIChildWindow() { ... } The application window is an MDIFrameWindow, which frames an MDIClientPane (the standard Windows control that holds the child windows). To create a child window class, one uses class ChildWindow : Window { mixin MDIChildWindow; ... } But I'm now thinking maybe I should predefine the ChildWindow and ChildFrameWindow classes, and have the lib user create subclasses of these. I can think of a few other benefits to this approach.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 10 2005
On Thu, 10 Mar 2005 11:58:22 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>My first example, didn't use a mixin, and worked. This snippet, used a mixin, and didn't work. This snippet was more like your code than my first example. I was trying to show the difference between mixin template usage and standard template usage. Which is, I believe, that a mixin creates a scope where it's used.C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.What's that to do with your snippet?I believe it's a subscope of the scope in which it's used, i.e. where type 'mixin'.Then the point becomes: what is this new scope a subscope of?But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?Currently, a mixin creates a new scope.That is how I understood it.<snip>I'd like to say a bit of both.Perhaps. Is there a problem with collision resolution? eg.You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g.Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used.It doesn't seem to address the issue of access rights though.True. Perhaps it should be explicit about it all. i.e. "mixins create their own sub-scope within the scope there they are used, not where they are defined. This means they have private access to the module where they are used, not where they are defined" .. or something.<snip>The question, as you said, is where does it create that scope. In the case of classes it's created where it's defined, in the case of mixins it's where it's used. It seems it needs to be explicit about this behaviour in the docs.Similarly, classes create a scope. So do functions. And yet classes have no trouble accessing private members in their modules, and functions have no trouble accessing private members in their classes.http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.The important one (in this case) seems to be: "Mixins create a scope, macros do not."<snip>Not that implement the interface, no, but you can derive all the classes from SimpleFoo, which in effect contains the shared implementation details.Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface.But in Java you can't (directly at least) share implementation details between classes that implement an interface.Excellent.. so it seems it's a better approach all round. ReganIn D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}<snip> At the moment I have class Window : WindowBase { ... } class FrameWindow : Window { ... } class MDIFrameWindow : FrameWindow { ... } class MDIClientPane : WindowBase { ... } template MDIChildWindow() { ... } The application window is an MDIFrameWindow, which frames an MDIClientPane (the standard Windows control that holds the child windows). To create a child window class, one uses class ChildWindow : Window { mixin MDIChildWindow; ... } But I'm now thinking maybe I should predefine the ChildWindow and ChildFrameWindow classes, and have the lib user create subclasses of these. I can think of a few other benefits to this approach....
Mar 10 2005
Regan Heath wrote:On Thu, 10 Mar 2005 11:58:22 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:<snip>I guess we've come to an agreement on this then.Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used.That is how I understood it.<snip>It doesn't seem to address the issue of access rights though.True. Perhaps it should be explicit about it all. i.e. "mixins create their own sub-scope within the scope there they are used, not where they are defined. This means they have private access to the module where they are used, not where they are defined" .. or something.The question, as you said, is where does it create that scope. In the case of classes it's created where it's defined, in the case of mixins it's where it's used. It seems it needs to be explicit about this behaviour in the docs.Good idea. <snip><snip> But not if the classes may already be derived from different classes. This is where mixins become useful - as a way of creating shared implementation details that may be applied to a variety of classes. Kind of like a makeshift form of multiple inheritance.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.But in Java you can't (directly at least) share implementation details between classes that implement an interface.Not that implement the interface, no, but you can derive all the classes from SimpleFoo, which in effect contains the shared implementation details.
Mar 11 2005