最新消息:

Perl6 vs Perl5 之我见

Perl admin 3486浏览 0评论

Perl6 诞生

2000 年 7 月 19 号,在一场无聊沉闷的政治组织会议中,Jon Orwant 站在一边听了几分钟,然后很淡定的走向咖啡桌,拿起一个个杯子往对面的墙上扔去,边扔边说“我们得想办法激励社群,不然都完了,大家越来越无聊,都去做别的事了。我不管您们怎么做,可您们得搞些大事出来。”,然后他掉头就走,这场事件,触发了 Perl6 诞生的火苗。经过十年的磨砺,2010 年 7 月 29 号,Perl6 的第一个实现版 Rakudo Star 终于发布了,这头曾经背负重担的骆驼轻装上路了。

Perl5 是用 C 写的核心,虽然已经很成熟,但核心代码太庞大,充满了各种难以理解的调用,且对多线程、unicode 的支持并不好, Perl6 相对 Perl5 做出了革命性的变革,除了更完美的支持线程、unicode 之外,可靠信号控制在一开始设计的时候就已经被加进去,新的内核更小、速度更快、外部扩展 API 更加清晰,在过去的二进制兼容问题也会被彻底解决掉。

 

START

安装 Perl6,可以从以下网址下载 http://rakudo.org/how-to-get-rakudo/, 安装步骤如下:

安装 Perl6

$ cd rakudo
$ perl Configure.pl --gen-parrot --gen-nqp
$ make
$ make install

参数–gen-parrot 实际上是在调用 svn 或 git 生成合适的 Parrot 才能编译它,Parrot 是 Perl6 相关计划书中支援 Perl6 的 Virtual Machine,也就是说, Perl 程序将在 Parrot 上执行,程序所面对的是个共通的跨平台 Virtual Machine 环境,而不用考虑您所面对的 OS 环境,就像 Java、.NET 所使用的 VM 一样。参数-gen-nqp 会下载一份 NQP,NQP 是一个小型的 Perl6 编译器,用来构建 Rakudo,Rakudo 是用于 Parrot 虚拟机上的编译器。

安装完之后,进入安装目录,并运行./Perl6,当您在 $ 后面见到 > 时,您就进入了 Rakudo 的环境中,可以执行一些东西见到 Rakudo 的响应,如:

运行 Perl6

$./perl6
>say “Hello world!”;
>Hello world!

而在 Perl5 中,运行./perl 后直接停留在当前状态,不会进入用户交互状态。

 

变量和类型

数组

Perl6 对数组和哈希的定义无需括号,如:

Perl6 中数组定义

@a = "hello", "world";
say @a;

输出:

helloworld

这里,say 函数是 Perl6 中新引入的一个函数,功能就是将一行文本打印到终端。

Hash

在 Perl6 中对哈希值的访问,键值如果用双引号则需用{}, 如果不用双引号,则需用<>, 如:

Perl6 中 Hash 定义

my %a = "first" => 1, "second" => 2, "third" => 3;
say  %a{“first”};
say  %a<second>

输出:

1
2

如果不使用=>符号定义 hash,还可以使用副词语法,如下:

副词语法

my %bar = :first(1), :second(2), :third(3);

副词语法提供了为数值命名,在 Perl6 中不仅仅用在 hash,很多地方都会用。

 

类型

在 Perl 5 中,$scalar 的标量只能包含二种东西引用或值,这值可以是任何东西,可以是整数、字符、数字、日期和您的名字,这通常是非常方便的,但并不明确。在 Perl6 中给您机会修改标量的类型 。如果您这个值比较特别,您可以直接放个类型名在 my 和 $variable 的中间。像下面的例子,是在设置值一定要是一个 Int 型的数据,来节约 cpu 判断类型的时间,和让您更少在程序上出错。

my Int $days = 24;

Perl6 提供了很多内置数据类型,最基础的有:

  • Bool : 布尔值,是枚举类型,只能是 true 或者 false。
  • Int: 整数型。
  • Array: 数组类型,通过整数索引。
  • Hash: 哈希类型,通过字符串名索引。
  • Num: 浮点数值。
  • Complex: 复杂数据类型,如虚数。
  • Pair: 将字符串名和数据对象的绑定。
  • Str: 字符串数据对象。

