当前位置: 首页 > 文档资料 > Perl6 入门指导 >

第七章 从 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