博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
perl子例程_子例程签名在Perl 6中如何工作
阅读量:2530 次
发布时间:2019-05-11

本文共 10000 字,大约阅读时间需要 33 分钟。

perl子例程

在本系列的中,比较了Perl 5和Perl 6,我们研究了在将代码迁移到Perl 6中可能遇到的一些问题。在 ,我们研究了垃圾收集在Perl 6中的工作方式, ,我们研究了容器如何替换Perl 6中的引用。在第四篇文章中,我们将重点介绍Perl 6中的(子例程)签名以及它们与Perl 5中的区别。

Perl 5中的实验签名

如果要从Perl 5代码迁移到Perl 6,则可能未使用Perl 5.20或任何较早的CPAN模块(例如 , 或任何其他Perl)中可用的 CPAN上的5个模块带有 。

在世界范围内的Perl程序中很少使用(例如 )。

由于这些原因,我仅将Perl 6功能与“经典” Perl 5参数传递的最常用用法进行比较。

在Perl 5中传递参数

传递给Perl 5子例程的所有参数将被展平,并放入自动定义的@_数组变量中。 基本上,Perl 5会将参数传递给子例程。 仅此而已。 但是,Perl 5中有一些习惯用法可以代替它。 根据我的经验,最常见的习惯用法是:

# Perl 5      
sub do_something
{
   
my
(
$foo
,
$bar
)
=
@_
;
   
# actually do something with $foo and $bar
}

这个习语对两个(新)词法变量执行列表分配(复制)。 Perl 6也支持这种访问子例程参数的方式,但它只是为了使迁移更容易。

如果期望固定数量的参数后跟可变数量的参数,通常使用以下惯用法:

# Perl 5      
sub do_something
{
   
my
$foo
=
;
   
my
$bar
=
;
   
for
(
@_
)
{
       
# do something for each element in @_
   
}
}

这个习语取决于的魔术行为,在这种情况下,该行为从@_转移。 如果打算将该子例程作为方法调用,则通常会看到类似以下内容:

# Perl 5      
sub do_something
{
   
my
$self
=
;
   
# do something with $self
}

因为传递的第一个参数是Perl 5中的 。

顺便说一句,这个习语也可以写成第一个习语:

# Perl 5      
sub do_something
{
   
my
(
$foo
,
$bar
,
@rest
)
=
@_
;
   
for
(
@rest
)
{
       
# do something for each element in @rest
   
}
}

但这会降低效率,因为它将涉及复制可能很长的值列表。

第三个习惯用法是直接访问@_数组。

# Perl 5      
sub sum_two
{
   
$_
[
0
]
+
$_
[
1
]
;  
# return the sum of the two parameters
}

该习惯用法通常用于小型的单行子例程,因为它是处理参数的最有效方法之一,因为不会进行复制。

如果要更改作为参数传递的任何变量,也可以使用此惯用法。 由于@_中的元素是任何指定@_的别名(在Perl 6中,您会说:“绑定到变量”),因此可以更改内容:

# Perl 5      
sub make42
{
   
$_
[
0
]
=
42
;
}
my
$a
=
666
;
make42
(
$a
)
;
say
$a
;      
# 42

Perl 5中的命名参数

诸如此类的命名参数在Perl 5中不存在 。但是,有一个常用的成语有效地模仿了命名参数:

# Perl 5      
sub do_something
{
   
my
%named
=
@_
;
   
if
(
%named
{
bar
}
)
{
       
# do stuff if named variable "bar" exists
   
}
}

%named通过从@_数组中交替获取键和值来初始化%named @_哈希。 如果您使用fat-逗号语法调用带有参数的子例程:

# Perl 5      
frobnicate
( bar
=>
42
)
;

它将传递两个值"foo"42 ,这两个值将作为与键"foo"关联的值42放入%named哈希中。 但是,如果您指定以下内容,也会发生相同的事情:

# Perl 5      
frobnicate
(
"bar"
,
42
)
;

=>是语法糖,用于自动引用左侧。 否则,它的功能就像逗号一样(因此命名为“胖逗号”)。

如果将子例程作为带有命名参数的方法来调用,则此惯用语将与标准惯用语结合使用:

# Perl 5      
sub do_something
{
   
my
(
$self
,
%named
)
=
@_
;
   
# do something with $self and %named
}

或者:

# Perl 5      
sub do_something
{
   
my
$self  
=
;
   
my
%named
=
@_
;
   
# do something with $self and %named
}

在Perl 6中传递参数

以最简单的形式,Perl 6中的子例程签名非常类似于Perl 5的“标准”惯用语。但是​​,它们不是该代码的一部分,而是该子例程的定义的一部分,您无需这样做。那作业:

# Perl 6      
sub do
- something
(
$foo
,
$bar
)
{
   
# actually do something with $foo and $bar
}

与:

# Perl 5      
sub do_something
{
   
my
(
$foo
,
$bar
)
=
@_
;
   
# actually do something with $foo and $bar
}

在Perl 6中, ($foo, $bar)部分称为子例程的签名

由于Perl 6具有实际的method关键字,因此不必考虑主诉人,因为self项自动可用:

# Perl 6      
class Foo
{
    method do
- something
-
else
(
$foo
,
$bar
)
{
       
# do something else with self, $foo and $bar
   
}
}

此类参数在Perl 6中称为位置参数 。除非另有说明,否则在调用子例程时必须指定位置参数。

如果需要在Perl 5中直接使用$_[0]的别名行为,则可以通过指定is rw特性将参数标记为可写:

