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

Hello folks,

I need to set this locale only if I am on the web, not in my Win32 development workstation - otherwise my script will stop complaining that it didn´t find these modules and locale definitions. But calling these modules and pragmas inside this block seems not to affect the outer code.

if ( $online == 1 ) { # This variable is defined before, according to +the $^0 use POSIX 'locale_h'; setlocale( LC_ALL, "pt_BR.iso88591" ); } :
Any ideas? Eval like this:?
eval { use POSIX 'locale_h'; setlocale( LC_ALL, "pt_BR.iso88591" ); }
Thanks a lot

Andre_br

Replies are listed 'Best First'.
Re: use depending on environment
by rinceWind (Monsignor) on Jun 22, 2005 at 15:34 UTC

    In order to make your use conditional, you need to wrap it, and the if condition, in a BEGIN block. This will then get run at compile time (use time).

    BEGIN { if ( $online == 1 ) { # This variable is defined before, according + to the $^0 use POSIX 'locale_h'; setlocale( LC_ALL, "pt_BR.iso88591" ); } }

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: use depending on environment
by Xaositect (Friar) on Jun 22, 2005 at 15:57 UTC

    Using a begin block is preferrable if you can get away with it, but if you can't know whether or not you want to load a module at compile-time, try using 'require' instead of 'use'. 'require' will load the module at run-time. ( 'use' is equivilant to BEGIN { require MODULE; } )

    In general, 'use' is preferable because it gives the compiler more information about the symbols in your namespace. For example, where you might have done

    use Data::Dumper; print Dumper $foo;
    You can't just substitute require because then the compiler won't know where the "Dumper" function comes from. Instead you have to do something like
    require Data::Dumper; print Data::Dumper::Dumper($foo);


    Xaositect - Whitepages.com
Re: use depending on environment
by tlm (Prior) on Jun 22, 2005 at 16:03 UTC

    How about:

    if ( $online == 1 ) { require POSIX; POSIX->import( 'locale_h' ); # blah blah }
    ?

    the lowliest monk

      This is the "correct" way to do this as use is a compile-time directive (is that the right term?). Perl will see the use inside the BEGIN { } or the eval { } and go search for that module.

      Addmittedly, it is seems odd that

      BEGIN { if ($condition) { use Foo; } }
      does not do what you expect; but it makes more sense if you think of what it really does. Convert the above code into
      BEGIN { if ($condition) { BEGIN { require Foo; Foo::import(); } } }

      Then remember that if you have this:

      print Bar::new(); print Bar::old(); package Bar; sub new { sub old { return "I'm old"; } return "I'm new"; } 1;
      you have created a real subroutine called "old" in package Bar that can be called. The same is true with the use inside the BEGIN { }; you created a real BEGIN { } block that will be executed at compile time in the order in which it was encountered. You will actually execute that code regardless of the if { } block that surrounds it.

      Ivan Heffner
      Sr. Software Engineer, DAS Lead
      WhitePages.com, Inc.

        Just a couple of things. According to the docs for use:

        [use] is exactly equivalent to
        BEGIN { require Module; import Module LIST; }
        except that Module must be a bareword.
        In other words, at least according to the docs, if one wants to replicate at runtime what use does, it should be Foo->import, not Foo::import.

        The second point is only a clarification of a potentially misleading detail. The routine Bar::old in your example can be called even if Bar::new has not been called first. In other words, it is not the case that executing Bar::new somehow defines Bar::old. (I'm not saying that you wrote or believe this, but someone reading your post may incorrectly draw this conclusion.)

        the lowliest monk

        WOW! GOT IT!

        Sorry, but we in fact have written lots of VALID code. The REAL problem was that I was relying on a sub called from other script to do the lc work. And, I didn´t know, it didn´t get the locale set at the main script!

        But now it´s great. Sorry to make you guys hit heads too! But at least now we have a huge record of "use depending on envirnoment"!

        Cheers

        This one also doesn´t work... I am beggining to think about suicide!
        BEGIN { ## ## use locale; ## ## eval "use POSIX ('locale_h')"; ## eval "setlocale( LC_ALL, 'pt_BR.iso88591' )"; ## ## } ##
        PS: no errors generated, just the incorrect default locale that remains set.
        Sorry guys, this is getting a little bit confusing for me, I am not very familiar with this routines. I´m testing the code below without successs:
        BEGIN { ## ## use locale; ## ## unless ( $ENV{REMOTE_ADDR} eq "127.0.0.1" ) { ## ## use POSIX ('locale_h'); ## setlocale( LC_ALL, "pt_BR.iso88591" ); ## ## } ## ## }
Re: use depending on environment
by VSarkiss (Monsignor) on Jun 22, 2005 at 15:38 UTC
      Does that really work? Since use is compile time, this will error out even if the condition isn't met:
      #!/usr/bin/perl -w use strict; BEGIN { if (0) { use Non_existant_module; } }
      Thanks for the replies. But are you sure this locale deffinition will be valid for the entire script? The BEGIN block provides that?