Mojolicious: невозможно вызвать рендеринг метода для неопределенного значения

Я получаю эту ошибку и не могу понять, почему это происходит. Это происходит, когда я перехожу к другой подпрограмме. Возможно, мне нужно кое-что понять о Mojolicious, почему это происходит.

Вот исходный код моей программы:

#!/usr/bin/perl

use Mojolicious::Lite;

get '/' => sub { &start_home; };

app->start;

sub start_home {
  my $d = shift;
  my $something = $d->param('something');
  ### Do things with $something.... etc.. etc..
  &go_somewhere_else; ### Go somewhere else
}

sub go_somewhere_else {
 my $c = shift;
 $c->render(text => "Hello World!");
 ### End of program
}

Я передаю значение средству визуализации, и есть значение. Почему он говорит, что оно не определено? Насколько я понимаю, это происходит только в том случае, если вы переходите к подпрограмме и пытаетесь отобразить вывод.

Моя операционная система — Windows, и я использую Strawberry Perl.


person gpwr    schedule 23.09.2016    source источник


Ответы (1)


Вам нужно передать объект контекста $c/$d вашей второй функции. неопределенное значение — это ваше $c в go_somewhere_else, потому что вы вызываете его без параметра.

Первоначально, чтобы заставить его работать, сделайте это.

sub start_home {
  my $d = shift;
  my $something = $d->param('something');

  go_somewhere_else($d);
}

Теперь вы передаете контекст, который вы назвали $d (это не общепринятое имя), другой функции, и предупреждение исчезнет.

Это потому, что форма &subname; без скобок () делает @_ (это список аргументов функции) доступным внутри go_somewhere_else, но поскольку вы shiftотключили $d, @_ теперь пусто, и, следовательно, ваше $c внутри go_somewhere_else равно undef.

В качестве альтернативы вы также можете изменить shift на назначение с @_. Но, пожалуйста, не делайте этого!

sub start_home {
  my ( $d ) = @_;
  my $something = $d->param('something');

  &go_somewhere_else;
}

Здесь есть и другие странные вещи, почти неправильные.

get '/' => sub { &start_home; };

Вы каррируете функцию start_home, но фактически не добавляете еще один параметр. Я объяснил выше, почему это работает. Но это не здорово. На самом деле все запутанно и сложно.

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

get '/' => \&start_home;

Внутри start_home вы должны называть свой контекст $c в соответствии с соглашением. Вы также не должны использовать нотацию амперсанда & для вызова функций. Это изменяет поведение так, как вы, безусловно, не хотите.

sub start_home {
  my $c = shift;
  my $something = $c->param('something');

  # ...
  go_somewhere_else($c);
}

Чтобы узнать больше о том, как работают вызовы функций в Perl, обратитесь к perlsub.

person simbabque    schedule 23.09.2016
comment
@Eugen ваше редактирование было неверным. Вся идея этого первого блока кода заключается в том, что @_ в функции пусто, поэтому нет никакой необходимости передавать его дальше. Я объясняю это в абзаце ниже. Я откатил вашу правку. - person simbabque; 25.09.2016
comment
В этом случае первый и второй примеры работают по-разному. Если start_home получит два или более аргумента, первый пример отбросит их все, а второй пропустит их. Проход через @_ в первом примере явно показывает, что разница между примерами только в первом аргументе. - person Eugen Konkov; 25.09.2016