www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Optional module names export list

reply bearophile <bearophileHUGS lycos.com> writes:
In a Python module if you define a name with a starting underscore, that name
will be private to that module, and it will not be imported if a command "from
module_name import *" is used:

class Name1: pass
def name2(): pass
_private_name3 = 3
name4 = 4

In Python there is another optional way to specify the list of names imported:
if a module (or package __init__.py code) defines a list named __all__, it is
taken to be the list of module names that should be imported when a "from
package import *" command is used.

So from this module you will not import name2 and _private_name3:

class Name1: pass
def name2(): pass
_private_name3 = 3
name4 = 4
__all__ = ["Name1", "name4"]


In Haskell there is a similar way to list the names to export from a module,
this module exports the name1, Name2, name3, ... names only:

module Foo(name1, Name2, name3, ...) where
-- module contents here


Several other languages have a similar feature.

In a D module you add a "private" beside each global name you don't want to
export from a module. (Maybe you are also allowed to use a "private:" at the
module top, and then add a "public" to each of the names you want to export,
but this doesn't look so safe, because you may miss a "public:" lost in the
middle of the module code).

For a safer management of exported names, in D it may be useful an optional way
to explicitly list (probably at the top of the module) the module names
exported. A possible syntax is similar to the Haskell one:

module foo(name1, name2, Name3, ...);

Bye,
bearophile
Feb 19 2011
next sibling parent reply spir <denis.spir gmail.com> writes:
On 02/20/2011 12:46 AM, bearophile wrote:
 In a Python module if you define a name with a starting underscore, that name
will be private to that module, and it will not be imported if a command "from
module_name import *" is used:

 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4

 In Python there is another optional way to specify the list of names imported:
if a module (or package __init__.py code) defines a list named __all__, it is
taken to be the list of module names that should be imported when a "from
package import *" command is used.

 So from this module you will not import name2 and _private_name3:

 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4
 __all__ = ["Name1", "name4"]


 In Haskell there is a similar way to list the names to export from a module,
this module exports the name1, Name2, name3, ... names only:

 module Foo(name1, Name2, name3, ...) where
 -- module contents here


 Several other languages have a similar feature.

 In a D module you add a "private" beside each global name you don't want to
export from a module. (Maybe you are also allowed to use a "private:" at the
module top, and then add a "public" to each of the names you want to export,
but this doesn't look so safe, because you may miss a "public:" lost in the
middle of the module code).

 For a safer management of exported names, in D it may be useful an optional
way to explicitly list (probably at the top of the module) the module names
exported. A possible syntax is similar to the Haskell one:

 module foo(name1, name2, Name3, ...);

 Bye,
 bearophile

I would love such a feature. In fact, I think import foo; should launch Error: module 'foo' does not define exported symbols. if, actually, 'foo' does not... Denis -- _________________ vita es estrany spir.wikidot.com
Feb 19 2011
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 20.02.2011 3:48, spir wrote:
 On 02/20/2011 12:46 AM, bearophile wrote:
 In a Python module if you define a name with a starting underscore, 
 that name will be private to that module, and it will not be imported 
 if a command "from module_name import *" is used:

 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4

 In Python there is another optional way to specify the list of names 
 imported: if a module (or package __init__.py code) defines a list 
 named __all__, it is taken to be the list of module names that should 
 be imported when a "from package import *" command is used.

 So from this module you will not import name2 and _private_name3:

 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4
 __all__ = ["Name1", "name4"]


 In Haskell there is a similar way to list the names to export from a 
 module, this module exports the name1, Name2, name3, ... names only:

 module Foo(name1, Name2, name3, ...) where
 -- module contents here


 Several other languages have a similar feature.

 In a D module you add a "private" beside each global name you don't 
 want to export from a module. (Maybe you are also allowed to use a 
 "private:" at the module top, and then add a "public" to each of the 
 names you want to export, but this doesn't look so safe, because you 
 may miss a "public:" lost in the middle of the module code).

 For a safer management of exported names, in D it may be useful an 
 optional way to explicitly list (probably at the top of the module) 
 the module names exported. A possible syntax is similar to the 
 Haskell one:

 module foo(name1, name2, Name3, ...);

 Bye,
 bearophile

I would love such a feature. In fact, I think import foo; should launch Error: module 'foo' does not define exported symbols. if, actually, 'foo' does not...

foo may have module constructors/destructors... Anyway why would it export nothing / what's wrong about it? And by the way we have, in fact, very reasonable module system + protection from function hijacking. I just can't stand all this talk about *explicitness* where it's *not* needed. Let's retype all of imported symbols, let's retype all of exported symbols. Then let's retype all of imported symbols we are going to use... That's all is inferior try at protect from function (symbol) hijacking by use of programmer convention.. never worked. And only for the sake of 'some other language have it', I'm not buying it. -- Dmitry Olshansky
Feb 20 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 19 February 2011 15:46:51 bearophile wrote:
 In a Python module if you define a name with a starting underscore, that
 name will be private to that module, and it will not be imported if a
 command "from module_name import *" is used:
 
 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4
 
 In Python there is another optional way to specify the list of names
 imported: if a module (or package __init__.py code) defines a list named
 __all__, it is taken to be the list of module names that should be
 imported when a "from package import *" command is used.
 
 So from this module you will not import name2 and _private_name3:
 
 class Name1: pass
 def name2(): pass
 _private_name3 = 3
 name4 = 4
 __all__ = ["Name1", "name4"]
 
 
 In Haskell there is a similar way to list the names to export from a
 module, this module exports the name1, Name2, name3, ... names only:
 
 module Foo(name1, Name2, name3, ...) where
 -- module contents here
 
 
 Several other languages have a similar feature.
 
 In a D module you add a "private" beside each global name you don't want to
 export from a module. (Maybe you are also allowed to use a "private:" at
 the module top, and then add a "public" to each of the names you want to
 export, but this doesn't look so safe, because you may miss a "public:"
 lost in the middle of the module code).
 
 For a safer management of exported names, in D it may be useful an optional
 way to explicitly list (probably at the top of the module) the module
 names exported. A possible syntax is similar to the Haskell one:
 
 module foo(name1, name2, Name3, ...);

And _what_ is wrong with using public and private? They do the job just fine. Adding other ways to do it would just complicate things. Other programming languages have chosen other ways to handle what is and isn't imported or exported from a module. D uses the same method that Java and C# do. It's straightforward, well known, well understood, and it works quite well. I'm not saying that there's anything wrong with how other languages have done it (though honestly, having a list of exportable symbols _is_ really annoying when the list isn't short), but D already has a way to deal with this, and it works just fine. There's no need to add another. The added value to having another way to do it wolud be neglible, and it would not only complicate the compiler but make it so that there's even more that a D programmer would have to know about to be able to read and deal with other people's code. The cost therefore would be very high. This suggestion adds almost nothing and costs a fair bit in complexity and intellectual overhead. What he have works just fine. There's no need to change it. - Jonathan M Davis
Feb 19 2011