Что означает {} в грамматике Web :: Scraper? - PullRequest
6 голосов
/ 04 марта 2011

Я запутался в грамматике Perl. Это пример Web :: Scraper .

my $t = scraper {
    process "li", "list[]" => "TEXT";
};
print ref($tweets), "\n";

Выход:

Web::Scraper

Я не могу понять значение фигурных скобок. Если scraper является функцией, то зачем использовать {} вместо ()?

Ответы [ 2 ]

7 голосов
/ 04 марта 2011

scraper - это подпрограмма, определенная с помощью прототипа (&):

sub scraper (&) {
    my $code_ref = shift;
    ...
    $code_ref->($some_value)
    ...
}

Этот прототип сообщает Perl, чтобы он анализировал подпрограмму пользователя scraper аналогично встроенным map {...} @list и grep {...} @list конструкций.Код, заключенный в скобки {...}, передается в функцию в качестве ссылки на код и такой же, как если бы вы написали sub {...}.Чтобы написать подпрограмму, подобную map или grep, вы должны использовать прототип (&@), который сообщает Perl ожидать блок кода, а затем список.

В этом случае (&)Прототип утверждает, что функция принимает ровно один аргумент с высоким приоритетом, и что аргумент должен быть пустым блоком (интерпретируемым как coderef), литеральным объявлением sub {...} или выражением, которому предшествует пара ссылка / разыменование \&{some_expression},Если выражение является простым скаляром, вы можете написать \&$code_ref

Хотя синтаксис, который вы нашли scraper {...}, является самым коротким, вы также можете назвать его как scraper sub {...}.

Еслизначение, которое нужно передать scraper, содержится в переменной, вы можете написать:

scraper \&$code_ref; # where the \& portion asserts that the value is a coderef

Тот же самый синтаксис используется с именованными подпрограммами:

sub some_sub {...}

scraper \&some_sub;

Вы можете узнать большео параметрах подпрограммы Perl в perlsub .

Наконец, необходимое предупреждение о прототипах.Прототипы часто неправильно используются начинающими программистами Perl как форма проверки аргументов, аналогичная сигнатурам функций в некоторых других языках.Такое использование подвержено ошибкам из-за наложения контекста (скаляр против списка), который могут указывать прототипы.Проверка аргументов лучше всего выполнять внутри подпрограммы при распаковке @_, если она вообще нужна.Использование прототипов должно быть зарезервировано для случаев, таких как scraper, где целью является создание подпрограммы, которая анализируется аналогично одной из встроенных функций perl.

7 голосов
/ 04 марта 2011

Web::Scraper::scraper - это функция, которая принимает в качестве аргумента другую функцию (или ссылку на функцию).В этом контексте { ... } объявляет анонимную подпрограмму, которая передается в качестве аргумента функции (в других контекстах { ... } может объявить ссылку на хеш).Предположительно, функция вызовет выполнение кода, который вы в какой-то момент выполняете (как предлагается в документации, когда вызывается функция scrape).

Существуют альтернативные способы вызова такой функции, что вывозможно, видели раньше:

# reference to a named function
sub my_scraper_function { process "li", "list[]" => "TEXT" };
scraper \&my_scraper_function;

# reference to an anonymous function
my $scraper_function = sub { process "li", "list[]" => "TEXT" }; 
scraper $scraper_function;

# using a function name
# sometimes this doesn't work under 'use strict subs'
sub my_scraper_function { process "li", "list[]" => "TEXT" };
scraper 'ThisPackage::my_scraper_function';

Вы также увидите этот синтаксис некоторых встроенных в Perl и других распространенных функций, таких какmap и grep:

@square_roots = map { sqrt($_) } 1 .. 100;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...