Re: Programming style: using Classes or inline




David wrote:
What I was trying to
do was something I guess not appropriate in Perl.  What I had attempted
was to keep it modular - I had three component files - but none were
defined as packages.  I'd attempted to keep the related portions of the
code in separate files, and then just include them into the main program.
In the fashion as you would in C.  In C, if you "include " a file, the
code and all variables in all these files are treated as if it were one
single file.  I found that this didn't work this way in Perl.

I think a "require" of a file that does not define a package may behave
similarly to what C does.  But there are caveats, and it's not as nice as
proper packages, so i never do it and can't really tell you.


An important thing to remember when placing a bunch of classes in one
file is that execution order still matters.  When using "require" or
"use", your whole pm file will be parsed and then executed.  If you
have all the classes in one file, all of the code will be parsed, but
whether it will be executed depends on the position in the file.

Not trying to be a grammar police, but, for my understanding, do you
mean "will have been executed"?  It appears that in the following code
all executes, but the question is whether it has executed by the time
(in this case) main:: does its thing.

You're correct.  More appropriate would be "when it will be executed".  Note
that if i'd put an "exit" at the end of main, the initialization code in
ThingTwo would not have run at all.


I had not even thought about executable code outside of a subroutin in a
package.  Since you bring up this point, wouldn't it be wise to avoid,
if at all possible, having any executable code outside a subroutine in a
package.  Again, I'm really new at this, but I'd think that it would be
best to do all initialization that you can from within your constructor.
Of course, I realize that this program you supplied was for
demonstration purposes.

Since packages are typically in pm files that are "use"d or "require"d, it's
not much of a problem.  The code outside of subroutines will be executed once,
when the files are "require"d ("use" performs a "require").  In many
situations, you need code outside of subroutines in modules for things like
initializing @ISA or @EXPORT_OK.  If you are placing your package at the
bottom a single-file program, you want to wrap that in a BEGIN block to ensure
that it executes at the right time.

In fact, convention for XS extensions is to have the bootstrapping calls
outside of subroutines.  See, for example, Glib.pm and Gtk2.pm.  This
effectively guarantees that they get called, and that they get called once.


To  wit:
[ .. sample program .. ]

Figuring out why is left as an exercise for you.  :-)

Yeah, think I followed it all..  Just tried something.  I cut-and-pasted
your program putting the three packages into separate files, and
inserting corresponding "use " statements at the appropriate places and
the program ran without error or warning.  I had expected the same
results as the single-file.pl.  Did I see somewhere that "use"
statements are all processed at compile time, regardless of position?

Yes.  Essentially, when "require"ing a file, it gets parsed, compiled, and
then executed before the "require" returns.  A "use", which performs a
"require", happens at compile time, so code in included modules gets executed
at compile time, a la BEGIN blocks.

"perldoc -f require" explains it in detail.  The perlmod manpage adds

   Because the "use" statement implies a "BEGIN" block, the importing of
   semantics happens as soon as the "use" statement is compiled, before
   the rest of the file is compiled.  This is how it is able to function
   as a pragma mechanism, and also how modules are able to declare sub-
   routines that are then visible as list or unary operators for the rest
   of the current file.  This will not work if you use "require" instead
   of "use".  With "require" you can get into this problem:

       require Cwd;                # make Cwd:: accessible
       $here = Cwd::getcwd();

       use Cwd;                    # import names from Cwd::
       $here = getcwd();

       require Cwd;                # make Cwd:: accessible
       $here = getcwd();           # oops! no main::getcwd()

   In general, "use Module ()" is recommended over "require Module",
   because it determines module availability at compile time, not in the
   middle of your program's execution.  An exception would be if two mod-
   ules each tried to "use" each other, and each also called a function
   from that other module.  In that case, it's easy to use "require"
   instead.




-- 
muppet <scott at asofyet dot org>





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]