在Web :: Scraper的语法中{}的含义是什么?

时间:2011-03-04 02:09:40

标签: perl

我对Perl语法感到困惑。这是关于Web::Scraper的示例。

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

输出:

Web::Scraper

我无法理解花括号的含义。如果scraper是一个函数,那么为什么要使用{}代替()

2 个答案:

答案 0 :(得分:7)

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的一些内置函数和其他常见函数的语法,例如mapgrep

@square_roots = map { sqrt($_) } 1 .. 100;

答案 1 :(得分:7)

scraper是使用(&)原型定义的子程序:

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

此原型告诉perl以与内置scrapermap {...} @list结构类似的方式解析用户子例程grep {...} @list。括号{...}括号中的代码作为代码引用传递给函数,与编写sub {...}时的代码相同。要编写类似mapgrep的子例程,您可以使用(&@)原型,它告诉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;

您可以在perlsub了解有关Perl子例程选项的更多信息。

最后,关于原型的必要警告。原型经常被新手Perl程序员滥用作为参数验证的一种形式,类似于其他一些语言中的函数签名。由于原型可以指定的上下文(标量与列表)的强加,这种用法很容易出错。参数检查最好在子程序内完成,同时解压缩@_(如果需要的话)。原型的使用应该保留给scraper这样的情况,其目的是创建一个以与perl的内置函数类似的方式解析的子例程。