我们可以通过 WHAT 函数来判断数据的类型,如:

WHAT 函数

my $a=3;
say $a.WHAT

输出:

Int()

此外,我们还可以通过一些特殊操作符对数据类型进行转换,如:

数据类型转换

my $num = +(“3”);  //+()将字符转换为数值
my @arr = @(“key” => “value”);   //@()将 hash 转换为数组
my $sca = $(2..4) ;//$()将列表转换为标量,这里 sca 为列表元素个数 3
my $str = ~3; //~()将数值转换为字符
my %hash = %(“a”,”1”,”b”,”2”);//%()将列表转换为哈希

 

操作符

拼接

Perl6 中使用~进行字符串的拼接,如:

字符串拼接

my Int $num = 5;
my Str $str = “I have “ ~ $foo ~ “ chapters to write”;
say $str; //这里~会将 5 转换为 string 再拼接

输出:

I have 5 chapters to write

匹配

Perl6 的字符串匹配使用~~,如:

字符串匹配

“c” ~~ /c/;     # 返回 true, 字符”c” 匹配正则表达式/c/

控制结构

格式

Perl6 中的控制符关键字后必须有空格,否则会被解析为函数,如:

控制体格式

if($x<5) {    //错误,会调用 if 函数
}
if ( $x <5) {  //正确
}

given/when

Perl6 引入新的控制体 Given/When,它类似 c 语言中的 switch/case,如:

given/when 用法

given $guess {
when 10 { say ‘$guess is the number 10’; }
when “hello” { say ‘$guess is the string “hello”’; }
when Bool { say ‘$guess is the _oolean quantity ‘ ~ $guess; }
}

以上的代码会将 guess 变量先匹配 10,如果不是,再匹配”hello”,最后判断是否是布尔类型。

for /loop

在 Perl 5 中,提供了 foreach 的关键字,当然您也能写成 for 的关键字来实现象 C 风格的循环。在 Perl 6 中,这些全都改变了。现在 for 是专用来进行列表的迭代。foreach 就不再使用了,如:

for 用法

for 1, 2, 3, 4 { .say }

这是一个最简单清晰的语法的例子。在这并没有使用括号来包起整个列表的语句,像这种写法可以贯穿整个 Perl 6.。通常比起 Perl 5 来您没有必要写那么多的括号了。这个循环中的值会默认存到 $_ 。在这个方法调用的 say 其实就是 $_.say,注意在 Perl 6 中,您不能直接只打一个 say 的调用而不加参数,默认情况下会使用 $_ 来传参,您需要使用 .say ,要么明确的指定是 $_。

而那个 C 风格的循环处理使用了新的关键字 loop,如:

loop 用法

loop (my $i = 1; $i<= 10; $i++) {
print $i;
}

repeat/while

Perl6 引入了 repeat/while 控制体,相当于 c 语言中的 do/while,如:

repeat/while 用法

My $n = 3;
repeat {
say $n;
} while $n <3;

以上代码会执行循环体一次。

函数

定义

Perl6 在定义函数时,显示了参数,这是非常灵活的。因为它不会对参数做任何默认的处理,程序会全部传给您来进行处理,并增加返回值关键字 return,,这点更像 c 语言定义函数,如:

函数定义

sub mysub ( $x ) {
     My $y = $x/2;
      Return $y;
}

除此之外,还允许定义可选参数及参数默认值,对于可选参数需要在参数后加?, 对于定义参数默认值则直接在参数后直接加 = defaultvalue,如:

参数设置

sub mysub($first, $second?,$third = 4);

这里参数$second 是可选参数,默认值为 undef,而参数$third 是必填参数,且默认值为 4。

重载

Perl 6 还允许定义相同名字的函数,但需要参数不同,并需要加上 multi 关键字,如:

函数重载

multi sub double(Int $x) {
my $y = $x * 2;
say “Doubling an Integer $x: $y”;
return $x * 2;
}

multi sub double(Num $x) {
my $y = $x * 2;
say “Doubling a Number $x: $y”;
return $x * 2;
}

