: -----Original Message----- : From: owner-cgi-list@jann.com [mailto:owner-cgi-list@jann.com] : On Behalf Of Vuillemot, Ward W : Sent: Tuesday, December 18, 2001 10:59 AM : To: cgi-list@jann.com : Subject: [CGI] OT using use with variables : : : According to www.perldoc.com regarding 'use', I believe : you must use barewords for module names. Is this correct? : : I want to do something like : : &$app::main($var1,$var2); : : where $app is provided elsewhere. : is there a way to do it? I have tried an eval statement, but it : fails. doing it directly also fails. ---------------------------------- Answers to both of your questions appear in like order below: ---------------------------------- : According to www.perldoc.com regarding 'use', I believe you : must use barewords for module names. Is this correct? No, not correct. You use "package names". (eg- glorified "barewords"). The package name which follows the use() command corresponds to the name of the module wherein that external code resides. Package names tell Perl which "package" or namespace to look in for the variables and methods of the module who's name is the same as the package it holds. CGI.pm holds the CGI package. CGI::param() is the method which you use to collect data passed to your script from a form or a query string. CGI::new() is the method you use in order to create new CGI objects. When you use methods, variables, and other things from Perl modules, you should call them with the arrow syntax as shown in the example code below. That syntax forces Perl to pass the package name to the constructor method inside that external module as the first argument which that method receives in its @_. Modules are built to expect this. The package name which is implicitly passed to the method in your module (when the arrow syntax is used) tells Perl the namespace wherein that code resides. That helps the ModuleX::new() # constructor method method gain access to its other methods and variables so it can carry out tasks which it might pass to other routines in the same module when you call it from your script. For example, CGI::new() uses lots of other routines in its namespace in order to initialize each new CGI object with all of the elements you'd expect a CGI object to have. CGI::new() has to store data about the CGI environment (%ENV), data about the way it was called (@ARGV), data submitted from forms, query strings, or even from the command line. If CGI::new needs to get to its those other methods, it could use that package name which Perl sent to it (along with any other arguments you passed yourself when you called it) in order to find where those methods are. When you have Perl pass a package name by using the arrow operator, CGI::new knows where to look to find its other methods. It knows that its param method is at CGI::param, and can tell Perl to go there and not be confused with any other subroutine in your script or in other modules which might happen to be named 'param' as well. : I want to do something like : : &$app::main($var1,$var2); : : where $app is provided elsewhere. : is there a way to do it? I have tried an eval statement, : but it fails. doing it directly also fails. Solution: $app->main($var1,$var2) if (UNIVERSAL::isa($app,'login'); Make sure that app::main() is expecting a reference to it's namespace. Perl will send it one when you call it with the arrow, which is what you should do if $app::main holds a reference to your module. You see, when you call a module with a package name and an arrow ( eg- CGI->new() ), Perl stuffs that package name into the @_ which CGI::new() receives. That way CGI::new() can create a new CGI object with that package name. The object it creates is, of course, named CGI. CGI::new(), and every other module you use will normally pass you back a reference to the new object it just made with its package name that you provided. You can use that reference to the new CGI object to get a cached version of any of the code inside it. Otherwise, if you always use CGI.pm in a manner where you call its methods like normal subroutines (eg- CGI::param(), CGI::header(), etc.) Perl will not give you the same benefits of using modular OO code objects. In fact, you just end up with a very bloated script. Once you have a reference to the new precompiled CGI object (NOT the same as a simple imported code library! This is discussed below) you can use that reference to call those cached methods. When you call those pre-cached methods inside your object with the reference to it which your constructor method sent back (the constructor method is CGI::new() ) Perl will now pass those methods a reference of their own as the first argument in their @_. This is why all methods or 'routines' in modules usually start out with the same argument: my($self) = shift; Where Perl first passed a string containing the package name to CGI::new when you called it with the arrow ( CGI->new() ), it now passes its methods a reference to the 'CGI' package name when you call them with the reference you got back from CGI::new(). These object methods expect that their first argument is the reference to the CGI object which you made with CGI::new(), and now that method can call all of its friends without bogging down the Perl interpreter by making it create a new copy of the code inside them each time they are called. Those methods also need access to the object which CGI::new() created for you. They want the benefits of using that pre-compiled code as well. They don't want to call the other methods in CGI.pm or ask for the other package variables in CGI.pm without that reference because Perl will have to create a whole copy of those subroutines and variables each time you do. And this is where the benefit of OO programming is manifest, and why well designed modules make scripts faster than they could otherwise have been. Objects are faster. Objects are compiled once, used over and over as many times as you want, they make your scripts cleaner, they make your development more quick and easy, and when you throw away the reference to them, Perl frees up the memory which held that object for the rest of your script to use. Use once and again, then throw them away to make room and reserve resources for more, or for your script. Objects are the bomb! You never get that benefit when you don't use Objects. When you don't use objects in your programming and your scripts use any of its subroutines more than one time, you are quite often making your script slower and making Perl work harder than it needs to. When you use a module correctly, you get a script that runs (and looks) "like a streamlined butterfly." It will work much more cleanly, execute much more rapidly, and only compile the methods you need. Modules like CGI.pm are not only well known, but well designed. CGI.pm is so smart that it only lets Perl compile a very limited portion of its internals when called correctly like: CGI->new() and only if you ever ask it for one of its less-used methods, such as the ones used to create HTML for you, will it ever load them into the executing process and run them for you. CGI.pm is smarter than the average bear --and smarter than the majority of those who use it too :o) As a quick review, we'll look at a quick code example and be done with it. You can ask me any questions if the code or the text of this post was confusing... and it may be confusing if I wrote it! Let's say our script uses my handy File utilities module from the Atrixnet Perl archives... # use File utilities module use Futils; # make a new Futils object, and store the # reference to its package name which the # Futils::new() subroutine will return my($objectref) = Futils->new(); Now inside Futils.pm, Futils::new() grabs that special reference which Perl passes to it when we called it with an arrow in our script. # -------------------------------------------------------- # Futils::new() # -------------------------------------------------------- sub new { # This is the 'constructor method', or 'the object # oriented subroutine used to make new Futils objects' [note- this is a simplified version of the actual Futils code] my($class) = shift; my($this) = {}; # Make a new Futils object with out of the variable # named '$this', and name it after the package name # that was sent to us from the caller and just saved # in '$class''. That package name happens to be... # # ...drum roll please... # "Futils" !!! # Or in OO speak, tell Perl to "bless()" the variable # named '$this' to become a new object or "instance" # of the code inside the 'Futils' package namespace. # (I liked the first explanation better.) bless($this, $class); # now that Perl has made a sleek new Futils object, it # gives us a reference to it by turning '$this' into # the new object, saving it in memory for its greedy # little self, and then only giving us back a reference # to it. (kind of like, "My parents went to Niagara Falls # and all I got was this lousy T-shirt") That reference # just happens to be returned to us when Perl keeps the # object for us in memory, and sends us back a reference # to it really sneaky by stuffing it into '$this' # Now we'll share it with others: # return the reference to this object back to # the caller... return($this); } Quick code explanation: Futils knows it is going to get its package name from the caller, so it grabs that as its first argument and saves it in a variable. It then bless()-s a separate variable into object-hood using the package namespace which Perl passed to it with any other arguments you may have passed as well. In other words, Perl creates a new object named Futils, and sends the caller a reference to the new object. -Tommy Butler, consultant Atrixnet, for Internet Business Software http://atrixnet.com 2200 North Lamar Suite 307 Dallas, TX 75202 -- Visit the open source Perl archives at Atrixnet http://www.atrixnet.com/pub/