perl5和perl6_容器在Perl 6

perl5和perl6

在本系列的第一篇文章中,比较了Perl 5和Perl 6,我们研究了将代码迁移到Perl 6时可能遇到的一些问题。在第二篇文章中 ,我们研究了Perl 6中垃圾回收的工作方式。第三篇文章,我们将重点介绍Perl 5的参考以及在Perl 6中如何处理它们,并介绍绑定和容器的概念。

参考资料

Perl 6中没有引用,这使许多习惯于Perl 5语义的人感到惊讶。 但不必担心:由于没有引用,因此您不必担心是否应取消引用某些内容。


   
   
# Perl 5
my $foo = \@bar ;   # must add reference \ to make $foo a reference to @bar
say @bar [ 1 ] ;       # no dereference needed
say $foo -> [ 1 ] ;     # must add dereference ->

# Perl 6
my $foo = @bar ;     # $foo now contains @bar
say @bar [ 1 ] ;       # no dereference needed, note: sigil does not change
say $foo [ 1 ] ;       # no dereference needed either

有人可能会说Perl 6中的所有内容都是参考。 来自Perl 5(其中的对象是一个受祝福的引用),这将是关于Perl 6的逻辑结论,在Perl 6中, 一切都是对象(或可以认为是对象)。 但这并不能使Perl 6的情况公平化,并且会妨碍您了解Perl 6的工作方式。当心虚假的朋友

捆绑

在开始分配之前,了解Perl 6中的绑定概念很重要。您可以使用:=运算符将某些内容明确绑定到其他内容。 定义词法变量时,可以将值绑定到它:

 my $foo := 42 ;  # note: := instead of = 

简而言之,这将在词汇垫(lexpad)中创建一个名称为“ $foo ”的键(您可以考虑将其包含在该词汇范围内可见的事物的信息的编译时哈希),并将其字面值设为42 。 因为这是一个文字常量,所以不能更改它。 尝试这样做将导致异常。 所以不要那样做!

此绑定操作在许多情况下都在后台使用,例如在迭代时:


   
   
my @a = 0 .. 9 ;     # can also be written as ^10
say @a ;           # [0 1 2 3 4 5 6 7 8 9]
for @a { $_ ++ }   # $_ is bound to each array element and incremented
say @a ;           # [1 2 3 4 5 6 7 8 9 10]

如果尝试遍历常量列表,则$_绑定到文字 ,您不能将其递增:

 for 0 .. 9 { $_ ++ }  # error: requires mutable arguments 

分配

如果在Perl 5和Perl 6中比较“创建词法变量并分配给它”,则外部看起来是相同的:

 my $bar = 56 ;  # both Perl 5 and Perl 6 

在Perl 6中,这还将在lexpad中创建一个名称为“ $bar ”的键。 但是,而不是直接绑定的值到lexpad条目, 容器Scalar对象)为您创建和绑定到“的lexpad进入$bar ”。 然后,将56作为值存储在该容器中。 在伪代码中,您可以将其视为:

 my $bar := Scalar . new ( value => 56 ) ; 

注意, Scalar对象是bound ,未分配。 在Perl 5中,与此最接近的是束缚标量 。 但是当然“ = 56 ”要少得多!

诸如ArrayHash类的数据结构也会自动将值放入绑定到该结构的容器中。


   
   
my @a ;       # empty Array
@a [ 5 ] = 42 ;   # bind a Scalar container to 6th element and put 42 in it

货柜

对于Perl 6中的大多数操作来说, Scalar容器对象是不可见的,因此大多数时候您不必考虑它。 例如,每当调用一个子程序(或方法)与变量作为自变量,它会结合容器中的值。 而且由于无法分配值,您将获得:


   
   
sub frobnicate ( $this ) {
    $this = 42 ;
}
my $foo = 666 ;
frobnicate ( $foo ) ; # Cannot assign to a readonly variable or a value

如果要允许分配外部值,可以将is rw特性添加到签名中的变量。 这会将签名中的变量绑定到指定变量的容器 ,从而允许赋值:


   
   
sub oknicate ( $this is rw ) {
    $this = 42 ;
}
my $foo = 666 ;
oknicate ( $foo ) ; # no problem
say $foo ;       # 42

代理

从概念上讲,Perl 6中的Scalar对象具有FETCH方法(用于生成对象中的值)和STORE方法(用于更改对象中的值),就像Perl 5中的绑定标量一样。

假设您稍后将值768分配给$bar变量:

 $bar = 768 ; 

从概念上讲,发生的事情等同于:

 $bar . STORE ( 768 ) ; 

假设您要在$bar的值上加上20

 $bar = $bar + 20 ; 

概念上发生的是:

 $bar . STORE ( $bar . FETCH + 20 ) ; 

如果您想在容器上指定自己的FETCHSTORE方法,则可以通过绑定Proxy对象来实现。 例如,创建一个变量,该变量将始终报告分配给它的值的两倍:


   
   
my $double := do {   # $double now a Proxy, rather than a Scalar container
    my $value ;
    Proxy . new (
      FETCH => method ( )     { $value + $value } ,
      STORE => method ( $new ) { $value = $new }
    )
}

请注意,您将需要一个额外的变量来将值存储在这样的容器中。

约束和默认

除值外, 标量还包含其他信息,例如类型约束和默认值。 采取以下定义:

 my Int $baz is default ( 42 ) = 666 ; 

它在lexpad上创建一个名称为“ $baz ”的标量绑定,将该容器中的值约束为与Int成功进行智能匹配的类型,将容器的默认值设置为42 ,并将值666放入容器中。

由于类型限制,将字符串分配给该变量将失败:


   
   
$baz = "foo" ;
# Type check failed in assignment to $baz; expected Int but got Str ("foo")

如果在定义变量时未提供类型约束,则将假定为Any类型。 如果未指定默认值,则将采用类型约束。

Nil (相当于Perl 5的undef的Perl 6)分配给该变量会将其重置为默认值:


   
   
say $baz ;   # 666
$baz = Nil ;
say $baz ;   # 42

摘要

Proxy (很像Perl 5中的绑定标量)和Scalar 。 简而言之,变量以及ListArrayHash的元素都是值(如果已绑定 )或容器(如果已分配 )。 每当调用子例程(或方法)时,给定的参数都将被取消容器化并绑定到子例程的参数(除非被告知要这样做)。 容器还保留诸如类型约束和默认值之类的信息。 将Nil分配给变量将使其返回其默认值,如果您未指定类型约束,则为Any

翻译自: https://opensource.com/article/18/8/containers-perl-6

perl5和perl6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值