Ask a Question related to PERL Miscellaneous, Design and Development.
-
JS Bangs #1
Re: Changing module dynamically
Thomas M. Widmann sikyal:
I'm not sure how much control you have over the architecture of the whole> So, to sum up: I'd like a function, let's call it changelang, which
> will do the following:
>
> - Take one argument, the language to change to ($lang).
>
> - If it hasn't been loaded, load Bibulus::Lang::$lang (or whatever
> -- I don't care much about the name, so long as each language is
> defined in its own file).
>
> - Change the symbol table look-up path, so that Bibulus::Lang::$lang
> is searched first.
>
> - This should not affect the whole package, just the instance (as if
> there was something called @{$self->ISA}).
thing, but this is how I would implement such a system:
First, have all of your text methods be defined in the base class
Bibulus::Lang, but don't actually define any text there. Rather, define a
global hash %text that has key => value pairs for the text, and simply
import that hash from a module. Thus, your base class has this:
our %text = (); # whatever . . .
sub new {
# blah blah blah . . .
$self->{text} = \%text;
bless $self, $class;
}
# Text functions could easily be generalized w/ AUTOLOAD
sub edition {
return $self->{text}->{edition};
}
sub changelang {
my $lang = pop;
require "Bibulus::Lang::$lang";
$self->{text} = \%Bibulus::Lang::$lang::text;
}
All of the Bibulus::Lang::lang subclasses then have the responsibility of
populating %text with appropriate values. The package variable %text will
have the "standard" values for each lang, while $self->{text} will have
instance-specific values.
Jesse S. Bangs [email]jaspax@u.washington.edu[/email]
[url]http://students.washington.edu/jaspax/[/url]
[url]http://students.washington.edu/jaspax/blog[/url]
JS Bangs Guest
-
Dynamically changing chart labels
HI I'm after an how too really, point me in the right direction is possible. I have a new dashboard app, monitoring a server, last part is load... -
URL Atribute Dynamically Changing Query
:confused; This is a very real life program, but for simplicity terms, I'm going to use the ubiquitous Art Gallery example. I know a little... -
Changing Text Dynamically
Hello, I would like to know if the text displayed on a webpage changes dynamically.I have 2 drop down menus and based on the options chosen I... -
Changing UserControls Dynamically
I have 2 user controls and I would like to display 1 of them depending on a session variable. I have trie a place holder, but it doesnt seem to... -
changing default runlevel dynamically
How can I choose the runlevel dynamically at startup through lilo menus or otherwise? I want to make a custom runlevel for powersave and such. ... -
Tassilo v. Parseval #2
Re: Changing module dynamically
Also sprach Thomas M. Widmann:
I don't understand this paragraph. @ISA is indeed package-scoped, but> I have a slightly odd problem. I know I'm abusing OO programming a
> bit, but I cannot think of any better way.
>
> Simply stated, my problem is as follows: I'm writing a bibliography
> package with multilingual features, so all texts are encapsulated in
> functions.
>
> E.g., $bib->edition(5) might return 'fifth edition' or '5th ed.' if
> the language is English, and 'femte udgave' og '5. udg' if it's
> Danish.
>
> Now, if one only ever needed one language in each bibliography, one
> could simply have put something like
> use Bibulus::Lang::da;
> in the beginning of the script using the bibliography package, and
> Bibulus::Lang::da would then have defined the relevant language
> functions to return Danish texts and it would have inherited the rest
> from the parent.
>
> However, the language can change for each entry. I could of course
> write functions like the following:
> sub edition {
> my $self = shift;
> my $ed = shift;
> if ($self->LANG eq 'da') {
> return "$ed. udgave";
> } elsif ($self->LANG eq 'en') {
> ...
> -- but this would quickly become unwieldy, and it would make it
> difficult for users to define their own languages easily.
>
> If only @ISA had not been package-scoped, one could have done
> something along the following lines:
> sub changelang {
> my $self = shift;
> my $lang = shift;
> @ISA = ("Bibulus::Lang::$lang");
> }
> -- but it is, so one cannot. :-( (Well, if I have to, I can go down
> this route -- since one would only write one entry at a time, one can
> of course just always switch to correct language at the beginning of
> each entry.)
why does that prevent you from changing it?
No, it does not. Just extract the package from $AUTOLOAD and> Instead, I've been playing around with autoloading:
> sub AUTOLOAD {
> my $self = shift;
> my $f = $AUTOLOAD;
> $f =~ s/(.*::)/$1$self->{LANG}\:\:/;
> &$f(@_);
> }
> but it most certainly isn't pretty, and it seems to break down if one
> tries to use inheritance. It also seems to be necessary to require
> all the language modules initially, which again makes it difficult for
> users to define their own languages.
eval-require it:
sub AUTOLOAD {
my ($pkg, $meth) = $AUTOLOAD =~ /(.*)::(.*)/;
eval "require $pkg";
goto &$AUTOLOAD;
}
Ah, now I see what you meant. You want an @ISA per object. That arguably> So, to sum up: I'd like a function, let's call it changelang, which
> will do the following:
>
> - Take one argument, the language to change to ($lang).
>
> - If it hasn't been loaded, load Bibulus::Lang::$lang (or whatever
> -- I don't care much about the name, so long as each language is
> defined in its own file).
>
> - Change the symbol table look-up path, so that Bibulus::Lang::$lang
> is searched first.
>
> - This should not affect the whole package, just the instance (as if
> there was something called @{$self->ISA}).
does not exist.
I'd go for an AUTOLOAD approach thusly:
Make a convention that you sufffix the edition() method with the
language. Extract this suffix, pull in the appropriate module and call
the edition() method from this namespace:
sub AUTOLOAD {
my ($meth, $lang) = $AUTOLOAD =~ /(edition)_(.*)/
or return;
eval "require Bibulus::Lang::$lang";
# for $self->edition_da(@args) this will translate to
# $self->Bibulus::Lang::da::edition(@args)
goto &{"Bibulus::Lang::${lang}::edition"};
}
Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
Tassilo v. Parseval Guest
-
Steve Grazzini #3
Re: Changing module dynamically
Thomas M. Widmann <thomas@widmann.uklinux.net> wrote:
[snip]> I have a slightly odd problem. I know I'm abusing OO programming a
> bit, but I cannot think of any better way.
What you're describing (a class for every object) is possible --> So, to sum up: I'd like a function, let's call it changelang, which
> will do the following:
>
> - Take one argument, the language to change to ($lang).
>
> - If it hasn't been loaded, load Bibulus::Lang::$lang (or whatever
> -- I don't care much about the name, so long as each language is
> defined in its own file).
>
> - Change the symbol table look-up path, so that Bibulus::Lang::$lang
> is searched first.
>
> - This should not affect the whole package, just the instance (as if
> there was something called @{$self->ISA}).
sub changelang {
my ($self, $lang) = @_;
my $pack = "Bibulus::Lang::$lang";
my $addr = sprintf '0x%x', $self;
eval qq{
require ${pack};
package ${pack}_${addr};
sub DESTROY { undef %${pack}_${addr}:: }
}.q{
our @ISA = ($pack, ref $self);
bless $self;
}
}
But delegating/dispatching the language methods by hand would be
cleaner:
sub changelang {
my ($this, $lang) = @_;
my $package = "Bibulus::Lang::$lang";
eval "require $package" or die $@;
$this->{lang} = $package;
}
sub edition {
my $this = shift;
($this->{lang} || $default)->edition(@_);
}
And as you might have suggested in the big snip, any number of
those language-aware proxy methods could be generated on the fly
by AUTOLOAD().
--
Steve
Steve Grazzini Guest
-
Thomas M. Widmann #4
Re: Changing module dynamically
"Tassilo v. Parseval" <tassilo.parseval@rwth-aachen.de> writes:
Ah, I hadn't thought of that -- thanks a lot!> Also sprach Thomas M. Widmann:
>
> [...]>> > Instead, I've been playing around with autoloading:
> > sub AUTOLOAD {
> > my $self = shift;
> > my $f = $AUTOLOAD;
> > $f =~ s/(.*::)/$1$self->{LANG}\:\:/;
> > &$f(@_);
> > }
> > but it most certainly isn't pretty, and it seems to break down if one
> > tries to use inheritance. It also seems to be necessary to require
> > all the language modules initially, which again makes it difficult for
> > users to define their own languages.
> No, it does not. Just extract the package from $AUTOLOAD and
> eval-require it:
>
> sub AUTOLOAD {
> my ($pkg, $meth) = $AUTOLOAD =~ /(.*)::(.*)/;
> eval "require $pkg";
> goto &$AUTOLOAD;
> }
>
No, that wouldn't work, since the edition function will be called in a> [...]
> I'd go for an AUTOLOAD approach thusly:
>
> Make a convention that you sufffix the edition() method with the
> language. Extract this suffix, pull in the appropriate module and call
> the edition() method from this namespace:
>
> sub AUTOLOAD {
> my ($meth, $lang) = $AUTOLOAD =~ /(edition)_(.*)/
> or return;
> eval "require Bibulus::Lang::$lang";
>
> # for $self->edition_da(@args) this will translate to
> # $self->Bibulus::Lang::da::edition(@args)
> goto &{"Bibulus::Lang::${lang}::edition"};
> }
place where the language is not known in advance.
However, with help from your eval-require, I've come up with some code
that seems to work. At least, the following program:
use A;
my $l1 = new A;
$l1->lang('da');
print $l1->test, "\n";
$l1->lang('en');
print $l1->test, "\n";
my $l2 = new A;
$l2->lang('da');
print $l2->test, "\n";
print $l1->test, "\n";
will produce the required output:
da
en
da
en
given the following three files A.pm, da.pm and en.pm:
##### file A.pm #####
package A;
sub new {
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
sub lang {
my $self = shift;
my $lang = shift;
$self->{LANG} = $lang;
}
sub AUTOLOAD {
my $self = shift;
my ($pkg, $meth) = $AUTOLOAD =~ /(.*)::(.*)/;
eval "require '$self->{LANG}.pm'";
$meth = "$self->{LANG}::$meth";
goto &$meth;
}
1;
##### file da.pm #####
package da;
sub test {
return 'da';
}
1;
##### file en.pm #####
package en;
sub test {
return 'en';
}
1;
Thanks a lot for your help!
/Thomas
--
Thomas Widmann Bye-bye to BibTeX: join the Bibulus project now!
[email]thomas@widmann.uklinux.net[/email] <http://www.nongnu.org/bibulus/>
Glasgow, Scotland, EU <http://savannah.nongnu.org/projects/bibulus/>
Thomas M. Widmann Guest
-
Thomas M. Widmann #5
Re: Changing module dynamically
JS Bangs <jaspax@u.washington.edu> writes:
I considered something like that originally, but I gave it up when I> Thomas M. Widmann sikyal:
>>> > So, to sum up: I'd like a function, let's call it changelang,
> > which will do the following:
> >
> > - Take one argument, the language to change to ($lang).
> >
> > - If it hasn't been loaded, load Bibulus::Lang::$lang (or
> > whatever -- I don't care much about the name, so long as each
> > language is defined in its own file).
> >
> > - Change the symbol table look-up path, so that
> > Bibulus::Lang::$lang is searched first.
> >
> > - This should not affect the whole package, just the instance
> > (as if there was something called @{$self->ISA}).
> I'm not sure how much control you have over the architecture of the
> whole thing, but this is how I would implement such a system:
>
> First, have all of your text methods be defined in the base class
> Bibulus::Lang, but don't actually define any text there. Rather,
> define a global hash %text that has key => value pairs for the text,
> and simply import that hash from a module. Thus, your base class has
> this:
>
> [...]
>
> All of the Bibulus::Lang::lang subclasses then have the
> responsibility of populating %text with appropriate values. The
> package variable %text will have the "standard" values for each
> lang, while $self->{text} will have instance-specific values.
realised that the order of elements can be language-dependent. (E.g.,
"5th" and "edition" might come out in the opposite order in some
languages.)
One could of course populate the hash with closures, but I fear it
would get totally out of hand.
But thanks anyway for the proposal!
/Thomas
--
Thomas Widmann, MA member of the steering group for europa.*
Mavisbank Gardens, Glasgow, Scotland, EU
[email]thomas@widmann.uklinux.net[/email] [url]http://www.widmann.uklinux.net[/url]
Thomas M. Widmann Guest



Reply With Quote

