perl语言中变量
在本系列的前四篇文章中,比较了Perl 5和Perl 6,我们研究了在迁移代码时可能遇到的一些问题, 垃圾回收的工作原理, 容器为何替换引用以及在Perl 6中使用(子例程)签名以及如何这些与Perl 5不同。
在这里,第五篇文章中,我们将着眼于细微的差别印记的Perl 5和Perl 6之间(在变量名的开始符号)。
概述
让我们从Perl 5和Perl 6的概述开始:
印记 | Perl 5 | Perl 6 |
---|---|---|
@ | 数组 | 位置性 |
% | 杂凑 | 联想的 |
& | 子程序 | 可召回 |
$ | 标量 | 项目 |
* | 类型球 | 不适用 |
@(数组与位置)
在Perl 5中定义数组时,您将创建一个可扩展的标量值列表,并使用sigil @命名它:
在Perl 6中定义数组时,将创建一个新的Array对象,并将其通过词汇表中的该名称绑定到该条目。 所以:
在功能上与Perl 5中的相同。但是,第一行是用于以下方面的语法糖:
# Perl 6
my
@foo
:= Array
.
new
(
1
,
2
,
3
)
;
这会将新的Array对象绑定(而不是分配)到按词法定义的名称@foo 。 Perl 6中的@ sigil表示类型约束:如果要使用该符号将某些内容绑定到lexpad条目中,则它必须执行Positional角色。 使用smartmatch确定类是否扮演特定角色并不难:
# Perl 6
say Array
~~ Positional
;
# True
您可能会争辩说,Perl 6中的所有数组都是以与 Perl 5中的绑定数组相同的方式实现的。 在不深入细节的情况下,可以通过一个简单的示例来阐明这一点。 AT-POS方法是实现位置角色的类的关键方法之一。 每当需要访问单个元素时,都会调用此方法。 所以,当你写:
say @a [ 42 ] ;
您正在执行:
say @a . AT - POS ( 42 ) ;
当然,这不是您可以实现的唯一方法。 还有更多 。
不必绑定执行位置角色的类,而是使用is trait的特殊语法。 因此,不必写:
# Perl 6
my
@a
:= YourClass
.
new
(
1
,
2
,
3
)
;
你可以写:
# Perl 6
my
@a is YourClass
=
1
,
2
,
3
;
在可能的情况下将操作码转换为机器代码。
(由于优化程序的进步,这种情况更快,更频繁,更好地发生了)。
%(哈希与关联)
Perl 6中的散列与数组的实现类似; 您也可以将它们视为绑定哈希(使用Perl 5术语)。 代替用于实现数组的Positional角色,应该使用Associative角色来实现哈希。
同样,一个简单的例子可能会有所帮助。 AT-KEY方法是实现关联角色的类的关键方法之一。 每当需要访问特定键的值时,都会调用此方法。 所以,当你写:
say %h <foo>
您正在执行:
say %h . AT - KEY ( "foo" ) ;
当然还有很多其他方法 你可以实现。
&(子例程vs.可调用)
在Perl 5中,只有一种类型的可调用可执行代码,即子例程:
而且,如果要传递子例程作为参数,则需要获取对其的引用:
在Perl 6中,多种类型的对象可以包含可执行代码。 他们的共同点是他们担当了Callable角色 。
&标记将绑定到执行Callable角色的对象,就像%标记与关联角色一样, @标记与位置角色一样。 非常接近Perl 5的示例是:
# Perl 6
my
&foo
=
sub
(
$a
,
$b
)
{
$a
+
$b
}
say foo
(
42
,
666
)
;
# 708
需要注意的是,即使变量具有与印记,你并不需要使用它的变量来执行代码。 实际上,如果您在BEGIN块中运行代码,则与普通的子声明相比没有什么区别:
# Perl 6
BEGIN
my
&foo
=
sub
(
$a
,
$b
)
{
$a
+
$b
}
# same as sub foo()
与Perl 5相比,在Perl 6中, BEGIN块可以是没有块的单个语句,因此它与外部共享其词法范围。 但是,我们将在以后的文章中进一步讨论。
其主要优势,使用了与 sigilled变量是,它会在编译的时候会有在那里可执行的东西 ,即使东西还不知道知道。
还有其他方法可以设置一段代码来执行:
# Perl 6
my
&boo
=
->
$a
,
$b
{
$a
+
$b
}
# same, using a Block with a signature
my
&goo
=
{
$^a
+
$^b
}
# same, using auto-generated signature
my
&woo
=
*
+
*;
# same, using Whatever currying
如果您想了解更多信息:
您使用的那个取决于情况和您的偏好。
最后,您还可以使用签名中的&标记来表明被叫方想要在那里执行某些操作。 这使我们回到本节的前两个代码示例:
# Perl 6
sub frobnicate
{
$^a
**
2
}
sub do
- stuff
- with
(
&lambda
,
$param
)
{ lambda
(
$param
)
}
say do
- stuff
- with
(
&frobnicate
,
42
)
;
# 1764
注意,在Perl 6中,您不需要参考。 您可以简单地将代码对象(如& sigil所示)作为参数传递。
$(标量与项目)
与@ , %和& sigils相比, $ sigil有点平淡。 它不执行任何类型检查,因此您可以将其绑定到任何类型的对象。 因此,当您编写:
# Perl 6
my
$answer
=
42
;
发生这样的事情:
# Perl 6
my
$answer
:= Scalar
.
new
(
42
)
;
除了非常低的水平。 因此,如果您想知道,此代码将不起作用。 这就是声明标量变量时的全部内容。
在Perl 6中, $还表示其中的任何内容都应视为一个项目。 因此,即使标量容器中填充了Array对象,在需要迭代的情况下,也将其视为单个项目:
# Perl 6
my
@foo
=
1
,
2
,
3
;
my
$bar
= Array
.
new
(
1
,
2
,
3
)
;
# alternately: [1,2,3]
. say
for
@foo
;
# 123
. say
for
$bar
;
# [1 2 3]
请注意,后一种情况仅进行一次迭代,而前一种情况仅进行三次 。 您可以通过在适当的符号前添加前缀来表明是否要迭代:
# Perl 6
. say
for $
@foo
;
# [1 2 3] , consider the array as an item
. say
for
@$bar
;
# 123 , consider the scalar as a list
但这可能使我们走入了线噪声领域。 幸运的是,还有更多详细的等效项:
# Perl 6
. say
for
@foo
. item
;
# [1 2 3] , consider the array as an item
. say
for
$bar
. list
;
# 123 , consider the scalar as a list
*(Typeglobs)
您可能已经注意到,Perl 6没有*符号,也没有typeglobs的概念。 如果您不知道什么是typeglob,则不必担心。 您可以很好地完成工作,而不必了解Perl 5中符号表的复杂性(并且可以跳过下一段)。
在Perl 6中, 符号是存储在符号表中的名称的一部分,而在Perl 5中,名称是不包含符号的。 例如,在Perl 5中,如果在程序中引用$ foo ,则编译器将查找foo (不带sigil),然后获取关联的信息(它是一个数组),并在索引中查找它需要的内容。 $印记。 在Perl 6中,如果引用$ foo ,则编译器将查找$ foo并直接使用与该键关联的信息。
请不要混淆用于指示在Perl 6的参数与在Perl的类型团印记slurpiness的* 5,他们什么都没有做与对方。
无痕变量
Perl 5不支持开箱即用的无符号变量(除了左值子例程,但这确实很笨拙)。
Perl 6也不直接支持无Sigilless变量,但是它通过在定义中的名称前面加上反斜杠( \ )来支持对无Sigilless名称的绑定:
# Perl 6
my
\the
- answer
=
42
;
say the
- answer
;
# 42
由于赋值的右侧是一个常量,因此这基本上与定义常量相同:
# Perl 5
use constant the_answer
=>
42
;
say the_answer
;
# 42
# Perl 6
my constant the
- answer
=
42
;
say the
- answer
;
# 42
如果定义的右侧是其他内容,则会更有趣。 像一个容器! 这允许使用以下语法技巧来获得无符号变量:
# Perl 6
my
\foo
= $
=
41
;
# a sigilless scalar variable
my
\bar
=
@
=
1
,
2
,
3
,
4
,
5
;
# a sigilless array
my
\baz
=
%
= a
=>
42
, b
=>
666
;
# a sigilless hash
基本上,这将创建无名词汇实体(标量,数组和哈希),并使用常规语义对其进行初始化,然后将结果对象( 标量容器, Array对象和Hash对象)绑定到无警惕的名称,您可以在Perl 6中将其用作任何其他普通变量。
# Perl 6
say
++ foo
;
# 42
say bar
[
2
]
;
# 3
bar
[
2
]
=
42
;
say bar
[
2
]
;
# 42
say baz
< a b
>;
# (42 666)
当然,这样做会失去信号的所有优点,特别是在插值方面。 然后,您将始终需要在插值中使用{} 。
# Perl 6
say
"The answer is {the-answer}."
;
# The answer is 42.
在大多数版本的Perl 5中,这种做法比较麻烦:
# Perl 5
say
"The answer is @{[the_answer]}."
;
# The answer is 42.
摘要
在考虑使用Perl 5概念的变量时,可以将Perl 6中的所有变量视为绑定变量。 这使它们起初有些慢。 但是在某些基准测试中,运行时优化和热代码路径的JITting(一度指向机器代码)已经使其比Perl 5变量快。
在Perl 6中, @ , %和&不会创建任何特定的对象,而是指示将类型约束应用于名称绑定到的对象。 $符号在这方面有所不同,因为没有类型约束要执行。
@和$前缀分别表示列表化和项目化,尽管使用.list和.item方法可能更易读。
通过一些语法技巧,您可以对 Perl 6进行编程,而无需在变量名中使用任何信号。
翻译自: https://opensource.com/article/18/9/using-sigils-perl-6
perl语言中变量