http://www.perlmonks.org?node_id=1212680

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

Hello everyone, I hope your are doing fine. I have this little problem, you can see the case here:

https://stackoverflow.com/questions/49770665/perl-call-subroutine-of-main-namespace-from-package

This work in console perl, but when I run with plackup I get error. Undefined subroutine &main::test

My program.pl
BEGIN { sub test{ return "from test"; } } use Mypackage; sub { return [ 200, [ "Content-Type" => "text/html" ], [ test() ] ]; };
Mypackage.pm
package Mypackage; ::test();
How can access to main space in plack psgi to run the function, like I do with console perl ? Thanks so much

Replies are listed 'Best First'.
Re: Call subroutine of main namespace from package in Plack
by choroba (Cardinal) on Apr 11, 2018 at 13:56 UTC
    Why do you need it? Calling functions from the main:: namespace in modules is a code smell. And now we also see why. How do you run the script under plackup?

    Also, please, linkify the crosspost link by at least wrapping it into square brackets.

    Update: I tried to just run

    plackup program.pl
    (and I added
    1;
    to the end of Mypackage.pm.

    To debug, you can add

    warn __PACKAGE__;
    inside the BEGIN block before defining the test subroutine. You'll see that plack doesn't call your program in the main namespace.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Hi choroba, I have a main script app.psgi, inside I have several modules, modules in my local folder like module1.pm, module2.pm, etc

      This modules have own functions.

      In the app.psgi I have anothers functions relation to router engine urls, to dispach content according to url.

      My target is set a value or get a value from main script (app.psgi) and pass that value to all modules, and retrieve the value from module via the function set in main script.

      * To do this I can pass a function value to another function.
      * I can create a our variable
      * I can used db to retrieve data

      But I want to avoid the above list, that's why the title of this thread.

        I don't understand. A module doesn't know who calls it, it can't make any assumptions about its caller's namespace and capabilities. The contract is defined by arguments and the returned value. If you need a function called in the main program and in the modules, move it into a new module and properly use it everywhere.

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Call subroutine of main namespace from package in Plack
by thanos1983 (Parson) on Apr 11, 2018 at 14:04 UTC

    Hello Thenothing,

    I am not familiar with PSGI/Plack but I read your question Perl - Call subroutine of main namespace from package and I think you are looking for something like that:

    main.pl

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Mypackage; sub callingTest { my $object = new Mypackage(); return [ 200, [ "Content-Type" => "text/html" ], [ $object->test() + ] ]; }; print Dumper callingTest(); __END__ $ perl main.pl $VAR1 = [ 200, [ 'Content-Type', 'text/html' ], [ 'from test' ] ];

    Mypackage.pm

    package Mypackage; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } sub test { return "from test"; } 1;

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      Hello thanos, I want to do the contrary. Get value from main script and retrieve in module. Thanks.

        That's rather backwards. Instead, create a function in the module, and from main, call that function with the required parameters.

        Hello again Thenothing,

        When you say contrary you mean this?

        main.pl

        #!/usr/bin/perl use strict; use warnings; use Mypackage; my $object = new Mypackage(); $object->setValue(100); print $object->getValue() . "\n"; # retrievable from any script __END__ $ perl main.pl 100

        Mypackage.pm

        package Mypackage; use strict; use warnings; sub new { my $class = shift; my $self = { _value => shift, }; bless $self, $class; return $self; } sub getValue { my( $self ) = @_; return $self->{_value}; } sub setValue { my ( $self, $value ) = @_; $self->{_value} = $value if defined($value); # return $self->{_value}; } 1;

        If not, show an example with words to understand what you mean.

        Update: Maybe this? Initialize the class with a value and then update it?

        #!/usr/bin/perl use strict; use warnings; use Mypackage; my $object = new Mypackage(100); print $object->getValue() . "\n"; $object->setValue(200); print $object->getValue() . "\n"; __END__ $ perl main.pl 100 200

        Hope this helps, BR.

        Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Call subroutine of main namespace from package in Plack
by poj (Abbot) on Apr 11, 2018 at 15:14 UTC

    Seems very odd but try

    BEGIN { package main; sub test{ return scalar localtime; } } use Mypackage; sub { print "OK"; return [200, ["Content-Type"=>"text/html" ],[Mypackage::test2()]]; };
    package Mypackage; sub test2 { ::test(); } 1;
    poj
      Hi there, poj. Thanks for your code, that work, maybe this approach I tried to implement is bad design ? Thanks to everyone.

        Perl is an incredibly flexible language that gives the power to execute bad designs. Yours is quite bad, especially in a PSGI pipeline where responsibilities are well designed and compartmentalized; and I encourage you to abandon it immediately.

        You should not feel bad, though. It's one of the early "intuitive" things a lot of us, especially self-taught programmers, try to do. The other that is almost a rite of passage is using variables as variable names. Working with raw PSGI is quite ambitious. It's not designed to be for direct webwork but for package authors to use as a platform for their higher level kits which are then in turn used for webwork.

        If you break down your project into small bites and present them as questions here, you'll probably get terrific advice and code snippets directly on point. Right now you're mostly getting expert advice on how to do things no one but experts even knows how to do because, like wheelies in traffic, it RFC:SHOULDN'T be done. :P

        Update: fixed a grammar booger that was bothering me.

        Interestingly (for some definition of "interesting"), this also works and seems exactly equivalent (update: and reduces worries about phasing of BEGIN blocks, use statements and sub definitions, etc.):

        c:\@Work\Perl\monks\Thenothing>perl -le "use warnings; use strict; ;; use Mypackage; ;; print Mypackage::test2(); ;; print test(); " hiya @ Wed Apr 11 12:35:25 2018 hiya @ Wed Apr 11 12:35:25 2018
        File Mypackage.pm:
        package Mypackage; use warnings; use strict; sub main::test { return 'hiya @ ' . localtime; } sub test2 { ::test(); } 1;
        Oh, and by the way: Don't Do This! Others have suggested much better ways of organizing your code.


        Give a man a fish:  <%-{-{-{-<

Re: Call subroutine of main namespace from package in Plack
by AnomalousMonk (Archbishop) on Apr 11, 2018 at 16:52 UTC