my $foo = double(5);        # Doubling an Integer 5: 10
my $bar = double(3.5);      # Doubling a Number 3.5: 7

块和闭包

在 Perl5 中,想要访问不同范围内的变量,只能通过 my、our、local 来定义变量的作用范围,而 Perl6 通过增加$OUTER 和$CALLER 使访问变量更加灵活,这里对于一个代码块来说使用$OUTER 找到上一层范围同命名的变量, 如:

$OUTER 使用

my $x = 5;
{
   my $x = 6;
   say $x;           # 6
   say $OUTER::x    # 5
}

对于函数来说,使用的是$CALLER 来找到对应的变量,如:

$CALLER 使用

my $x = 5;
mySubroutine(7);

sub mySubroutine($x) {
   say $x;         # 7
   say $CALLER::x; # 5
}

 

定义

Perl6 拥有了真正概念上的类和对象,公有变量可以使用符号,私有变量使用符号!, 并将以前的方法调用符->变为.,如:

类定义

class MyClass {
        has $!private;
        has @.public;

        # and with write accessor
        has $.stuff is rw;

        method bark {
            if self.can(‘bark’) {
                say “Something doggy”;
            }
        }
}

以上代码中,使用一个 class 的关键字定义类。如果您有学过 Perl5 的话,您能想到这有点像包(package)的变种。接下来,使用 has 的关键字来声明属性访问器方法。这个”.”的东西名叫 twigil.。Twigil 是用来告诉您指定变量的作用域。它是”属性 + 存取方法”的组合。接下来是方法的使用,并介绍使用 method 的关键字。在对象中的方法像包中的子函数,不同之处在于方法是放在类的方法列表的条目中。它还能自动取得调用者(invocant),所以您如果没有在参数列表中加入参数,它是会给自我传递过去,在 Perl 5 中需要我们显示的写 $self = shift。

对于以前在 Perl5 中使用的大部分函数都已经转换为方法,如得到字符串长度,调用 chars 方法:My $len = $string.chars 和排序数组,调用 sort 方法:Print @array.sort ;

构造函数

Perl5 的构造函数是类的子程序,它返回与类名相关的一个引用,将类名与引用相结合称为 bless 一个对象。Perl6 所有的类都使用名叫 new 的默认的构造器,它会自动的映射命名参数到属性,所有传进的参数会存到属性中,如:

构造函数

my $comer = family.new(name => 'Jack', age=>23);
say $fido.name;  # Jack

继承

Perl6 的继承直接使用 is+父类名就可以,如:

继承

class MySubClass is MyClass {
        method bark {
                say “Something wow!”;
        }
}

 

小结

我们将以上内容总结对比为如下表:

Perl6 与 Perl5 对比一览表
类别 Perl6 Perl5
命令运行 支持交互 不支持交互
数组定义 @a = “hello”, “world”; @a = (“hello”, “world”;)
哈希定义 %a = “first” => 1, “second” => 2; or
%a = :first(1),:second(2);
%a = (“first” => 1, “second” => 2);
哈希访问 %a{“first”} or %a<first> $a{“first”}
字符拼接 “hello “ ~ “ world” “hello”.”world”
匹配 “c” ~~/c/ “c” =~/c/
数据类型 Bool, Array, Int, Num, Pair,Complex, Str 等 Scalar, Array, Hash
控制结构 given/when
for foreach
loop for
repeat/while while
函数重载 参数不同,并需要加上 multi 关键字
变量作用域 my, our, local, $OUTER, $CALLER my , our, local
类定义 使用 class,支持公有变量和私有变量 使用 package
构造函数 new() 引用+bless()
方法调用 使用. 使用->
继承 is 父类名(使用的是 class) use 父类名(使用的是 package)

总结

本文从 Perl6 的诞生来由讲起,从变量、类型、操作符、控制结构、函数、类六个方面介绍了 Perl6 的改进,并给出实例,最后总结对比在 Perl5 中的差异点的使用方法。从这些改进中,可以看出 Perl6 在字符处理方面更加轻便、灵活,且从结构上成为真正意义上的面向对象语言。

转载请注明:爱开源 » Perl6 vs Perl5 之我见

您必须 登录 才能发表评论!