www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - private module stuff

reply Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
	So I was learning how to make a module of mine very strict with private 
parts, and was surprised I could only do this with global variables and 
functions.   Enums, structs, and classes are fully visible outside the 
module regardless of being wrapped in a private{} or prefixed with 
private.  Am I expecting too much here?



rough code:


module mymoduletree.mymodule;

private
{
struct foo
{
int x;
int y;
}

int somevar = 4;
}


.....


module someothertree.othermodule;

import mymoduletree.mymodule;

int bar(int arg)
{
     foo var;  // why can i use this type here??
     var.x = arg;
     var.y = somevar;  // this generates an error (access of somevar is 
private and not allowed)
     return var.y;
}
May 08 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Sean Cavanaugh:

 	So I was learning how to make a module of mine very strict with private 
 parts, and was surprised I could only do this with global variables and 
 functions.   Enums, structs, and classes are fully visible outside the 
 module regardless of being wrapped in a private{} or prefixed with 
 private.  Am I expecting too much here?
You are expecting the right thing. If you are right, then it's a bug that eventually needs to be fixed. Take a look in Bugzilla, there are several already reported import/module-related bugs. Bye, bearophile
May 08 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
 Sean Cavanaugh:
 	So I was learning how to make a module of mine very strict with private
 
 parts, and was surprised I could only do this with global variables and
 functions.   Enums, structs, and classes are fully visible outside the
 module regardless of being wrapped in a private{} or prefixed with
 private.  Am I expecting too much here?
You are expecting the right thing. If you are right, then it's a bug that eventually needs to be fixed. Take a look in Bugzilla, there are several already reported import/module-related bugs.
They're private _access_ but still visible. I believe that that is the correct behavior and not a bug at all. I believe that it's necessary for stuff like where various functions in std.algorithm return auto and return a private struct which you cannot construct yourself. Code which uses that struct needs to know about it so that it can use it properly, but since it's private, it can't declare it directly. It works because the types are appropriately generic (ranges in this case). Regardless, I believe that the current behavior with private is intended. - Jonathan M Davis
May 08 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 They're private _access_ but still visible.
In my opinion this is not good, it looks like a messy special case.
 I believe that it's necessary for stuff like 
 where various functions in std.algorithm return auto and return a private 
 struct which you cannot construct yourself.
Do you mean something like this? This returns a struct defined inside, but it's not a private definition. auto foo() { struct Bar {} return Bar(); } Bye, bearophile
May 08 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
 Jonathan M Davis:
 They're private _access_ but still visible.
In my opinion this is not good, it looks like a messy special case.
 I believe that it's necessary for stuff like
 where various functions in std.algorithm return auto and return a private
 struct which you cannot construct yourself.
visibility, though in most cases, there's no real difference in usage. So, there's nothing abnormal - quite the opposite really - with D doing what it's doing.
 Do you mean something like this? This returns a struct defined inside, but
 it's not a private definition.
 
 auto foo() {
   struct Bar {}
   return Bar();
 }
True. That wasn't the best example, since that's not techinically private, but you can run into the same situation with classes or structs which _are_ private. - Jonathan M Davis
May 08 2011
prev sibling parent reply Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 5/8/2011 4:05 AM, Jonathan M Davis wrote:
 Sean Cavanaugh:
 	So I was learning how to make a module of mine very strict with private

 parts, and was surprised I could only do this with global variables and
 functions.   Enums, structs, and classes are fully visible outside the
 module regardless of being wrapped in a private{} or prefixed with
 private.  Am I expecting too much here?
You are expecting the right thing. If you are right, then it's a bug that eventually needs to be fixed. Take a look in Bugzilla, there are several already reported import/module-related bugs.
They're private _access_ but still visible. I believe that that is the correct behavior and not a bug at all. I believe that it's necessary for stuff like where various functions in std.algorithm return auto and return a private struct which you cannot construct yourself. Code which uses that struct needs to know about it so that it can use it properly, but since it's private, it can't declare it directly. It works because the types are appropriately generic (ranges in this case). Regardless, I believe that the current behavior with private is intended. - Jonathan M Davis
The more I play with private/protected/package the more confused I am by it. For the most part the rules are: Functions and variables have protection Types (enum, struct, class) do not this and ~this are special and are not considered functions, and are always public struct and class members always default to public If you search phobos you will find occurences of 'private struct' and 'private class', so even the people writing libraries are expecting something to be happening that isn't. For example: //in std.parallelism: private struct AbstractTask { mixin BaseMixin!(TaskStatus.notStarted); void job() { runTask(&this); } } //and in std.demangle: private class MangleException : Exception { this() { super("MangleException"); } } and in my code I can compile the following without compile-time errors: import std.parallelism; import std.demangle; int main() { MangleException bar = new MangleException(); AbstractTask foo; foo.job(); return 0; } With the language the way it is now, it is nonsensical to have the attributes public/protected/package/private/export precede the keyword struct, class, or enum.
May 08 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Sean Cavanaugh:

 With the language the way it is now, it is nonsensical to have the 
 attributes public/protected/package/private/export precede the keyword 
 struct, class, or enum.
