Вызов подпрограмм в Perl Plack ничего не возвращает - PullRequest
0 голосов
/ 29 апреля 2018

Я новичок в Perl Plack / PSGI. Я хочу получить доступ к подпрограмме в цикле perl plack / psgi, но похоже, что подпрограмма не выполняется. Каждая родительская переменная, такая как $ number, должна передаваться автоматически, как при написании обычного сценария Perl Я что-то здесь скучаю, это возможно?

..
my $app = sub {

  my $number = 10;

  &count_number;
  sub count_number {
    $number +=10;
  }


  return ['200',[  'Content-Type' => 'application/json' ],
  [ "{\"number\":$number} ]];     

}
.. 

10 возвращается вместо 20: (

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Оператор my имеет два эффекта:

  • во время компиляции вводит скалярную переменную.
  • во время выполнения создает новый скалярный объект для этой переменной.

По сути, эти два скаляра являются разными переменными, хотя они имеют одинаковые имена.

Оператор sub name { ... } имеет только эффект времени компиляции. Он назначает подпрограмму во время компиляции для данного имени. Поэтому, когда подпрограмма компилируется, она видит исходную переменную времени компиляции, а не переменную времени выполнения, которая создается намного позже.

Следовательно, вы не должны вкладывать именованные подпрограммы. На самом деле, если вы use warnings получите предупреждение об этом: «Переменная« $ number »не останется общей».

У вас есть два варианта:

  • Вы можете использовать замыкание, которое видит переменную времени выполнения. При этом используются анонимные подпрограммы:

    ...
    my $number = 10;
    my $count_number = sub {
      $number += 10;
    };
    
    $count_number->();
    
    ...
    
  • Или вы передаете значения как явные параметры отдельной подпрограмме. Да, это немного усложняет ситуацию, но также разделяет отдельные вещи. Чистый поток данных является признаком хорошего дизайна.

0 голосов
/ 29 апреля 2018

Если я исправлю кавычки в строке в выражении return (у вас нет закрывающей двойной кавычки), я получу предупреждение

Переменная «$ number» недоступна в строке 7. source_file.pl.

Причина в том, что лексические значения $app и $number определяются во время выполнения, тогда как подпрограмма count_number определяется намного раньше во время компиляции

Решение состоит в том, чтобы отложить определение count_number на время выполнения, сделав вместо этого анонимную подпрограмму. Вызов $count_number->() также необходимо перевести на после определения

my $app = sub {

    my $number = 10;

    my $count_number = sub {
        $number +=10;
    };

    $count_number->();

    return [
        '200',
        [ 'Content-Type' => 'application/json' ],
        [ "{\"number\":$number}" ]
    ];     
};


use Data::Dumper;
print Dumper $app->();
* * Выход тысяча двадцать-один * * одна тысяча двадцать-дв
$VAR1 = [
            '200',
            [
                'Content-Type',
                'application/json'
            ],
            [
                '{"number":20}'
            ]
        ];

Есть соответствующее предупреждение

Переменная «$ number» не будет оставаться общей

с аналогичным решением. Вы можете прочитать об обоих в perldoc perldiag. Сообщения перечислены и описаны в алфавитном порядке

...