第七章 从 Perl5 到 Perl6
优质
小牛编辑
126浏览
2023-12-01
简介
尽管与Perl5相比很相似,Perl6依旧包含了大量的改动。本章节会帮助Perl5程序员更好的向Perl6过渡。
本章节将会简洁明了地教你如何将Perl5程序以最直接的方式改写到Perl6中,而不会去介绍Perl6中那些强有力的新操作符。
Hello World
Perl6中仍然保留了print()
,但是相比之下使用say()
会更加直接一点。
此方法今后可能会变得比较通用,因为它能够在行尾自动追加换行符(事实上Perl-5.10已经实现了这个特性)。
tutorial/p526/hello_world.p6
use v6;
# Perl5: print
# Perl5.10: say
# Perl6: print依旧可用,但是say更好些
# 就像5.10版本一样,能够在行尾自动追加换行符
print "Hello World\n";
say "Hello World";
标量变量
tutorial/p526/scalars.p6
use v6;
# Perl 5: my
# Perl 6: Perl6 中必须要使用“my”关键字(你可以当做一直处在严格模式下)
my $name = "Moose";
# Perl 6: 标量变量依旧能够嵌入到双引号字符串中:
say "Hello $name";
# 为了迎合面向对象教徒,Perl6中允许这么做:
"Hello $name".say;
# Perl 5: <STDIN>
# Perl 6: 由于从标准输入中读入单行数据需要首先打印出一条提示,
# Perl6中可以调用 prompt(),
# 它能够自动截断新的一行
my $line = prompt('Please type in your name: ');
say "Hi $line, how are you?";
# Perl 5: substr
# substr 依旧存在只不过没有了接收四个参数的版本
say substr $line, 2, 3;
# 依旧可用
$line.substr(2, 3).say;
# Perl 5: length
my $a = "This is a string";
# Perl 6: 去除了 length() 方法,相应地能加了意义更加明确的方法如 bytes() chars()
say $a.chars;
say $a.bytes;
# Perl 5: chomp
# Perl 6: 由于在Perl6中读入数据将对新行自动截断,因此此方法用的将会比较少
# 在任何情况下 chomp() 都将会返回截断后的值而不会改变变量本身
my $b = chomp $a;
# Perl 5: defined
# Perl 6: 依旧可用:
defined $b;
# Perl 5: undef
# Perl 6: 不一样!
# $b = undef; # 译注:这种写法Perl6将不再支持
# Perl 5: .
# Perl 6: 字符串拼接现在由 ~ 操作符完成
my $str = "Foo" ~ "Bar";
$str.say;
$str ~= " and Moo";
say $str;
# Perl 5: x
# Perl 6: 字符串倍率器依旧可用
say "abc" x 3;
# Perl 5: index 和 rindex
# Perl 6: 依旧可用
my $s = "The brown cat climbed the green tree";
index $s, "b";
# Perl 5: lc 和 uc
# Perl 6: 依旧可用
say lc "Hello World";
say uc "Hello World";
数组
tutorial/p526/arrays.p6
use v6;
# Perl6中声明新数组与Perl5无异
my @numbers = ("one", "two", "three");
# 用于调试的输出一般使用 .perl 方法而非 Data::Dumper:
@numbers.perl.say; # ["one", "two", "three"]
# Perl6中的方法调用可以省略圆括号:
my @digits = 1, 3, 6;
@digits.perl.say; # [1, 3, 6]
# Perl5 的 qw() 操作符被尖括号取代:
my @names = <foo bar baz>;
@names.perl.say; # ["foo", "bar", "baz"]
# 数组无法被嵌入到双引号的字符串中:
say "@names"; # @names
# 你可以直接使用@符号而无需转义它:
say "joe@names.org"; # joe@names.org
# 如果你需要将数组嵌入字符串内需要使用大括号:
say "names: {@names}"; # names: foo bar baz
# 在Perl6中访问数组依旧需要使用数组标记@
# 尽管看上去比较别扭,但是用长远的目光看这是有益的
say @names[0]; # foo
# Perl6摒弃了Perl5中 $#array 这样的形式
# 返回数组长度可以使用 elems() 函数
# 这里采用面向对象的写法比较好:
say @names.elems; # 3
# Perl6中区间依旧可用
my @d = 1..11;
@d.perl.say; # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
# 区间对于字符同样有效
my @chars = ('a' .. 'd');
@chars.perl.say; # ["a", "b", "c", "d"]
# Perl5中C语言风格的“for”循环现在叫做“loop”
# 但是我们在这里更推荐使用另一种风格的循环
# Perl5中人们经常写作“foreach”
# Perl6中就叫做“for”
for 1..3 -> $i {
say $i; # 1 # 2 # 3 (on 3 lines)
}
# 对于数组同样可用:
for @names -> $n {
say $n; # foo # bar # baz (on 3 lines)
}
# 在这种情况下不需要使用“my”关键字声明新变量
# 循环变量会被自动声明并且作用于循环体内
# 当需要使用数组下标进行迭代时可以这样写:
for 0..@names.elems -1 -> $i {
say "$i {@names[$i]}"; # 0 foo # 1 bar # 2 baz (on 3 lines)
}
# 你也可以使用 Moritz Lenz 推荐的方式来进行迭代(感谢Moritz!):
for @names.keys -> $i {
say "$i {@names[$i]}"; # 0 foo # 1 bar # 2 baz (on 3 lines)
}
# 从哈希借鉴来的keys方法能够返回数组的所有下标
# 即使数组中存在undef这样的值,keys也会将他们算在内
# split方法与Perl5无异,但是会少一些默认操作
# 关于这一点你需要查看标准
# 参见 S32-setting-library/Str.pod 以获得详细信息
# ( http://perlcabal.org/syn/S32/Str.html )
"a,b,c".split(',').perl.say; # ["a", "b", "c"]
哈希
tutorial/p526/hashes.p6
#!/usr/bin/env perl6
use v6;
# 像在Perl5中一样创建哈希
my %h = ("Perl", "Larry", "Python", "Guido");
# Perl5: 访问哈希元素
say %h{"Perl"}; # 访问哈希元素的方法与Perl5相同,但是需要保留%符号
# Perl5: 使用不带双引号的哈希键
say %h<Perl>; # 如果你不想使用双引号的话,可以采用这种写法(Perl5中写作 $h{Perl} )
# Perl5: exists
%h.exists("Perl"); # 检查键是否存在
defined(%h<Perl>); # 检查给定的键是否被定义
# Perl5: keys
keys %h; # 如同Perl5一样返回所有键
%h.keys; # 同样可用
# Perl5: values
# 依旧可用,同keys
# Perl5: each
# %h.kv
for %h.kv -> $key, $value {
say "$key => $value";
}
控制结构
tutorial/p526/control_structures.p6
use v6;
# Perl 5: if
# Perl 6: 用法相同,不过条件语句周围没有必要使用小括号包裹
my $x = 23;
if $x < 42 {
}
# Perl5: foreach (for)
my @names = <Larry Guido Matz>;
for @names -> $person {
say $person;
}
# Perl5: for (foreach)
loop (my $i=1; $i < 10; $i++) {
say $i;
}
# 无限循环:
loop {
say "lopping";
}
# Perl5: while
while $i < 10 {
say $i;
}
函数
tutorial/p526/functions.p6
#!/usr/bin/env perl6
use v6;
my $lang = "Perl";
creator("Larry", $lang);
sub creator { # 依旧和Perl5一样,从@_中获取变量
my ($person, $language) = @_;
say "the creator of $language is $person";
}
creator_2("Larry", $lang);
sub creator_2 ($person, $language) { # 你也可以定义想要的参数
#$language ~= 6; # 但是在这种情况下就无法改变变量
say "the creator of $language is $person";
}
creator_3("Larry", $lang);
sub creator_3 ($person, $language is rw) { # 你也可以定义想要的参数
$language ~= 6; # 现在你可以改变变量language的值
say "the creator of $language is $person";
}
say "What ? $lang"; # 这也同时会改变传入参数自身的值
creator_4("Larry", $lang);
sub creator_4 ($person is copy, $language is rw) {
$person ~= " Wall";
say "the creator of $language is $person";
}
文件
tutorial/p526/files.p6
#!/usr/bin/env perl6
use v6;
# Perl5: open
my $fh = open 'examples/p526/files.p6', :r;
# Perl5: close
close($fh);
$fh.close
# Perl5: <$fh>
# $fh.readline
模块和类
tutorial/p526/modules.p6
#!/usr/bin/env perl6
use v6;
# Perl5: package
module Person {
our $fname;
our $lname;
}
$Person::fname = "Foo";
$Person::lname = "Bar";
其他
译注:
这里单纯列举了一些从Perl5到Perl6的默认变量名或语法结构的变化
@ARGV @$ARGS
$0 $*PROGRAM-NAME
foreach my $s (@arr) {} for @arr -> $s { }
$#array
scalar @array @array.elems