It's an implementation bug or a design bug. If it's not already in Bugzilla then it deserves to be there. Bye, bearophile
May 08 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
 On 5/8/2011 4:05 AM, Jonathan M Davis wrote:
 Sean Cavanaugh:
 	So I was learning how to make a module of mine very strict with
 	private
 
 parts, and was surprised I could only do this with global variables and
 functions.   Enums, structs, and classes are fully visible outside the
 module regardless of being wrapped in a private{} or prefixed with
 private.  Am I expecting too much here?
You are expecting the right thing. If you are right, then it's a bug that eventually needs to be fixed. Take a look in Bugzilla, there are several already reported import/module-related bugs.
They're private _access_ but still visible. I believe that that is the correct behavior and not a bug at all. I believe that it's necessary for stuff like where various functions in std.algorithm return auto and return a private struct which you cannot construct yourself. Code which uses that struct needs to know about it so that it can use it properly, but since it's private, it can't declare it directly. It works because the types are appropriately generic (ranges in this case). Regardless, I believe that the current behavior with private is intended. - Jonathan M Davis
The more I play with private/protected/package the more confused I am by it. For the most part the rules are: Functions and variables have protection Types (enum, struct, class) do not this and ~this are special and are not considered functions, and are always public struct and class members always default to public If you search phobos you will find occurences of 'private struct' and 'private class', so even the people writing libraries are expecting something to be happening that isn't. For example: //in std.parallelism: private struct AbstractTask { mixin BaseMixin!(TaskStatus.notStarted); void job() { runTask(&this); } } //and in std.demangle: private class MangleException : Exception { this() { super("MangleException"); } } and in my code I can compile the following without compile-time errors: import std.parallelism; import std.demangle; int main() { MangleException bar = new MangleException(); AbstractTask foo; foo.job(); return 0; } With the language the way it is now, it is nonsensical to have the attributes public/protected/package/private/export precede the keyword struct, class, or enum.
private, public, protected, and private are _always_ about access and _never_ about visibility. They affect whether you can _use_ a particular symbol in a particular piece of code, _not_ whether the compiler can see it in that context. It doesn't matter whether it's a function, variable, class, etc. Now, there may be bugs in the current implementation, but the design is fairly straightforward. For instance, anything templated is currently always public regardless of what you mark it as ( http://d.puremagic.com/issues/show_bug.cgi?id=1904 , http://d.puremagic.com/issues/show_bug.cgi?id=2775 ). Also, it looks like there is a bug report for structs and classes not dealing with private properly ( http://d.puremagic.com/issues/show_bug.cgi?id=2830 ) when the entire class or struct is marked as private. So unfortunately, the implementation _is_ currently buggy, but the design is fairly straightforward. Oh, and this and ~this _are_ functions (albeit special) and can be made private - or even outright removed entirely with disable. Traits works with __ctor and __dtor rather than this and ~this, and you can call the constructor with __ctor (though it's unlikely that there's a case where you should) and the destructor with __dtor (though there probably isn't really a valid case to do that - use clear instead, and it'll call the destructor along with everything else it does). The thing with the default constructor is that it exists if you don't declare any constructors, and it'll default to public, so you generally have to declare it and make it private if you want it to have a default constructor and not have it public. That _does_ seem like a likely place for a bug in the case where the class is private, but since that's completely broken right now anyway, that's not really a concern. The destructor is in the same boat, though why you'd want to make the destructor private, I don't know. And structs don't have the issue with default constructors because they can't have them. So, yes, the current implementation is broken (and more broken than I thought that it was actually), but the basic design is quite straightforward. I would think that assuming that dmd were not buggy with regards to private that the access specifiers would generally work as you expect them to - though there may be some cases where they would surprise you. For instance, per TDPL, private member functions are overridable but not callable (as they wolud be in C++) by derived classes, which surprises a lot of people in C++ (though presently, private functions are not overridable - there's at least one bug report on it - so this surprising issue doesn't come up right now). And it's because access specifiers are for _access_ only, not visibility. - Jonathan M Davis
May 08 2011