Suppose a class or other module creates other packages to get its job done. It may need targets for blessings to handle overloaded operators, or targets for tie, or just to keep things neat.

Now for variables that should not be seen outside of the module, we have my. If you wanted to hide a function, you could use a local function reference instead.

But what about packages? In C++ an anonymous namespace will localize anything to the current translation unit (source file), including class names. In Perl, a package pretty much has to have an actual name. That is, it can't be a local reference to an unnamed object (e.g. what Symbol::gensym does). I suppose the normal way of doing this is by assuming that if I named my module Foo, than no other module named Foo exists, and Foo::x, Foo::y, etc. are all OK. Big comments say that those internal namespaces are, well, internal (e.g. see documentation for Carp::Heavy). If more than one developer or a distributed team is working on the same module, then you still have to be careful about conflicts, and perhaps use an internal naming convention.

But, is there a better way? Are there any other ways, really? Is there anything proposed for Perl 6 that will better hide internal details from other code?

—John

Replies are listed 'Best First'.
(tye)Re: Hiding Internal Classes ?
by tye (Sage) on Jul 11, 2001 at 00:05 UTC

    Perl has never been much of a bondage-and-discipline language. There is nothing to stop you from doing lots of stupid things except, well, "sense". If you want to convey that a namespace is "internal" besides the comments (and people using namespaces without reading the documentation for them don't have enough "sense"), then prepend an underscore to it ("Carp::_Heavy", for example). The leading underscore to mean "for internal use only" is a "standard" in Perl.

            - tye (but my friends call me "Tye")
Re (tilly) 1: Hiding Internal Classes ?
by tilly (Archbishop) on Jul 11, 2001 at 01:46 UTC
    Well you can always use things like Class::Object, Class::Classless, and the like.

    There was also talk of having support for truly anonymous classes. (In fact Simon Cozens tried to single-handedly add support for that to Perl 5 and was told not to.) I have no idea what current plans for that are supposed to be.

    As for better ways, well I like the way that Smalltalk does it (and other languages have borrowed it - I am more familiar with the way it works in Ruby than Smalltalk). In Smalltalk a class is an object. Any variable can hold a class, but normally you would want your classes to be held in global variables. An object belongs to a class. The methods of an object are accessed through a lookup on the class. There is a distinction here between class methods (ie methods of the class object) and object methods (ie methods of the object that is a member of the class).

    For instance Ruby has a File class. File has methods relating to files but not a specific file, for instance it has methods for various file tests. When you call File.open you get an instance of class File. This instance has methods appropriate to handling a file, you can read, print, and so on. However it makes no sense to ask a file whether another file exists, so you can't. That isn't an object method. It makes no sense to ask the concept of a File to read the next line. So you can't. That isn't a class method.

    Perl confuses object and class methods in a most unfortunate way. However if you wanted to, you could create the above structure in Perl. You could probably do it fairly efficiently. These classes would usually be anonymous. Hmm....

    But I won't. Yet.

      A class it itself an object: Yes, if blessing (and @ISA) referred to the underlying symbol table hash, rather than it's name, then you could use references to unnamed classes. But the implementation is based on the string, not what it ultimatly resolves to.

      Why?

        Probably because Perl's OO is a hack on top of package namespaces. Constructed at a time when references were still really new in Perl, and nobody knew how useful they would turn out to be or how far they would go.

        And the idea of a class as an object is not part of Perl. Indeed there are many Perl programmers who think it a ood idea to make what I would say should be class methods into object methods. (Yes, I am referring to the testing in new whether you are passed something blessed...)

Re: Hiding Internal Classes ?
by bikeNomad (Priest) on Jul 11, 2001 at 03:25 UTC
    John,

    Toby Everett and I have just come up with a pretty complete solution to this and many other problems. Our solution is a much better way to handle dynamically created packages. We're still polishing it up before we put it on CPAN, but if you want to get a pre-release peek at it, take a look at ftp://ftp.bike-nomad.com/Class-Prototyped-0.03.tar.gz.

    The basic idea is to have each object live in its own namespace, with automatically generated names. And you have complete control over inheritance (from other objects or regular Perl classes), and a full reflection capability, and the ability to add and delete data fields or subroutines on the fly and have everything work dynamically.

    And subroutine calls are just as fast as regular Perl calls. If you've done any work with the Self language, you'll appreciate the ability to make objects with unique behavior that can inherit from other objects or classes.

    Take a look at our work; we'd enjoy suggestions.

Re: Hiding Internal Classes ?
by Anonymous Monk on Jul 10, 2001 at 23:09 UTC
    What does a call of a method over a blessed reference if you have deleted the symbol of the package in %main::?
      I really don't understand what you said. But, I find that methods can still be called when the symbol for the package is deleted. So, does that mean that blessing is symbolic after all? No, because a newly minted object does not work. So I suspect it's a cacheing thing.

      use v5.6.1; #ActiveState build 626 use strict; use warnings; package Foo; sub bar { print "Foo::bar has been called\n"; } sub new { my $s= 0; return bless \$s, "Foo"; } package main; *newFoo= \&Foo::new; my $x1= new Foo::; $x1->bar(); # OK print "before:", join (' ', keys %main::), "\n"; delete $main::{"Foo::"}; print "after:", join (' ', keys %main::), "\n"; $x1->bar(); # still works! my $x2= newFoo(); # works $x2->bar(); # can't find "Foo"

        Yes, methods are cached. Changing @ISA causes the cache to be invalidated except (apparently) for non-inherited methods. undefing or redefining the subroutine rather than the whole package is correctly handled by the caching code. I'm not surprised that the caching code doesn't expect people to undef the whole package. (:

                - tye (but my friends call me "Tye")