Amazon Best VPN GoSearch

OnWorks 网站图标

perlref - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管提供商中运行 perlref

这是命令 perlref,可以使用我们的多个免费在线工作站之一(例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器)在 OnWorks 免费托管提供商中运行

程序:

您的姓名


perlref - Perl 引用和嵌套数据结构

注意


这是有关参考文献各个方面的完整文档。 对于更短的教程
仅介绍基本功能,请参阅 perlreftut。

商品描述


在 Perl 版本 5 之前,很难表示复杂的数据结构,因为
所有引用都必须是符号性的——即使如此,引用变量也很困难
而不是符号表条目。 Perl 现在不仅使使用符号变得更容易
对变量的引用,还可以让您对任何数据或数据块进行“硬”引用
代码。 任何标量都可以持有硬引用。 因为数组和哈希包含标量,
您现在可以轻松构建数组的数组、散列数组、数组散列、数组数组
函数的哈希值等等。

硬引用很聪明——它们自动为您跟踪引用计数
当引用计数变为零时释放所引用的事物。 (参考计数
对于自引用或循环数据结构中的值,如果没有
帮助不大; 有关详细说明,请参阅“循环引用”。)如果发生这种情况
要成为一个对象,该对象就被破坏了。 有关对象的更多信息,请参阅 perlobj。 (在一个
从某种意义上说,Perl 中的一切都是对象,但我们通常保留这个词来引用
已被正式“祝福”到类包中的对象。)

符号引用是变量或其他对象的名称,就像符号链接一样
Unix 文件系统仅包含文件名。 *glob 表示法是一种
象征性参考。 (符号引用有时称为“软引用”,但是
请不要这样称呼他们; 没有无用的同义词,引用已经够混乱的了。)

相比之下,硬引用更像是 Unix 文件系统中的硬链接:它们用于
访问底层对象而不关心它的(其他)名称是什么。 当。。。的时候
“参考”一词不带形容词使用,如下段所示,它是
通常谈论硬引用。

在 Perl 中引用很容易使用。 只有一个最重要的原则:一般来说,
Perl 不进行隐式引用或取消引用。 当标量持有引用时,
它始终表现为一个简单的标量。 它不会神奇地开始成为数组或散列
或子程序; 您必须通过取消引用来明确告诉它这样做。

也就是说,请注意 Perl 版本 5.14 引入了该规则的例外,例如
语法方便。 实验性数组和哈希容器函数行为允许
Perl 处理数组和散列引用,就好像它们已被显式处理一样
语法上取消引用。 请参阅 perl5140delta 和 perlfunc 中的“语法增强”
了解详情。

制作 案例
可以通过多种方式创建参考。

1. 在变量、子例程或值上使用反斜杠运算符。 (这很有效
就像 C 中的 &(地址)运算符。)这通常会创建 另一个 参考一个
变量,因为符号表中已经存在对该变量的引用。
但是符号表引用可能会消失,并且您仍然会拥有该引用
反斜杠又回来了。 这里有些例子:

$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&处理程序;
$globref = \*foo;

不可能创建对 IO 句柄(文件句柄或目录句柄)的真实引用
使用反斜杠运算符。 您最多可以获得的是对 typeglob 的引用,
这实际上是一个完整的符号表条目。 但请看解释
*foo{THING} 语法如下。 但是,您仍然可以使用类型 glob 和 globrefs 作为
虽然它们是 IO 句柄。

2. 可以使用方括号创建对匿名数组的引用:

$arrayref = [1, 2, ['a', 'b', 'c']];

在这里,我们创建了对一个包含三个元素的匿名数组的引用,其最终元素
element 本身是对另一个包含三个元素的匿名数组的引用。 (这
稍后描述的多维语法可用于访问它。 例如,
在上述之后,“$arrayref->[2][1]”将具有值“b”。)

引用枚举列表与使用 square 不同
括号——相反,它与创建引用列表相同!

@list = (\$a, \@b, \%c);
@list = \($a, @b, %c); # 一样!

作为一种特殊情况,“\(@foo)”返回对 @foo 内容的引用列表,而不是
对 @foo 本身的引用。 对于 %foo 也是如此,只不过关键引用是
副本(因为键只是字符串而不是成熟的标量)。

3. 可以使用大括号创建对匿名哈希的引用:

$hashref = {
'亚当' => '夏娃',
'克莱德' => '邦妮',
};

