digitalmars.D.learn - is there a way to enforce module 'namespace' semantics?
- clayasaurus (41/41) Mar 20 2005 Hi,
- Chris Sauls (18/25) Mar 20 2005 A darn good question: I'd very much like this myself. One possible
- clayasaurus (16/48) Mar 20 2005 That may be a decent alternative, but it doesn't cut it for me, since it...
- Ben Hinkle (13/19) Mar 20 2005 why not? D is designed to be used that way. Can you give more details ab...
- clayasaurus (89/118) Mar 20 2005 I would rather use a 'module global' instead of a 'class global',
- Lukas Pinkowski (21/38) Mar 20 2005 I use classes with static methods and properties, thus having something ...
- Ben Hinkle (9/31) Mar 20 2005 Maybe it's just me but I don't want to see this become common in D. The
- clayasaurus (18/59) Mar 20 2005 When you have two modules with the same functions, you are forced to
- Carlos Santander B. (19/28) Mar 20 2005 I'm with Ben here. What if in one of your modules you forget your
- J C Calvarese (8/19) Mar 20 2005 I think this part of the issue can best be solved by a better error
- Derek Parnell (11/29) Mar 20 2005 I suspect that you are very correct here. In general, I think that Walte...
- J C Calvarese (10/28) Mar 20 2005 Well, there always going to have to be some computer science jargon, but...
- Regan Heath (8/34) Mar 20 2005 I had a very brief look at the front end code (so I may be way off base ...
- Ilya Minkov (37/37) Mar 21 2005 I think you may have something like:
Hi, Say I have module foo, and it has funtion bar, like this ------foo.d--------------- module foo; void bar() { } -------------------------- Now, I'm writing a library and I don't want the user of the library to be able to call bar by itself, like this ------main.d-------------- import foo; bar(); // nose -------------------------- Instead, I want to make it so the only way the user can call bar is like this ------main.d-------------- import foo; foo.bar(); // yes -------------------------- Is there a way I can enforce the functions inside of the module? Maybe like this? ------foo.d--------------- module foo; enforce // enforces module 'namespace' { void bar() { } } -------------------------- The reason I want to enforce the module 'namespace' is because I'm using modules as a replacement for a global class. I have multiple modules with similar function names, and as the library writer, I don't want my users to just call 'bar()', because it is not how I want the module to be used and the compiler will complain if they import another module with the same function name 'bar()' Is there a good solution to this problem? Or should there be some way to enforce module 'namespace' within D? Thanks. - Clay
Mar 20 2005
clayasaurus wrote:Instead, I want to make it so the only way the user can call bar is like this ------main.d-------------- import foo; foo.bar(); // yes --------------------------A darn good question: I'd very much like this myself. One possible (albeit hackish) solution I thought of off the top of my head would be to use static members of an abstract class... ie: Granted it probably provides feeding ground for cute errors from missing capitalization, but it should work. Maybe I'll test it later. -- Grant
Mar 20 2005
Chris Sauls wrote:clayasaurus wrote:That may be a decent alternative, but it doesn't cut it for me, since it is using pseudo-module namespace, and you can call weird things like... foo.Foo.bar() // i think It would be simpler to just let the compiler bite the user when they try to do this ---------------------------- import foo1; // has bar() import foo2; // has bar() bar(); ---------------------------- but it would be more consistent to be able to enforce the 'namespace', so this kind of thing can never happen (it does when programmers get shortsighted/lazy) Thanks for the reply : ) - ClayInstead, I want to make it so the only way the user can call bar is like this ------main.d-------------- import foo; foo.bar(); // yes --------------------------A darn good question: I'd very much like this myself. One possible (albeit hackish) solution I thought of off the top of my head would be to use static members of an abstract class... ie: Granted it probably provides feeding ground for cute errors from missing capitalization, but it should work. Maybe I'll test it later. -- Grant
Mar 20 2005
The reason I want to enforce the module 'namespace' is because I'm using modules as a replacement for a global class. I have multiple modules with similar function names, and as the library writer, I don't want my users to just call 'bar()', because it is not how I want the module to be usedwhy not? D is designed to be used that way. Can you give more details about the API? Personally I wouldn't fight the standard D style but one is free to make whatever API one wants, I suppose. If the standard approach results in errors or painful usage then I suggest posting examples so that Walter can try to find a nice solution.and the compiler will complain if they import another module with the same function name 'bar()'It should only complain when they try to use it. When that happens they will have to use the foo.bar or an alias to fix the conflict. You might be seeing import conflicts because of public imports, too. This, actually, is one reason why private imports are better than public ones because it can be nasty to track down conflicts when you nest several public imports and somewhere along the chain a conflict happens. Keeping everything private prevents that from happening. -Ben
Mar 20 2005
Ben Hinkle wrote:I would rather use a 'module global' instead of a 'class global', because with classes you have to 'new' it, and you have to give it a name, which would probably be something like 'gClass'. With a 'module global', the name is the module name, and I don't have to 'new' it. These globals are ok for me, because they are there for the entire length of the program, and everything needs easy access to them. Also, with module global, there is no need for declaration, as you just use 'import module' : ) I see this as a nice solution, and easy for the user of your program to use, for instance ---------------------------------- import input; input.open() input.process() if (input.keyDown('a')) writefln("a key is down") ---------------------------------- versus ---------------------------------- import input; gInput = new Input(); gInput.open(); gInput.process() if (gInput.keyDown("a")) writefln("a key is down"); ---------------------------------- Also, I have a module named window, which holds window width, size, etc, and that has similar function names so the code is familiar. I am not asking that all D modules require this, I am just asking for a keyword (or something else?) to enforce the module namespace, or asking if someone can think of a better solution (I know I am not a master programmer) What I have, a snippet from my code, is something like this... ---- input.d -------------- module input; private { // vars } public { // funcs open() close() } --------------------------- I have a very similar ------- window.d ---------- module window; private { // vars } public { open() close() } -------------------------- Now, with my program, window and input and guarenteed to be used together, and if one calls open(); // depending on the cirsumstance, will either err or be 'ok', // but for consistency, I would rather force the code to be // input.open() or window.open(), so the programmer knows what // is happening and so, depending on what you import, you don't // all of a sudden get the compiler complaining to you Maybe I'm making a big deal out of nothing, and I'll just let an ignorant programmer write weird code that could mean different things depending on what I import.The reason I want to enforce the module 'namespace' is because I'm using modules as a replacement for a global class. I have multiple modules with similar function names, and as the library writer, I don't want my users to just call 'bar()', because it is not how I want the module to be usedwhy not? D is designed to be used that way. Can you give more details about the API? Personally I wouldn't fight the standard D style but one is free to make whatever API one wants, I suppose. If the standard approach results in errors or painful usage then I suggest posting examples so that Walter can try to find a nice solution.if i can choose to have the compiler complain about foo in the first place, no worries :) as they'll have to use foo.bar. also, they will not want to use an alias, because there is no better name they can alias too :)and the compiler will complain if they import another module with the same function name 'bar()'It should only complain when they try to use it. When that happens they will have to use the foo.bar or an alias to fix the conflict.You might be seeing import conflicts because of public imports, too. This, actually, is one reason why private imports are better than public ones because it can be nasty to track down conflicts when you nest several public imports and somewhere along the chain a conflict happens. Keeping everything private prevents that from happening.It might be nice for D to force either 'public' or 'private' on all things within the module, and not default everything to 'public' or 'priavte' I know, at first, I didn't understand that D defaulted all module access to public. And, I don't think it hurts productivity to force either public or private, rather it makes the programmer think about what they really want to be shared within a module, potentially avoiding hard to track down future module conflicts within large programs. Anyway, what it boils down to for me is that if i have module module foo; // has bar() in it module dance; // has bar() in it bar(); // the compiler will complain, no? Bar, is a public function, I want it to be public, I need it to be public. I know what I can hide and what I can't. :) I just think it would be nice if I could make the compiler complain in the first place, so my library can not be abused.-Ben
Mar 20 2005
clayasaurus wrote:Ben Hinkle wrote:I use classes with static methods and properties, thus having something like a namespace. You don't have to 'new' a class to use its static methods and members and you are forced to use MyClass.method() instead of just method() like in modules. ie. module input; class Input { static { void open() { bla } void process() { bla } ... } } and import input; Input.open(); Input.process(); ...I would rather use a 'module global' instead of a 'class global', because with classes you have to 'new' it, and you have to give it a name, which would probably be something like 'gClass'. With a 'module global', the name is the module name, and I don't have to 'new' it.The reason I want to enforce the module 'namespace' is because I'm using modules as a replacement for a global class. I have multiple modules with similar function names, and as the library writer, I don't want my users to just call 'bar()', because it is not how I want the module to be usedwhy not? D is designed to be used that way. Can you give more details about the API? Personally I wouldn't fight the standard D style but one is free to make whatever API one wants, I suppose. If the standard approach results in errors or painful usage then I suggest posting examples so that Walter can try to find a nice solution.
Mar 20 2005
I use classes with static methods and properties, thus having something like a namespace. You don't have to 'new' a class to use its static methods and members and you are forced to use MyClass.method() instead of just method() like in modules. ie. module input; class Input { static { void open() { bla } void process() { bla } ... } } and import input; Input.open(); Input.process(); ...Maybe it's just me but I don't want to see this become common in D. The whole point of the module rules is to free users from having to type Input. or whatever. Please don't force me as a user of your library to work in Java style where dummy classes wrap top-level functions. If you (meaning a library author) wants to always include the module name in your code because you think it looks nice then feel free to do that (it is legal D so it isn't a problem). But please let's keep D libraries free from the hacks that other languages need. The module rules in D are flexible enough to keep everyone happy. If they aren't then we need to alert Walter so that he can fix it up.
Mar 20 2005
Ben Hinkle wrote:When you have two modules with the same functions, you are forced to type input anyway, the compiler will complain. In my lib, you are guarenteed to have two modules with the same function names, out of design. What happens when it goes wrong is that it you get a weird error message, like "foo.d(3): function foo.fooo conflicts with bar.fooo at bar.d(3)," that doesn't give you the name of the source file where the actual conflict occurs (in this case main.d), and it is a bit hard to track down in a large program. I thought it would be better to enforce module namespace so these errors do not happen, and if you forget to do it then the compiler can tell you the line of code it goes wrong on.I use classes with static methods and properties, thus having something like a namespace. You don't have to 'new' a class to use its static methods and members and you are forced to use MyClass.method() instead of just method() like in modules. ie. module input; class Input { static { void open() { bla } void process() { bla } ... } } and import input; Input.open(); Input.process(); ...Maybe it's just me but I don't want to see this become common in D. The whole point of the module rules is to free users from having to type Input. or whatever.Please don't force me as a user of your library to work in Java style where dummy classes wrap top-level functions. If you (meaning a library author) wants to always include the module name in your code because you think it looks nice then feel free to do that (it is legal D so it isn't a problem). But please let's keep D libraries free from the hacks that other languages need. The module rules in D are flexible enough to keep everyone happy. If they aren't then we need to alert Walter so that he can fix it up.I've decided i'm not going to use static classes or whatever (though neat trick!) I'll just let the compiler bite when it feels it is time :-) And then they can have fun tracking it down, without DMD telling you the line or source where the conflict occurs. fun.
Mar 20 2005
clayasaurus wrote:I've decided i'm not going to use static classes or whatever (though neat trick!) I'll just let the compiler bite when it feels it is time :-) And then they can have fun tracking it down, without DMD telling you the line or source where the conflict occurs. fun.I'm with Ben here. What if in one of your modules you forget your proposed "enforce" attribute? module a; enforce: void foo() {} module b; //oops, forgot enforce void foo() {} module usercode; void bar() { foo(); // user made a mistake: he meant a.foo } The compiler would not complain about it and the user would get a wrong result. Again, I also prefer the flexibility that D gives right now. _______________________ Carlos Santander Bernal
Mar 20 2005
clayasaurus wrote: ...When you have two modules with the same functions, you are forced to type input anyway, the compiler will complain. In my lib, you are guarenteed to have two modules with the same function names, out of design. What happens when it goes wrong is that it you get a weird error message, like "foo.d(3): function foo.fooo conflicts with bar.fooo at bar.d(3)," that doesn't give you the name of the source file where the actual conflict occurs (in this case main.d), and it is a bit hard to track down in a large program.I think this part of the issue can best be solved by a better error message. Maybe if we mention these substandard error messages enough times, Walter will have a chance to fix them. ;) -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Mar 20 2005
On Sun, 20 Mar 2005 21:48:17 -0600, J C Calvarese wrote:clayasaurus wrote: ...I suspect that you are very correct here. In general, I think that Walter needs to make a determined effort to systematically go through the compiler and standardize all the error messages. They should at the very least identify the file name and line number that *triggered* the error, and the text of the message needs to be in plain language rather than compiler-speak (i.e. Minimize the computer science jargon). -- Derek Melbourne, Australia 21/03/2005 2:52:15 PMWhen you have two modules with the same functions, you are forced to type input anyway, the compiler will complain. In my lib, you are guarenteed to have two modules with the same function names, out of design. What happens when it goes wrong is that it you get a weird error message, like "foo.d(3): function foo.fooo conflicts with bar.fooo at bar.d(3)," that doesn't give you the name of the source file where the actual conflict occurs (in this case main.d), and it is a bit hard to track down in a large program.I think this part of the issue can best be solved by a better error message. Maybe if we mention these substandard error messages enough times, Walter will have a chance to fix them. ;)
Mar 20 2005
Derek Parnell wrote:On Sun, 20 Mar 2005 21:48:17 -0600, J C Calvarese wrote:...Well, there always going to have to be some computer science jargon, but the message should at least provide all of the relevant line numbers. And I think Walter is already responsive to these criticisms, one man can only find and fix them so fast. I wonder how much we could help by pointing him to a particular string in the front-end. Hmmm... -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/I suspect that you are very correct here. In general, I think that Walter needs to make a determined effort to systematically go through the compiler and standardize all the error messages. They should at the very least identify the file name and line number that *triggered* the error, and the text of the message needs to be in plain language rather than compiler-speak (i.e. Minimize the computer science jargon).What happens when it goes wrong is that it you get a weird error message, like "foo.d(3): function foo.fooo conflicts with bar.fooo at bar.d(3)," that doesn't give you the name of the source file where the actual conflict occurs (in this case main.d), and it is a bit hard to track down in a large program.I think this part of the issue can best be solved by a better error message. Maybe if we mention these substandard error messages enough times, Walter will have a chance to fix them. ;)
Mar 20 2005
On Sun, 20 Mar 2005 22:21:32 -0600, J C Calvarese <jcc7 cox.net> wrote:Derek Parnell wrote:I had a very brief look at the front end code (so I may be way off base here) but I noticed the error function simply gets passed a string, which it then prints. What if Walter changes that to take a file, line and error. The function could then print in a set format, the calling code would all error highlighting all the calls which now require file/line information. ReganOn Sun, 20 Mar 2005 21:48:17 -0600, J C Calvarese wrote:...Well, there always going to have to be some computer science jargon, but the message should at least provide all of the relevant line numbers. And I think Walter is already responsive to these criticisms, one man can only find and fix them so fast. I wonder how much we could help by pointing him to a particular string in the front-end. Hmmm...I suspect that you are very correct here. In general, I think that Walter needs to make a determined effort to systematically go through the compiler and standardize all the error messages. They should at the very least identify the file name and line number that *triggered* the error, and the text of the message needs to be in plain language rather than compiler-speak (i.e. Minimize the computer science jargon).What happens when it goes wrong is that it you get a weird error message, like "foo.d(3): function foo.fooo conflicts with bar.fooo at bar.d(3)," that doesn't give you the name of the source file where the actual conflict occurs (in this case main.d), and it is a bit hard to track down in a large program.I think this part of the issue can best be solved by a better error message. Maybe if we mention these substandard error messages enough times, Walter will have a chance to fix them. ;)
Mar 20 2005
I think you may have something like: implementation_module.d - all your real stuff is here, including definition of functionCall(). module.d: // Proxy struct module{ import implementation_module; } // end of module.d test.d: import module; void main(){ // this should work: module.functionCall(); // this must fail: //~ functionCall(); } // end of module.d However, if you really have collision on function names, it might be a hint that you might want to bring some class encapsulation into the game, or solve the issue otherwise. You should never give functions the same name, unless they also do exactly the same - perhaps, on different types. However, if they do the same, you have 2 possibilities: either drop all functions into the same namespace, or you can find a place in a class hierarchy, making full-scale methods out of them. To drop all the functions into the same namespace, you need not define them in the same module. Instead, say ambiguousFunction() is defined in module1, module2 and module3, using different types as argument. Then in a new module you may do: module common; private import module1, module2, module3; alias module1.ambiguousFunction ambiguousFunction; alias module2.ambiguousFunction ambiguousFunction; alias module3.ambiguousFunction ambiguousFunction; Now when you import them all through module "common" they will obey to type overloading correctly. -eye
Mar 21 2005