in reply to multiple "sub" packages in 1 file: possible? how?

I really wouldn't recommend using packages this way. However, if you're intent on doing it this way, this seems to work:

use strict; use warnings; use Test::More 'no_plan'; package my_temp_convert; my $curr_scale=0; #centigrade, 1=faren my $cur_ctemp=0; sub set_scale{ $curr_scale=shift} sub set_temp{ $cur_ctemp =shift} sub c {return $cur_ctemp;} sub f {return 32+(9*$cur_ctemp)/5} package main; *set_scale = \&my_temp_convert::set_scale; *set_temp = \&my_temp_convert::set_temp; *c = \&my_temp_convert::c; *f = \&my_temp_convert::f; set_scale(1); set_temp(0); is( f(), 32, 'f() returns 32' ); is( c(), 0, 'c() returns 0' );

You might also want to look at Re^3: Beyond Inside-Out (details), which has some interesting examples.

Generally, I'd advise using a real object for this kind of job. Then you'd do:

my $temp = My::Temp::Thing->new(); $temp->set_c(0); is( $temp->get_f(), 32, '0 c is 32 f' );

In that case, you don't clutter your current name space with junk from another package. You can have multiple temperature objects instead of just One. Etc.

Replies are listed 'Best First'.
Re^2: multiple "sub" packages in 1 file: possible? how?
by perl-diddler (Chaplain) on Aug 05, 2007 at 03:11 UTC
    As I mentioned, using the "package" construct within same file was a "development" step before potentially splitting it off into another file.

    The objectification of the items in the packages is _desirable_, but I haven't gotten to the point of figuring out what things I want to "objectify".

    It's a case of I first developed a "script" (if you can call something around 500+ lines 'a script' :-)) -- that started as "hacks" (my first GUI using Tk; hope to convert to native Win32 if/when I get things properly abstracted and objectified). So your advice to restructure using objects is desirable, though possibly premature -- I'm trying to "evolve" the program toward something more modular and clean. Starting from an example that displays a single "picture", I've been evolving/modifying the program from there.

    From the large glob of "prog" I have now, I want to move to objects where it makes sense, but first I want to "conceptually" break apart "functions" by putting groups of functions into separate packages.

    Perhaps unrealistically idealistic, I'd like to be able to accomplish:

    ...prog... use moda; use modb; ....
    where instead of putting the code for "moda" and "modb" in separate files, I can include it "inline". Ideally, I'd like to use the standard "Export" type functions within the defined packages, to somehow specify the functions I want to use as interface functions.

    I notice you are using the "*func=\&mypackage::func" notation to import specific names from the packages. Is there anyway to do that using the standard "Exporter" and "@Exports=" functionality? I.e. pretty much as if I literally copied a normal "package" into my file -- maintains its own namespace, but uses "Exports" to define the exported interface.

    If it is not possible, at least I could use "manual" mode of "exporting" my functions from the packages into the main symbol table via the "*func=..." construct. Seemingly not as elegant as using the standard "Exporter" functions, but perhaps the best alternative.

    Thanks for the suggestions...at least I can use the above temporarily until I find something better...:-)

      Well, this works too, if you really want to go through Exporter. I don't think you're going to be able to use as you would if the package were in a separate file since use really implies other fileness.

      use strict; use warnings; use Test::More 'no_plan'; package my_temp_convert; require Exporter; our @ISA = ('Exporter'); our @EXPORT = qw(set_temp set_scale c f); my $curr_scale=0; #centigrade, 1=faren my $cur_ctemp=0; sub set_scale{ $curr_scale=shift} sub set_temp{ $cur_ctemp =shift} sub c {return $cur_ctemp;} sub f {return 32+(9*$cur_ctemp)/5} package main; Exporter::import( 'my_temp_convert' ); set_scale(1); set_temp(0); is( f(), 32, 'f() returns 32' ); is( c(), 0, 'c() returns 0' );
        Exporter::import( 'my_temp_convert' );

        Careful! import() is a method, so that line tries to import code from a package named my_temp_convert.