Jump to page: 1 2
Thread overview
is there a way to enforce module 'namespace' semantics?
Mar 20, 2005
clayasaurus
Mar 20, 2005
Chris Sauls
Mar 20, 2005
clayasaurus
Mar 20, 2005
Ben Hinkle
Mar 20, 2005
clayasaurus
Mar 20, 2005
Lukas Pinkowski
Mar 20, 2005
Ben Hinkle
Mar 21, 2005
clayasaurus
Mar 21, 2005
J C Calvarese
Mar 21, 2005
Derek Parnell
Mar 21, 2005
J C Calvarese
Mar 21, 2005
Regan Heath
Mar 21, 2005
Ilya Minkov
March 20, 2005
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






March 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:

# module foo;
#
# abstract class Foo {
#   static void bar() { }
# }

# module main;
# import foo;
#
# // ...
# Foo.bar();
# // ...

Granted it probably provides feeding ground for cute errors from missing capitalization, but it should work.  Maybe I'll test it later.

-- Grant
March 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 used

why 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


March 20, 2005
Chris Sauls wrote:
> 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:
> 
> # module foo;
> #
> # abstract class Foo {
> #   static void bar() { }
> # }
> 
> # module main;
> # import foo;
> #
> # // ...
> # Foo.bar();
> # // ...
> 
> Granted it probably provides feeding ground for cute errors from missing capitalization, but it should work.  Maybe I'll test it later.
> 
> -- Grant

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 : )
- Clay



























March 20, 2005
Ben Hinkle wrote:
>>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
> 
> 
> why 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.

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.


> 
> 
>>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.

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 :)

> 
> 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 
> 
> 
March 20, 2005
clayasaurus wrote:

> Ben Hinkle wrote:
>>>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
>> 
>> 
>> why 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.
> 
> 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.

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();

...
March 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.


March 21, 2005
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();
>>
>>...
> 
> 
> 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.

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.

> 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.







March 21, 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
March 21, 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/
« First   ‹ Prev
1 2