Re: PlPerl scope issue

Поиск
Список
Период
Сортировка
От Tim Bunce
Тема Re: PlPerl scope issue
Дата
Msg-id 20091215153247.GQ27445@timac.local
обсуждение исходный текст
Ответ на PlPerl scope issue  ("Peter" <peter@greatnowhere.com>)
Ответы Re: PlPerl scope issue  ("Peter" <peter@greatnowhere.com>)
Список pgsql-general
On Tue, Dec 15, 2009 at 08:35:21AM -0600, Peter wrote:
>    After upgrade to 8.4.1 Perl "my" variables are no longer being seen by subroutines:
>
>     CREATE OR REPLACE FUNCTION global.perl_test()
>      RETURNS "varchar" AS
>    $BODY$
>    my $test="x";
>    test();
>    return $test;
>    sub test {
>     elog(NOTICE,"X=".$test);
>    }
>    $BODY$
>    language 'plperlu';
>
>    Now, "select global.perl_test()" returns "x" but the value is missing from notice statement. This worked
>    just fine in 8.3, and Perl scoping rules say `my' variables are visible by subroutines within the same
>    code block. I'm running Ubuntu Karmic, installed from stock PG repositories. Whats going on here?

The docs at http://www.postgresql.org/docs/8.4/static/plperl-funcs.html
say

    Note: The use of named nested subroutines is dangerous in Perl,
    especially if they refer to lexical variables in the enclosing scope.
    Because a PL/Perl function is wrapped in a subroutine, any named
    subroutine you create will be nested. In general, it is far safer to
    create anonymous subroutines which you call via a coderef. See the
    perldiag man page for more details.

I believe the section of perldiag it's refering to is this one:

    =item Variable "%s" will not stay shared

    (W closure) An inner (nested) I<named> subroutine is referencing a
    lexical variable defined in an outer named subroutine.

    When the inner subroutine is called, it will see the value of
    the outer subroutine's variable as it was before and during the *first*
    call to the outer subroutine; in this case, after the first call to the
    outer subroutine is complete, the inner and outer subroutines will no
    longer share a common value for the variable.  In other words, the
    variable will no longer be shared.

    This problem can usually be solved by making the inner subroutine
    anonymous, using the C<sub {}> syntax.  When inner anonymous subs that
    reference variables in outer subroutines are created, they
    are automatically rebound to the current values of such variables.

In other words:

     my $test="x";

     my $test_sub = sub {
       elog(NOTICE,"X=".$test);
     };

     $test_sub->();
     return $test;

Tim.

В списке pgsql-general по дате отправления:

Предыдущее
От: "Peter"
Дата:
Сообщение: PlPerl scope issue
Следующее
От: Greg Smith
Дата:
Сообщение: Re: Interesting Benchmark Article