像这样的匿名哈希和数组编辑器可以自由混合以生成:
根据需要将结构复杂化。 下面描述的多维语法
也适用于这些。 上面的值是文字,但是变量和表达式
也会同样有效,因为 Perl 中的赋值运算符(即使在 当地的() or
我的()) 是可执行语句,而不是编译时声明。

因为大括号(大括号)用于其他一些东西,包括 BLOCK,
有时您可能需要在语句开头消除大括号的歧义
在前面放一个“+”或“return”,以便 Perl 意识到左大括号不是
开始一个BLOCK。 使用curlies的经济和助记价值被认为是值得的
这偶尔会带来额外的麻烦。

例如,如果您想要一个函数创建一个新的哈希值并返回对其的引用,
您有以下选择:

sub hashem { { @_ } } # 默默地错误
子哈希 { +{ @_ } } # 好的
子哈希 { return { @_ } } # 好的

另一方面,如果你想要其他含义,你可以这样做:

sub showem { { @_ } } # 不明确(目前可以,
# 但可能会改变)
子节目 { {; @_ } } # 好的
子showem { { return @_ } } # 好的

前导“+{”和“{;” 总是用来消除表达的歧义
HASH 引用或 BLOCK。

4. 可以使用不带子句的“sub”来创建对匿名子例程的引用
子名称:

$coderef = sub { print "Boink!\n" };

请注意分号。 除了里面的代码不会立即执行之外,一个“sub
{}”与其说是一个声明,不如说它是一个运算符,如“do{}”或“eval{}”。
(但是,无论您执行该特定行多少次(除非您处于
一个 "eval("...")"),$coderef 仍然会引用 匿名
子程序。)

匿名子例程充当闭包 我的() 变量,即
当前作用域内词汇可见的变量。 闭包是一个概念
Lisp 世界说如果你在特定的词法中定义一个匿名函数
上下文,即使在上下文之外调用它,它也会假装在该上下文中运行。

用人类的话来说,当您定义时,将参数传递给子例程是一种有趣的方式
它以及当你调用它时。 它对于设置要运行的少量代码很有用
稍后,例如回调。 你甚至可以用它来做面向对象的事情,尽管 Perl
已经提供了一种不同的机制来做到这一点——请参阅 perlobj。

您可能还认为闭包是一种编写子例程模板而不使用
评估()。 这是闭包如何工作的一个小例子:

子新纸{
我的 $x = 班次;
返回 sub { 我的 $y = 转变; 打印“$x,$y!\n”; };
}
$h = newprint("你好");
$g = newprint("问候");

# 时间流逝...

&$h("世界");
&$g("地球人");

这打印

你好,世界!
问候,地球人!

特别注意 $x 继续引用传入的值 新打印()
尽管 当匿名子例程运行时,“my $x”已超出范围。
这就是闭包的意义所在。

顺便说一句,这仅适用于词汇变量。 动态变量继续
像往常一样工作。 闭包并不是大多数 Perl 程序员所关心的
一开始就需要麻烦自己。

5. 引用通常由称为构造函数的特殊子例程返回。 珀尔
对象只是对特殊类型对象的引用,该对象恰好知道哪些
与其关联的包。 构造函数只是知道如何执行的特殊子例程
创建该关联。 他们从一个普通的参考开始,并且它
即使它也是一个对象,它仍然是一个普通的引用。 构造函数是
通常命名为“new()”。 你 能够 间接调用它们:

$objref = new Doggie( 尾巴 => '短', 耳朵 => '长' );

但这在某些情况下可能会产生不明确的语法,因此通常最好使用
直接方法调用方式:

$objref = Doggie->new(尾巴 => '短', 耳朵 => '长');

使用 Term::Cap;
$terminal = Term::Cap->Tgetent( { OSPEED => 9600 });

使用 Tk;
$main = 主窗口->new();
$menubar = $main->Frame(-relief => "凸起",
-边框宽度=> 2)

6. 如果取消引用,适当类型的引用就会出现
在假设它们存在的上下文中。 因为我们还没有讨论取消引用
然而,我们还无法向您展示任何示例。

7. 可以使用一种特殊的语法来创建引用,这种语法被亲切地称为
*foo{THING} 语法。 *foo{THING} 返回对 *foo 中 THING 槽的引用(其中
是符号表条目,其中包含称为 foo 的所有内容。

$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *处理程序{代码};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
$formatref = *foo{格式};
$globname = *foo{NAME}; #“富”
$pkgname = *foo{包}; # “主要的”

其中大多数都是不言自明的,但 *foo{IO} 值得特别注意。 它
返回 IO 句柄,用于文件句柄(perlfunc 中的“open”)、套接字(“socket”
在 perlfunc 中和“socketpair”在 perlfunc 中),以及目录句柄(“opendir”在
perlfunc)。 为了与以前版本的 Perl 兼容,*foo{FILEHANDLE} 是
*foo{IO} 的同义词,但从 5.8.0 开始已弃用。 如果弃用警告
生效后,它会对其使用发出警告。

*foo{THING} 如果尚未使用该特定 THING,则返回 undef,除非在
标量的情况。 *foo{SCALAR} 如果 $foo 返回对匿名标量的引用
尚未使用。 这可能会在未来的版本中发生变化。

*foo{NAME} 和 *foo{PACKAGE} 是例外,因为它们返回字符串,而不是
比参考文献。 它们返回 typeglob 本身的包和名称,而不是
比已分配给它的那个。 所以,在“*foo=*Foo::bar”之后,*foo将变成
"*Foo::bar" 当用作字符串时,但 *foo{PACKAGE} 和 *foo{NAME} 将继续
分别产生“main”和“foo”。

*foo{IO} 是“Typeglobs and
perldata 中的“文件句柄”,用于将文件句柄传入或传出子例程,或者
存储到更大的数据结构中。 它的缺点是它不会创建新的
为您提供文件句柄。 它的优点是你被破坏的风险比
你想要使用 typeglob 赋值。 (它仍然将文件和目录混为一谈
但是,如果将传入值分配给标量而不是
就像我们在下面的示例中所做的那样,使用 typeglob ,就不会有发生这种情况的风险。

溅射(*STDOUT); # 传递整个 glob
溅射(*STDOUT{IO}); # 传递文件和目录句柄

子溅射{
我的 $fh = shift;
打印 $fh "她嗯嗯嗯\n";
}

$rec = get_rec(*STDIN); # 传递整个 glob
$rec = get_rec(*STDIN{IO}); # 传递文件和目录句柄

子 get_rec {
我的 $fh = shift;
返回标量 <$fh>;
}

运用 案例
这就是创建参考的过程。 现在您可能非常想知道如何使用
参考以找回您丢失已久的数据。 有几种基本方法。

1. 将标识符(或标识符链)作为变量的一部分或
子例程名称,您可以用简单的标量变量替换标识符
包含正确类型的引用:

$bar = $$scalarref;
推(@$arrayref,$filename);
$$arrayref[0] = "一月";
$$hashref{"KEY"} = "VALUE";
&$coderef(1,2,3);
打印 $globref "输出\n";

重要的是要了解我们特别 而不去 取消引用 $arrayref[0]
或 $hashref{"KEY"} 那里。 发生标量变量的取消引用 before it
进行任何关键查找。 任何比简单标量变量更复杂的东西都必须
使用下面的方法 2 或 3。 然而,“简单标量”包括一个标识符
本身递归地使用方法1。 因此,下面打印“howdy”。

$refrefref = \\\"你好";
打印$$$$refrefref;

2. 将标识符(或标识符链)作为变量的一部分或
子例程名称,您可以用返回引用的 BLOCK 替换标识符
正确的类型。 换句话说,前面的例子可以这样写:

$bar = ${$scalarref};
推(@{$arrayref}, $文件名);
${$arrayref}[0] = "一月";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("输出\n"); # 当且仅当 IO::Handle 已加载

不可否认,在这种情况下使用花体有点愚蠢,但是 BLOCK 可以
包含任意表达式,特别是带下标的表达式:

&{ $dispatch{$index} }(1,2,3); # 调用正确的例程

由于能够省略 $$x 的简单情况,人们经常
错误地将解引用符号视为正确的运算符,并且想知道
关于他们的优先顺序。 但是,如果是的话,您可以使用括号而不是
大括号。 事实并非如此。 考虑以下差异; case 0 是简写
案例1的版本, 而不去 案例2:

$$hashref{"KEY"} = "VALUE"; # 案例0
${$hashref}{"KEY"} = "VALUE"; # 情况1
${$hashref{"KEY"}} = "VALUE"; # 案例2
${$hashref->{"KEY"}} = "VALUE"; # 案例3

情况 2 也具有欺骗性,因为您访问的是一个名为 %hashref 的变量,而不是
通过 $hashref 取消引用它可能引用的哈希。 那将是
案例3.

3. 子例程调用和单个数组元素的查找频繁出现,以至于
使用方法 2 会很麻烦。作为语法糖的一种形式,以下示例
方法2可以写成:

$arrayref->[0] = "一月"; # 数组元素
$hashref->{"KEY"} = "VALUE"; # 哈希元素
$coderef->(1,2,3); # 子程序调用

箭头的左侧可以是任何返回引用的表达式,包括
先前取消引用。 请注意 $array[$x] 是 而不去 与“$array->[$x]”相同
这里:

$array[$x]->{"foo"}->[0] = "一月";

这是我们之前提到的案例之一,其中引用可能会出现
在左值上下文中存在。 在这条语句之前,$array[$x]可能已经是
不明确的。 如果是这样,它会自动使用哈希引用定义,以便我们可以
在其中查找“{”foo“}”。 同样 "$array[$x]->{"foo"}" 将自动获取
用数组引用定义,以便我们可以在其中查找“[0]”。 这个过程是
被称为 自动活化.

这里还有一件事。 箭头是可选的 之间 括号下标,所以你可以
将上面的内容缩小到

$array[$x]{"foo"}[0] = "一月";

在仅使用普通数组的退化情况下,这给你
多维数组就像 C 语言一样:

$分数[$x][$y][$z] += 42;

好吧,实际上并不完全像 C 的数组。 C 不知道如何成长
按需阵列。 Perl 确实如此。

4. 如果一个引用恰好是一个对象的引用,那么很可能有方法
访问所提到的内容,您可能应该坚持使用这些方法
除非您位于定义对象方法的类包中。 换句话说,
保持友善,并且在没有充分理由的情况下不要违反对象的封装。
Perl 不强制封装。 我们这里不是极权主义者。 我们确实期望
不过有一些基本的礼貌。

使用字符串或数字作为引用会产生符号引用,如上所述。
使用引用作为数字会生成一个表示其存储位置的整数
记忆。 唯一有用的事情就是比较两个参考
数字以查看它们是否引用相同的位置。

if ($ref1 == $ref2) { # 引用的廉价数字比较
print "refs 1 和 2 指的是同一个东西\n";
}

使用引用作为字符串会生成其引用对象的类型,包括任何包
perlobj 中描述的祝福,以及以十六进制表示的数字地址。 这
参考() 运算符仅返回引用所指向的事物的类型,而不返回
地址。 有关其使用的详细信息和示例,请参阅 perlfunc 中的“ref”。

这个 保佑() 运算符可用于将引用指向的对象与
包充当对象类。 请参阅 perlobj。

typeglob 可以像引用一样取消引用,因为取消引用
语法始终指示所需的引用类型。 所以“${*foo}”和“${\$foo}”都是
指示相同的标量变量。

这是将子例程调用插入字符串的技巧:

print "我的 sub 当时返回了 @{[mysub(1,2,3)]}。\n";

它的工作方式是,当在双引号字符串中看到“@{...}”时,它是
评估为一个块。 该块创建对包含以下内容的匿名数组的引用
调用“mysub(1,2,3)”的结果。 所以整个块返回一个对
数组,然后通过“@{...}”取消引用并插入双引号字符串中。
这种欺骗对于任意表达式也很有用:

print "这会产生 @{[$n + 5]} 小部件\n";

类似地,返回标量引用的表达式可以通过以下方式取消引用
“${...}”。 因此,上面的表达式可以写为:

print "这会产生 ${\($n + 5)} 小部件\n";

案例
在 Perl 中创建“循环引用”是可能的,这可能导致内存泄漏。 A
当两个引用包含对彼此的引用时,就会发生循环引用,例如
这个:

我的 $foo = {};
我的 $bar = { foo => $foo };
$foo->{bar} = $bar;

您还可以使用单个变量创建循环引用:

我的 $foo;
$foo = \$foo;

在这种情况下,变量的引用计数永远不会达到 0,并且引用
永远不会被垃圾收集。 这可能会导致内存泄漏。

因为 Perl 中的对象是作为引用实现的,所以可能有循环
也可以引用对象。 想象一个 TreeNode 类,其中每个节点都引用它的
父节点和子节点。 任何具有父节点的节点都将成为循环引用的一部分。

您可以通过创建“弱引用”来打破循环引用。 弱引用确实
不增加变量的引用计数,这意味着该对象可以出去
范围并被摧毁。 您可以使用导出的“weaken”函数削弱引用
通过 Scalar::Util 模块。

以下是我们如何使第一个示例更安全:

使用 Scalar::Util '弱化';

我的 $foo = {};
我的 $bar = { foo => $foo };
$foo->{bar} = $bar;

削弱 $foo->{bar};

从 $foo 到 $bar 的引用已被削弱。 当 $bar 变量超出
范围,它将被垃圾收集。 下次当你查看该值时
“$foo->{bar}”键,它将是“undef”。

这个远距离的动作可能会令人困惑,所以你应该小心使用
削弱。 您应该削弱将超出范围的变量中的引用 第一.
这样,寿命较长的变量将包含预期的引用,直到它消失
的范围。

符号 引用
我们说过,如果引用未定义,则它们会根据需要而出现,但是我们
没有说如果已经定义了用作引用的值会发生什么,但是 是不是 a
硬参考。 如果您将其用作引用,它将被视为符号引用。
也就是说,标量的值被视为 姓名 一个变量,而不是一个
直接链接到(可能)匿名值。

人们经常期望它像这样工作。 确实如此。

$name = "foo";
$$名称 = 1; # 设置$foo
${$名称} = 2; # 设置$foo
${$名称 x 2} = 3; # 设置$foofoo
$名称->[0] = 4; # 设置$foo[0]
@$名称=(); # 清除@foo
&$name(); # 调用 &foo()
$pack =“那个”;
${"${pack}::$name"} = 5; # 设置 $THAT::foo 而不使用 eval

这是强大的,但有点危险,因为它可以意图(以最大的努力)
真诚)使用硬引用,并意外地使用符号引用。 到
防止这种情况,你可以说

使用严格的“参考”;

然后,仅允许对封闭块的其余部分进行硬引用。 一个
内部块可能会反驳这一点

没有严格的“参考”;

只有包变量(全局变量,即使是本地化的)对符号引用可见。
词法变量(声明为 我的()) 不在符号表中,因此对于
这个机制。 例如:

本地 $value = 10;
$ref = "值";
{
我的价值 = 20;
打印 $$ref;
}

这仍然会打印 10,而不是 20。请记住 当地的() 影响包变量,其中
对于包来说都是“全局”的。

不那么具有象征意义 引用
符号引用周围的括号可以简单地用于隔离标识符或变量
表达式其余部分的名称,就像它们在字符串中一样。 为了
例,

$push = "弹出";
打印“${push}over”;

总是意味着打印“pop on over”,尽管push是一个保留字。 这是
概括为在没有双引号的情况下同样工作,因此

打印 ${push} 。 “超过”;

乃至

打印 ${ 推 } 。 “超过”;

将会有同样的效果。 这个构造是 而不去 被认为是一个象征性的参考
当您使用严格引用时:

使用严格的“参考”;
${ 裸字 }; # 好吧,意味着 $bareword。
${“裸词”}; # 错误,符号引用。

类似地,由于所有下标都是使用单个单词完成的,因此相同的规则
适用于任何用于下标哈希的裸字。 所以现在,而不是写

$array{ "aaa" }{ "bbb" }{ "ccc" }

你可以写

$array{ aaa }{ bbb }{ ccc }

不用担心下标是否是保留字。 在极少数情况下,您
确实想做类似的事情

$数组{移位}

您可以通过添加任何使其超过的内容来强制解释为保留字
一个裸词:

$数组{ 移位() }
$数组{+shift}
$array{ 移动@_ }

“使用警告”杂注或 -w 如果 switch 解释保留字,它将警告您
作为字符串。 但它不会再警告您使用小写单词,因为
字符串被有效引用。

伪哈希: 运用 an 排列 as a 哈希
伪哈希已从 Perl 中删除。 'fields' 编译指示仍然可用。

功能 模板
如上所述,可以访问可见词法变量的匿名函数
当该函数被编译时,创建一个闭包。 它保留对这些变量的访问
即使它直到稍后才运行,例如在信号处理程序或 Tk 回调中。

使用闭包作为函数模板允许我们生成许多函数
相似地。 假设您想要以生成 HTML 字体的颜色命名的函数
各种颜色的变化:

print "Be ", red("小心"), "用那个", green("light");

这个 红色的()绿色() 功能将是相似的。 为了创建这些,我们将分配一个闭包
到我们正在尝试构建的函数名称的 typeglob。

@colors = qw(红蓝绿黄橙紫紫);
为我的 $name (@colors) {
没有严格的“参考”; # 允许符号表操作
*$name = *{uc $name} = sub { " @_ " };
}

现在所有这些不同的功能似乎都是独立存在的。 您可以致电 红色的(),
红色的(), 蓝色(), 蓝色的(), 绿色()等。这种技术可以节省编译时间和内存
使用,并且也不太容易出错,因为语法检查是在编译时发生的。 它是
匿名子例程中的任何变量都必须是词法的,以便创建一个
适当的关闭。 这就是循环迭代变量中使用“my”的原因。

这是为闭包提供原型非常有意义的唯一地方之一。 如果
您想对这些函数的参数施加标量上下文(可能不是
对于这个特定的例子来说是明智的想法),你可以这样写:

*$name = sub ($) { " $_[0] " };

然而,由于原型检查发生在编译时,所以上面的赋值会发生
太晚了,没有多大用处。 您可以通过将整个循环放在
BEGIN 块内的赋值,强制它在编译期间发生。

访问随时间变化的词汇——就像上面“for”循环中的词汇一样,基本上
来自周围词法范围的元素的别名——仅适用于匿名子项,
不使用命名子例程。 一般来说,命名子程序不能正确嵌套,
只能在主包范围内声明。

这是因为命名子例程是在编译时创建的,因此它们的词法变量
从父块的第一次执行开始分配给父词法。 如果一个
第二次进入父作用域,它的词法被再次创建,而嵌套的
潜艇仍然引用旧的。

每次执行“sub”运算符时,匿名子例程都会捕获,因为它们是
即时创建。 如果您习惯在其他编程中使用嵌套子程序
语言有自己的私有变量,你必须在 Perl 中进行一些工作。 这
此类事物的直观编码会引发关于“不会留下来”的神秘警告
由于上述原因,“共享”。例如,这是行不通的:

子外{
我的 $x = $_[0] + 35;
sub inside { return $x * 19 } # 错误
返回 $x + 内部();
}

解决方法如下:

子外{
我的 $x = $_[0] + 35;
本地 *inner = sub { return $x * 19 };
返回 $x + 内部();
}

现在 内() 只能从内部调用 外(),因为临时任务
的匿名子例程。 但当它发生时,它可以正常访问词汇
变量 $x 的范围 外() 在调用外部时。

这具有创建另一个函数的本地函数的有趣效果,
Perl 中通常不支持的东西。

警告


您可能不会(有用地)使用引用作为哈希的密钥。 它将被转换成
串:

$x{ \$a } = $a;

如果您尝试取消引用该键,它不会执行硬取消引用,并且您也不会
完成你正在尝试的事情。 你可能想做一些更像

$r = \@a;
$x{ $r } = $r;

然后至少你可以使用 values(),这将是真正的参考,而不是
键(),这不会。

标准 Tie::RefHash 模块为此提供了一种方便的解决方法。

后缀 解引用 句法


从 v5.20.0 开始,提供了使用引用的后缀语法。 它的行为就像
在“使用引用”中描述,但不是前缀印记,而是后缀印记和-
使用星号。

例如:

$r = \@a;
@b = $r->@*; # 相当于@$r 或@{ $r }

$r = [ 1, [ 2, 3 ], 4 ];
$r->[1]->@*; # 相当于@{ $r->[1] }

必须使用“use feature 'postderef'”启用此语法。 这是实验性的,并且将会
默认情况下发出警告,除非“没有警告'experimental::postderef'”有效。

后缀解引用应该适用于块(circumfix)解引用的所有情况
有效,并且应该完全等效。 该语法允许编写取消引用
并完全从左到右阅读。 定义了以下等效项:

$sref->$*; # 与 ${ $sref } 相同
$aref->@*; # 与 @{ $aref } 相同
$aref->$#*; # 与 $#{ $aref } 相同
$href->%*; # 与 %{ $href } 相同
$cref->&*; # 与 &{ $cref } 相同
$gref->**; # 与 *{ $gref } 相同

特别注意“$cref->&*”是 而不去 相当于“$cref->()”,并且可以服务于不同的
的目的。

可以通过后缀解引用功能提取 Glob 元素:

$gref->*{标量}; # 与 *{ $gref }{SCALAR} 相同

后缀数组和标量取消引用 能够 用于插入字符串(双引号
或“qq”运算符),但前提是启用了附加的“postderef_qq”功能。

后缀 参考法案 切片
数组和散列的值切片也可以采用后缀解除引用表示法,
具有以下等价关系:

$aref->@[ ... ]; # 与 @$aref[ ... ] 相同
$href->@{ ... }; # 与 @$href{ ... } 相同

Postfix 键/值对切片,在 5.20.0 中添加并记录在键/值哈希中
perldata 的切片部分,也按预期运行:

$aref->%[ ... ]; # 与 %$aref[ ... ] 相同
$href->%{ ... }; # 与 %$href{ ... } 相同

与后缀数组一样,后缀值切片取消引用 能够 用于插值
字符串(双引号或“qq”运算符),但前提是附加“postderef_qq”
功能已启用。

分配 案例


从 v5.22.0 开始,可以分配引用运算符。 它执行一个
别名操作,使左侧引用的变量名变成
右侧引用的事物的别名:

\$a = \$b; # $a 和 $b 现在指向相同的标量
\&foo = \&bar; # foo() 现在意味着 bar()

必须使用“使用功能‘refaliasing’”启用此语法。 这是实验性的,并且
默认情况下会发出警告,除非“没有警告‘experimental::refaliasing’”生效。

这些形式可以分配给右侧,并导致右侧以标量求值
上下文:

\$标量
\@大批
\%哈希值
\&sub
\我的$标量
\我的@array
\我的%哈希值
\state $scalar # 或 @array 等。
\我们的$标量#等。
\local $scalar # 等。
\local 我们的 $scalar # 等。
\$some_array[$index]
\$some_hash{$key}
\local $some_array[$index]
\local $some_hash{$key}
健康)状况 ? \$this : \$that[0] # 等等

切片操作和括号会导致在列表中评估右侧
上下文:

\@数组[5..7]
(\@array[5..7])
\(@array[5..7])
\@hash{'foo','bar'}
(\@hash{'foo','bar'})
\(@hash{'foo','bar'})
(\$标量)
\($标量)
\(我的$标量)
\my($标量)
(\@大批)
(\%哈希值)
(\&子)
\(&子)
\($foo, @bar, %baz)
(\$foo, \@bar, \%baz)

右侧的每个元素必须是对正确类型的数据的引用。
紧邻数组的括号(也可能是
"my"/"state"/"our"/"local") 将使数组的每个元素成为
右侧引用的相应标量:

\(@a) = \(@b); # @a 和 @b 现在具有相同的元素
\my(@a) = \(@b); # 同样地
\(我的@a) = \(@b); # 同样地
推@a,3; # 但现在 @a 多了一个 @b 缺少的元素
\(@a) = (\$a, \$b, \$c); # @a 现在包含 $a、$b 和 $c

将该形式与“local”结合起来并立即在散列两边加上括号是
禁止(因为不清楚他们应该做什么):

\local(@array) = foo(); # 错误的
\(%hash) = bar(); # 错误的

对引用和非引用的分配可以在列表和条件中组合
三元表达式,只要右侧的值是正确的类型
左侧的每个元素,尽管这可能会导致代码混淆:

(我的$汤姆,\我的$迪克,\我的@harry)=(\ 1,\ 2,[1..3]);
# $tom 现在是 \1
# $dick 现在是 2(只读)
# @harry 是 (1,2,3)

我的 $type = ref $thingy;
($type ? $type == 'ARRAY' ? \@foo : \$bar : $baz) = $thingy;

“foreach”循环还可以为其循环变量采用引用构造函数,尽管
语法仅限于以下之一,后面带有可选的“my”、“state”或“our”
反斜杠:

\$s
\@A
\%H
\&C

不允许使用括号。 此功能对于数组的数组特别有用,
或哈希数组:

foreach \my @a (@array_of_arrays) {
frobnicate($a[0], $a[-1]);
}

foreach \my %h (@array_of_hashes) {
$h{gelastic}++ 如果 $h{type} == '有趣';
}

警告: 别名不能与闭包一起正常工作。 如果你尝试给词法起别名
来自内部子例程或“eval”的变量,别名仅在内部子例程或“eval”中可见
该内部子程序,并且不会影响声明变量的外部子程序。
这种奇怪的行为可能会改变。

使用 onworks.net 服务在线使用 perlref


免费服务器和工作站

下载 Windows 和 Linux 应用程序

Linux 命令

Ad




×
广告
❤️在这里购物、预订或购买——免费,有助于保持服务免费。