mirod has asked for the wisdom of the Perl Monks concerning the following question:

I have a module in which I want to use locale or use utf8 depending on a condition. Something like:

if( $locale) { use locale; } elsif( $utf8 and $perl_version_ok) { use utf8; } if( $word=~ /^\w+$/) { ... }

Obviously the way \w matches is impacted by the locale/utf8 setting.

My problem is that use locale/utf8 is scoped to the enclosing block, hence the use pragma will not be in scope outside of the if block and \w will just match [a-zA-Z]. How could I get it to match what I want?

In addition I would need to have the locale/utf8 active in most of the module, so it might be difficult to find an enclosing block. This means also that I can't put the statements affected by the pragma in the block. This is not possible:

if( $locale) { use locale; if( $word=~ /^\w+$/) { ... } } elsif( $utf8 and $perl_version_ok) { use utf8; if( $word=~ /^\w+$/) { ... } }

Replies are listed 'Best First'.
Re: use locale/utf8 scoping
by theorbtwo (Prior) on Aug 07, 2002 at 08:55 UTC

    Try doing a use locale (); and a use utf8 ();, then calling (locale|utf8)::(un?)import as needed. Since they both work by setting $^H, and $^H has magicly strange scope, you may have to play around a bit with exactly where you call them. I should suspect the correct answer is "as early as possible", but I'm not sure.

    Try reading utf8.pm and locale.pm, and perlvar for more on the scoping of $^H. On second look, you might have to put the calls to utf8/locale inside BEGIN, which would rather suck, because it would require you to do your option parsing there.


    Confession: It does an Immortal Body good.

Re: use locale/utf8 scoping
by jmcnamara (Monsignor) on Aug 07, 2002 at 09:20 UTC

    An interesting question. I guess the problem comes down to the fact that the pragmata are set at compile time but you wish to change then at run time.

    I don't think that this is possible. I tried to set $^H and to use pragma->unimport() at run-time but these approaches didn't (and probably shouldn't) work.

    If you can set some of the logical variables at compile time you could possibly do something like this (using strict instead of utf8 as an example):

    #!/usr/bin/perl -l my $foo; BEGIN {$foo = rand 2 > 1} BEGIN {require strict; strict->import('vars') if $foo} $not_scoped = 1; # Error if $foo is true BEGIN {strict->unimport('vars')} $not_scoped = 1; # Not an error print "Finished." __END__

    --
    John.

      The biggest problem is that use locale and use utf8 are scoped to the enclosing block, contrary to strict.

      I define an XML name to be my $REG_NAME= q{[^\W\d_][\w:.-]*}; and when I match a name, in different places in the module, I'd like the \W and \w to use the locale/utf8 pragma, depending on a variable set by the user.

      The solutions I can think of are: testing everywhere I match (a pain, and it means duplicating code) or create a method that would just do the match (but it would actually have to be several methods, one for each regexp in which I use $REG_NAME, plus it will probably impact the performaces, I have to assess this). It is easier when the match is done through a dynamically generated function, because I can include the use in the text of the function.

Re: use locale/utf8 scoping
by Zaxo (Archbishop) on Aug 07, 2002 at 16:48 UTC

    The if.pm module from 5.8 is available on CPAN, and my preliminary tests indicate it works in 5.6.1. Here is one way to get your logic in the outer scope:

    use if $locale, 'locale'; use if !$locale and $utf8 and $perl_version_ok, 'utf8';

    After Compline,
    Zaxo

Re: use locale/utf8 scoping
by mirod (Canon) on Aug 07, 2002 at 17:44 UTC

    None of the above methods seem to work. It looks like locale and utf8 do not behave like regular modules: you cannot play require/import/unimport (which is what if.pm does too) with them. Either they're use-d or not (in the current lexical scope).

    utf8 seems to have higher priority than locale BTW.