If you know what use does (perldoc -f use, perldoc -f require) ...
an example is File::Spec (a core module)
package File::Spec;
use strict;
use vars qw(@ISA $VERSION);
$VERSION = '0.86';
my %module = (MacOS => 'Mac',
MSWin32 => 'Win32',
os2 => 'OS2',
VMS => 'VMS',
epoc => 'Epoc',
NetWare => 'Win32', # Yes, File::Spec::Win32 works on Ne
+tWare.
dos => 'OS2', # Yes, File::Spec::OS2 works on DJGP
+P.
cygwin => 'Cygwin');
my $module = $module{$^O} || 'Unix';
require "File/Spec/$module.pm";
@ISA = ("File::Spec::$module");
1;
__END__
Sure you don't need to actually require/use anything, but @ISA is @ISA ;)(perldoc perlmod, perldoc perlvar ...)
| MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!" | | I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README). | | ** The third rule of perl club is a statement of fact: pod is sexy. |
| [reply] [d/l] |
require is definitely a good and straight answer to the question, and I believe this must be one of the original reasons made them to have require in Perl in the first place. As sometime, you simply either cannot determine what to use at compile time, or you cannot determine whether you even require anything.
The other way seems also very natual is to have a base class and those platform-specific classes subclass it. Less efficient, but chance is that there are common attributes across platforms, and could be a pretty neat design.
Actually should be a mixture of both, a neat OO design with dynamically loading of subclasses.
| [reply] |
I'd put the various packages in different files. For instance,
the file mac.pm:
package mac;
use strict;
use warnings;
use Exporter ();
our @EXPORT = qw /get_answer/;
our @ISA = qw /Exporter/;
sub get_answer {
"mac";
}
1;
__END__
And then the main program:
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
if ( $^O =~ /dar/ ) { require mac; mac -> import; }
elsif ( $^O =~ /sol/ ) { require sun; sun -> import; }
elsif ( $^O =~ /aix/ ) { require aix; aix -> import; }
else { die "unknown os." }
};
print "answer is " . get_answer () . "\n";
__END__
Abigail | [reply] [d/l] [select] |
You could try using inheritance and polymorphism
our $Type ;
BEGIN {
if ( $^O =~ /dar/ ) { $Type = 'Mac' ; }
elsif ( $^O =~ /sol/ ) { $Type = 'Sun' }
elsif ( $^O =~ /aix/ ) { $Type = 'Aix' }
else { die "unknown os." }
};
package base ;
sub common_routine {}
sub specific_routine { die "must be one of mac, aix, sun" ; }
sub
package Mac ;
our(@ISA) = qw/base/ ;
sub specific_routine { DoMacStuff()}
package Aix;
our(@ISA) = qw/base/ ;
sub specific_routine { DoAIXStuff()}
package Sun ;
our(@ISA) = qw/base/ ;
sub specific_routine { DoSunStuff()}
package main ;
my($obj) = new $Type ;
$obj->specific_routine ;
Nuts and Bolts
We start with a 'base' package. This will contain all of the methods that are common to all the platforms. Then for each supported platform we create a new package, and declare within it the @ISA variable(this package 'is a' ...) so that when perl wants to find a method when doing $obj->method_name, it will first check the objects package, if it doesn't find it there, it will go through each package in the @ISA list, and execute the first 'method_name' it finds. This is how perl does OOP polymorphism, the facility for different classes to have different implementations for the same 'method_name'.
For each method, that will need a different implementation for a given platform, we'll first add that method to the base package, which may just include a 'die' to remind us to implement this method for this platform we're testing on, and then add the method in each specific platform.
It possible that some methods may service several platforms, and one just needs it a little differently, in which case we can put the common method in the 'base' package, and the one that needs to be different in its own pacakge, thus overriding it.
| [reply] [d/l] |
If I understand correctly, you want to have multiple modules together with the main script all in the same file. One way I can think of, without excessive rewrite, is by using a scalar reference to point to required package code at run-time, sort of a poor-man's dynamic link library.
#!/usr/bin/perl -w
my $pkg;
BEGIN {
if ( $^O =~ /dar/ ) { $pkg = \&mac::get_answer }
elsif ( $^O =~ /sol/ ) { $pkg = \&sun::get_answer }
elsif ( $^O =~ /aix/ ) { $pkg = \&aix::get_answer }
else { die "unknown os." }
};
print "answer is " . &$pkg() . "\n";
exit 0;
package mac;
sub get_answer { return "Apple" }
package sun;
sub get_answer { return "Sun" }
package aix;
sub get_answer { return "IBM" }
__END__
| [reply] [d/l] |
#!/usr/bin/perl -w
my $pkg;
BEGIN {
if ( $^O =~ /dar/ ) { $pkg = 'mac' }
elsif ( $^O =~ /sol/ ) { $pkg = 'sun' }
elsif ( $^O =~ /aix/ ) { $pkg = 'aix' }
else { die "unknown os." }
};
print "answer is " . $pkg->get_answer() . "\n";
exit 0;
package mac;
sub get_answer { return "Apple" }
package sun;
sub get_answer { return "Sun" }
package aix;
sub get_answer { return "IBM" }
__END__
Which makes it a lot easier to add new class methods in the future.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
:(){ :|:&};:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
Excellent! Thanks so much; this looks exactly like what I want to accomplish.
| [reply] |
#! perl -slw
use strict;
use warnings;
package xtest::mac;
sub get_answer{ 'Apple' }
package xtest::sun;
sub get_answer{ 'Sun' }
package xtest::aix;
sub get_answer{ 'IBM' }
package xtest::win;
sub get_answer{ 'Win' }
package xtest;
if( $^O =~ m[(dar|sol|aix|win)]i ) {
## Export to main for testing only.
*main::get_answer = \&{"xtest::\L$1\E::get_answer"};
}
else {
die 'Unknown OS';
}
1;
Then P:\test>perl -Mxtest -e"print get_answer()"
Win
If you have lots of vaient subs, then you can put the platform specific packages in separate modules, use the standard export mechanism and require them from the base package and then call test::$1::export(); to get the exports into your package.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!
| [reply] [d/l] [select] |