# Perl 6      
sub make42
(
$foo is rw
)
{
   
$foo
=
42
;
}
my
$a
=
666
;
make42
(
$a
)
;
say
$a
;      
# 42

当您将数组作为参数传递给子例程时,它不会在Perl 6中变平。您只需要在签名中接受一个数组作为数组:

# Perl 6      
sub handle
- array
(
@a
)
{
   
# do something with @a
}
my
@foo
=
"a"
..
"z"
;
handle
- array
(
@foo
)
;

您可以传递任意数量的数组:

# Perl 6      
sub handle
- two
- arrays
(
@a
,
@b
)
{
   
# do something with @a and @b
}
my
@bar
=
1
..
26
;
handle
- two
- arrays
(
@foo
,
@bar
)
;

如果您希望Perl 5的( )扁平化语义,可以通过在签名的前面加上星号来用“浆糊数组”来表明这一点:

# Perl 6      
sub slurp
- an
- array
(
*@
)
{
   
# do something with @values
}
slurp
- an
- array
(
"foo"
,
42
,
"baz"
)
;

稀疏数组只能作为签名中的最后一个位置参数出现。

如果您喜欢使用Perl 5在Perl 6中指定参数的方式,可以通过在签名中指定一个稀疏数组*@_来实现:

# Perl 6      
sub do
- like
-
5
(
*
@_
)
{
   
my
(
$foo
,
$bar
)
=
@_
;
}

Perl 6中的命名参数

在调用方,Perl 6中的命名参数的表达方式与Perl 5中的表达方式非常相似:

# Perl 5 and Perl 6      
frobnicate
( bar
=>
42
)
;

但是,在子例程的定义方面,情况非常不同:

# Perl 6      
sub frobnicate
(
:
$bar
)
{
   
# do something with $bar
}

普通(位置)参数和命名参数之间的区别是冒号,冒号先于 以及定义中的变量名称:

$foo           
# positional parameter, receives in $foo
:
$bar    
# named parameter "bar", receives in $bar

除非另有说明,否则命名参数是可选的 。 如果未指定命名参数,则关联变量将包含默认值,该默认值通常是类型对象Any

如果要捕获任何 (其他)命名参数,则可以使用所谓的“稀疏哈希”。 就像slurpy数组一样,它在哈希之前以星号表示:

# Perl 6      
sub slurp
- nameds
(
*
%nameds
)
{
    say
"Received: "
~
", "
,
%nameds
;
}
slurp
- nameds
( foo
=>
42
, bar
=>
666
)
;
# Received: bar, foo

与slurpy数组一样,签名中只能有一个slurpy哈希,并且必须在其他任何命名参数之后指定。

通常,您希望将命名参数从具有相同名称的变量传递给子例程。 在Perl 5中,它看起来像: do_something(bar => $bar) 。 在Perl 6中,可以用相同的方式指定它: do-something(bar => $bar) 。 但是,您也可以使用快捷方式: do-something(:$bar) 。 这意味着更少的打字次数和更少的错别字机会。

Perl 6中的默认值

Perl 5具有以下惯用法,用于使参数成为默认值:

# Perl 5      
sub dosomething_with_defaults
{
   
my
$foo
=
@_
?
:
42
;
   
my
$bar
=
@_
?
:
666
;
   
# actually do something with $foo and $bar
}

在Perl 6中,可以通过指定等号和表达式来将默认值指定为签名的一部分:

# Perl 6      
sub dosomething
- with
- defaults
(
$foo
=
42
,
:
$bar
=
666
)
{
   
# actually do something with $foo and $bar
}

如果为位置参数指定了默认值,则它们将变为可选参数。 无论任何默认值,命名参数都保持可选。

摘要

Perl 6具有一种描述子例程的参数应如何捕获到该子例程的参数中的方式。 位置参数由其名称和适当的符号(例如$foo )指示。 命名参数以冒号作为前缀(例如:$bar )。 可以将位置参数标记为is rw以允许在调用者的作用域中更改变量。

位置参数可以在一个带有星号(例如*@values )前缀的稀疏数组中展平。 可以使用粗俗的哈希来收集意外的命名参数,该哈希还以星号作为前缀(例如*%nameds )。

通过在等号后添加表达式(例如$foo = 42 ),可以在签名内指定默认值,这使该参数成为可选参数。

除了此处概述的功能外,Perl 6中的签名还具有许多其他有趣的功能。 如果您想进一步了解它们,请查阅Perl 6 。

翻译自:

perl子例程

转载地址:http://mgjzd.baihongyu.com/

你可能感兴趣的文章
SCALA STEP BY STEP
查看>>
cocos2d-x学习笔记
查看>>
MySql中的变量定义
查看>>
Ruby数组的操作
查看>>
hdu1181暴搜
查看>>
解码字符串 Decode String
查看>>
json学习笔记
查看>>
工具:linux 性能监控工具-nmon
查看>>
fatal error C1853
查看>>
Ural 1001 - Reverse Root
查看>>
玩转webpack之webpack的entry output
查看>>
java 操作mongodb查询条件的常用设置
查看>>
黑马程序员_java基础笔记(02)...java语言基础组成
查看>>
对innodb 拷贝文件实现数据库的方式(转)
查看>>
python知识点 2014-07-09
查看>>
FloatingActionButton的一点学习感悟
查看>>
ABAP CDS ON HANA-(10)項目結合して一つ項目として表示
查看>>
网站地址信息
查看>>
产品经理 - 登录 注册
查看>>
Notepad++ 通过g++编译
查看>>