免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 32828 | 回复: 45

[Perl 6]Perl 5 to 6 中译版 ( 完整 ) [复制链接]

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-08 18:31 |显示全部楼层
本帖最后由 iakuf 于 2015-04-23 17:44 编辑

在本帖连续 3 周所发 "Perl 5 to 6 中译版" 都以完成, 感谢 py 的支持 ( 很多地方看不懂的英文都是问他 ). 有什么译得不好, 和错误的地方,大家回帖,我来更正.

如果想只看所有译文, 请点击上方的 "只看该作者"

想试玩, 请安装我在 Ceonts 6 上打包好的 rpm 包, 可以比较快速和简单. 直接到下面这个地址下载.
http://pan.baidu.com/s/1gdF4f2z

本文开始是以 [一系列文章] 的形式存在,为阅读方便收集整理而成

"Perl 5 to 6" - 介绍

概要

学习 Perl 6 ( 假设你已经了解 Perl 5 )
学会欣赏 Perl 6
知道为什么

描述

Perl 6 目前文档不足. 这并不奇怪, 因为编写 Perl 6 的编译器比写文档这事 ( 目前只有一个 specification 规范 ) 这个对于用户来讲更加重要多了.

不幸的是, 这意味着会让大家不太容易学习 Perl 6, 除非你是对 Perl 6 有比较深入的关注的人, 就算这样, 目前也就只能从 specification, IRC 和测试套件中学习.

这个项目, 初步给名字定为 "Perl 5 to 6"(目前我找不到更好的名字) 来填补文档空白这个事情.

这个课程都内容都会保持矮小精悍. 我会试图用很短的例子来解释 2-3 个重点. 也会解释从 Perl 5 变成 Perl 6 的改进, 这一点非常重要. 我希望你通过读这些课程学到所需要的知识.

这些内容都是 Synopses 中的, 这是 Perl 智慧的来源和汇总.

为了保证读起来方便, 每个课程会控制在不超过 200 行或者 1000 个单词 ( 当然就是个软限制 );

这个对于学习编程语言也许太短了. 但我希望是讲出语言的设计的目标, 让你看到它强大并美丽的一面, 并且不用按语言大纲就能很快的学习并使用.

IT'S NOT

这并不是一个 Perl 5 转成 Perl 6 的指南, 所以没有完整的转换列表.

文章路线图

已经在写了的和准备要写的:

00 Intro
01 Strings, Arrays, Hashes
02 Types
03 Control structures
04 Subs and Signatures
05 Objects and Classes
06 Contexts
07 Rules
08 Junctions
09 Comparisons and Smartmatching
10 Containers and Binding
11 Basic Operators
12 Laziness (-)
13 Custom Operators (-)
14 the MAIN sub
15 Twigils
16 Enums
17 Unicode (-)
18 Scoping
19 More Regexes
20 A Grammar for XML
21 Subset types
22 State of the Implementations
23 Quoting and Parsing (-)
24 Recude meta operator
25 Cross meta operator
26 Exceptions and control exceptions

( 有些不是或者目前 Rakudo 没有实现完的内容标了一个 (-))

有些东西我想写, 但我对这些的了解还不够:

Macros
Meta Object Programming
Concurrency
IO

这个东西, 我想提到, 但不知道放在那个地方合适

.perl method

我也会更新这些课程, 也保证他们不是太落伍了.

AUTHOR

Moritz Lenz, http://perlgeek.de/, moritz@faui2k3.org

LINKS

Other documentation efforts can be found on http://perl6.org/documentation/.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2014-05-08 18:38 |显示全部楼层
支持。期待连载。

我因为懒都从来没翻译过东西

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-08 22:34 |显示全部楼层
"Perl 5 to 6" 第 1 课 - 字符串、数组和哈希

概要

  1. my $five = 5;
  2. print "an interpolating string, just like in perl $five\n";
  3. say 'say() adds a newline to the output, just like in perl 5.10';

  4. my @array = 1, 2, 3, 'foo';
  5. my $sum = @array[0] + @array[1];
  6. if $sum > @array[2] {
  7.     say "not executed";
  8. }
  9. my $number_of_elems = @array.elems;     # 或者使用 +@array
  10. my $last_item = @array[*-1];

  11. my %hash = foo => 1, bar => 2, baz => 3;
  12. say %hash{'bar'};                       # 2
  13. say %hash<bar>;                         # 同上, 会自动的加上双引
  14. # 在这使用 %hash{bar} 是错误的
  15. # 没加引号的字符, 这会试着调用 bar 函数. 但这不存在
复制代码
描述

Perl 6 这些部分很象 Perl 5 - 只会变得更加友好. 声明的语句还是以分号终止. 在代码块中最后的语句和在行结束的右大括号的分号终止符是可选的.

变量仍然以记号 (象 $, @, %)开头.

字符串

字符串是用双引号包起来 ( 插值的情况下 ), 或者使用单引号. 反斜杠转义的工作方式和 Perl 5 中一样.

然而插值规则已经改变了一点. 看下面插值
  1. my $scalar = 6;
  2. my @array = 1, 2, 3;
  3. say "Perl $scalar";         # 'Perl 6'
  4. say "An @array[]";          # 'An 1 2 3', a so-called "Zen slice"
  5. say "@array[1]";            # '2'
  6. say "Code: { $scalar * 2 }" # 'Code: 12'
复制代码
数组和哈希只有当后面跟索引的时候才会插值 ( 或者方法调用, 象 "some $obj.method()" ), 空索引会给整个数据结构做插值操作.

当出现了一个花括号时会执行花括号中的代码给结果进行插值操作.

数组

数组还是以 @ 标记开始. 并且他们总是这样 ( 在 Perl 5 中元素文章不是 @ 是 $ ), 就算访问数组中的元素也是使用 @ 开头. ie. 这个索引需要存在, 这个对新手学习就不在会晕了.
  1. my @a = 5, 1, 2;            # 不再需要括号
  2. say @a[0];                  # 没错, 是以 @ 开头
  3. say @a[0, 2];               # 数组切片也能正常工作
复制代码
列表的构造是通过逗号, 不在需要括号. 1, 是一个列表, (1) 不是.

既然一切都是对象,你可以调用数组的方法:
  1. my @b = @a.sort;
  2. @b.elems;                   # 成员元素数量
  3. if @b > 2 { say "yes" }     # 仍然可以这样
  4. @b.end;                     # 最后一个索引的位置, 替换 $#array
  5. my @c = @b.map({$_ * 2 });  # 没错, map 也是个方法调用
复制代码
下面的方法是替换老的 qw/../ 来进行字符数组的构造:

  1. my @methods = <shift unshift push pop end delete sort map>;
复制代码
哈希

Perl 6 在列表上下文时哈希是列表对. 列表对可以做一些其它的事情, 它可以是子函数的名字, 稍后详述.

就象数组使用的开头的标记不变, 哈希也是一样. 当你创建索引时使用 % 开头. 并且 hash 也有自己的方法调用.
  1. my %drinks =
  2.     France  => 'Wine',
  3.     Bavaria => 'Beer',
  4.     USA     => 'Coke';

  5. say "The people in France love ",  %drinks{'France'};
  6. my @countries = %drinks.keys.sort;
复制代码
注意, 当你访问哈希的元素是通过 %hash{...}, 这个 key 不会象 Perl 5 自动的加引号. 所以 %hash{foo} 并不能访问到索引 "foo" 的元素. 这会调用 foo() 的函数. 需要自动的对字符加引号就需要如下这种不同的语法:

  1. say %drinks<Bavaria>;
复制代码
最后的注意事项

大多内置的方法, 既作为一种方法也可以做为 sub 调用. 所以你可以写在 sort @array 或者 @array.sort.

最后, 你需要知道这 [..] 和 `{...}' 这二个东西, 现在它们只是方法调用的特殊语法, 在这不是绑定数组和哈希. 这意味着, 他们也不会依赖于特定的前缀符号.
  1. my $a = [1, 2, 3];
  2. say $a[2];          # 3
复制代码
这意味着, 我们不需要特殊的引用和解引用的语法, 并且您可以创建能够同时充当数组, 哈希和 sub 子函数的对象.

另请参阅

http://perlcabal.org/syn/S02.html, http://perlcabal.org/syn/S29.html

论坛徽章:
1
未羊
日期:2014-09-08 22:47:27
发表于 2014-05-09 09:03 |显示全部楼层
很好,谢谢

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-09 10:37 |显示全部楼层
"Perl 5 to 6" Lesson 02 - 类型

概要
  1. my Int $x = 3;
  2. $x = "foo";         # error
  3. say $x.WHAT;        # 'Int()'

  4. # 类型检查
  5. if $x ~~ Int {
  6.     say '$x contains an Int'
  7. }
复制代码
描述

Perl 6 中有了类型这东西. 在 Perl 6 中任何东西都是对象, 都自己的类型. 变量虽然可以有类型的限制, 并他们并不是必需的.

有一些基本的常用类型, 你必须知道的:
  1. 'a string'      # Str
  2. 2               # Int
  3. 3.14            # Rat (rational number)
  4. (1, 2, 3)       # Seq
复制代码
全部 "标准" 的内置类型都是大写字母开头. 全部 "标准" 类型继承 "Any", 所有的类型都继承 Mu.

你可以限制变量存储的值所用的类型, 只要你在声明的时候指定变量类型.
  1. my Numeric $x = 3.4;
  2. my Int @a = 1, 2, 3;
复制代码
如果试图给存一个错误的类型的值到变量会提示出错.

类型的声明也合适于数组的包含的元素内容, 所以 my Str @s 是指定这个数组只能包含字符串.

有某些类型可以代表更加具体的类型, 象 integers (type Int), rationals (type Rat) 和 浮点数 (type Num) 这些都是 Numeric 类型.
自省

你可以通过调用 .WHAT 方法了解对象的详细类型.
  1. say "foo".WHAT;     # Str()
复制代码
如果你想检查一些东西的类型, 有不同的方式, 也需要考虑到类型的继承, 所以建议使用下面的方法:
  1. if $x ~~ Int {
  2.     say 'Variable $x contains an integer';
  3. }
复制代码
动机

这个类型系统让我们很容易了解所有的细节. 为什么我们需要类型, 使用他们也有很多理由:

[程序更加安全]

如果你声明了一些东西是特定的类型, 你就可以肯定的在上面执行某些操作, 并不需要检查它是什么.

[优化]

当你在编译的时候有类型的信息, 可以执行更多的优化, Perl 6 原则上不一定比 C 慢.

[扩展性]

当有类型信息时, 使用 multiple dispatch 时更加容易细化特定的操作.

另请参阅

http://perlcabal.org/syn/S02.html#Built-In_Data_Types,

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-09 11:06 |显示全部楼层
自从元素访问可以使用 % 我想会有很多人学习的时候不会晕掉了. 象 PHP 之类都没有标量和列表环境变符号这种东西,这个比较影响人学习和使用这个. 类型机制很多时候也是很方便的.反正你真不想写时,还是可以不写的.

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-09 12:55 |显示全部楼层
"Perl 5 to 6" Lesson 03 - 基本的控制结构

概要
  1. if $percent > 100  {
  2.     say "weird mathematics";
  3. }
  4. for 1..3 {
  5.     # 在循环中使用 $_
  6.     say 2 * $_;
  7. }
  8. for 1..3 -> $x {
  9.     # 有明确的循环变量
  10.     say 2 * $x;
  11. }

  12. while $stuff.is_wrong {
  13.     $stuff.try_to_make_right;
  14. }

  15. die "Access denied" unless $password eq "Secret";
复制代码
描述

大多 Perl 5 的控制结构和 Perl 6 颇为相似, 如果从视觉差异上来讲, 你可以见到在使用 if, while, for 之类不后需要一对括号.

为什么没有括号了, 当任何标识符后面紧跟着 (无空格) 左括号时很容易被解析成子程序调用. 所以 if($x < 3) 很容易理解变成调用 if 函数的调用. 所以这样更加安全, 还不需要写括号.
分支控制

if 功能大部分没在变化, 仍然可以添加 elsif 和 else 分支. unless 仍然存在,但是在 unless 之后没有了 else 分支.
  1. my $sheep = 42;
  2. if $sheep == 0 {
  3.     say "How boring";
  4. } elsif $sheep == 1 {
  5.     say "One lonely sheep";
  6. } else {
  7.     say "A herd, how lovely!";
  8. }
复制代码
你现在还是可以使用 if 和 unless 做语句修饰, 即后声明方式来使用.
  1. say "you won" if $answer == 42;
复制代码
循环

你可以通过 next 和 last 来控制循环就象 Perl 5 一样.

在这 for 循环现在只用于遍历列表. 默认是操作 $_ 变量, 除非显式的指出变量名.
  1. for 1..10 -> $x {
  2.     say $x;
  3. }
复制代码
在这的 -> $x { ... } 是叫做 "pointy block" 这就象一个匿名的子函数或者 lisp 中的 lambda 操作.

你也可以使用一个以上的循环变量:
  1. for 0..5 -> $even, $odd {
  2.     say "Even: $even \t Odd: $odd";
  3. }
复制代码
这也是遍历哈希值的好方法:
  1. my %h = a => 1, b => 2, c => 3;
  2. for %h.kv -> $key, $value {
  3.     say "$key: $value";
  4. }
复制代码
这个 C-style 的 for 循环现在叫做 loop ( 这是唯一需要括号的循环结构 ):
  1. loop (my $x = 2; $x < 100; $x = $x**2) {
  2.     say $x;
  3. }
复制代码
另请参阅

[http://perlcabal.org/syn/S04.html#Conditional_statements]

论坛徽章:
1
处女座
日期:2014-03-28 10:11:00
发表于 2014-05-09 18:29 |显示全部楼层
   赞凯哥!

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-12 15:57 |显示全部楼层
本帖最后由 iakuf 于 2014-05-12 16:00 编辑

"Perl 5 to 6" Lesson 04 - 子函数和参数

概要
  1. # Perl 5 中传参的方式
  2. sub print_arguments {
  3.     say "Arguments:";
  4.     for @_ {
  5.         say "\t$_";
  6.     }
  7. }

  8. # 参数在这个地方使用固定的位置和指定的类型:
  9. sub distance(Int $x1, Int $y1, Int $x2, Int $y2) {
  10.     return sqrt ($x2-$x1)**2 + ($y2-$y1)**2;
  11. }
  12. say distance(3, 5, 0, 1);

  13. # 默认参数
  14. sub logarithm($num, $base = 2.7183) {
  15.     return log($num) / log($base)
  16. }
  17. say logarithm(4);       # 这会给第二个参数使用默认的值
  18. say logarithm(4, 2);    # 明确的指名第二个参数

  19. # 命名参数

  20. sub doit(:$when, :$what) {
  21.     say "doing $what at $when";
  22. }
  23. doit(what => 'stuff', when => 'once');  # 'doing stuff at once'
  24. doit(:when<noon>, :what('more stuff')); # 'doing more stuff at noon'
  25. # illegal: doit("stuff", "now")
复制代码
描述

子函数是使用 sub 关键字来声明, 并且有形式参数列表, 就象 C, Java 和一些其它的语言. 这些参数有可选的类型约束.

参数默认是只读的. 可通过 "traits" 来修改成可以读写.
  1. sub try-to-reset($bar) {
  2.     $bar = 2;       # 禁止修改参数
  3. }

  4. my $x = 2;
  5. sub reset($bar is rw) {
  6.     $bar = 0;         # 可以修改
  7. }
  8. reset($x); say $x;    # 0

  9. sub quox($bar is copy){
  10.     $bar = 3;
  11. }
  12. quox($x); say $x    # still 0
复制代码
参数可以在后面增加一个问号来标记是否可选.
  1. sub foo($x, $y?) {
  2.     if $y.defined {
  3.         say "Second parameter was supplied and defined";
  4.     }
  5. }

  6. sub bar($x, $y = 2 * $x) {
  7.     ...
  8. }
复制代码
命名参数

当你象这样调用子函数: my_sub($first, $second). 在这的这个 $first 参数会绑定到第一个正式的参数, $second 会传递给第二个参数..等等, 这就是所谓的位置 "positional".

有时, 我们希望使用更加容易记住的名字, 而不是数字之类. 这是为什么使用命名参数的原因:
  1. my $r = Rectangle.new(
  2.         x       => 100,
  3.         y       => 200,
  4.         height => 23,
  5.         width  => 42,
  6.         color  => 'black'
  7. );
复制代码
当你看到这样这些名字, 你马上知道参数具体是什么含义。

要定义一个命名参数, 你只需要给 : 放在参数之前:
  1. sub area(:$width, :$height) {
  2.     return $width * $height;
  3. }
  4. area(width => 2,  height => 3);
  5. area(height => 3, width => 2 ); # 同上
  6. area(:height(3), :width(2));    # 同上
复制代码
这最后一个例子使用的是叫 colon pair syntax 的语法. 当给使用 :draw-perimeter 给其赋布尔值的时候, 你什么都不写默认是 True, 当想给一个参数赋值为布尔类型的 FALSE 的时候,也不需要写明 0,而是用以下格式:!transparent

  1. :draw-perimeter                 # same as "draw-perimeter => True"
  2. :!transparent                   # same as "transparent => False"
复制代码
在命名参数的声明, 变量也被用来作为参数. 您可以使用不同的名称:
  1. sub area(:width($w), :height($h)) {
  2.     return $w * $h;
  3. }
  4. area(width => 2,  height => 3);
复制代码
Slurpy 参数

你给你的 sub 参数的时候, 有时你并不知道所有的参数个数. 你可以定义一种称作 slurpy 参数来提交任何所剩余的参数:
  1. sub tail ($first, *@rest){
  2.     say "First: $first";
  3.     say "Rest: @rest[]";
  4. }
  5. tail(1, 2, 3, 4);           # "First: 1\nRest: 2 3 4\n"
复制代码
对于哈希, 命名的 slurpy 参数定义是使用有 * 号前缀的哈希参数:
  1. sub order-meal($name, *%extras) {
  2.     say "I'd like some $name, but with a few modifications:";
  3.     say %extras.keys.join(', ');
  4. }

  5. order-meal('beef steak', :vegetarian, :well-done);
复制代码
Interpolation

默认数组是不能插入到参数的列表中. 所以这不同于 Perl 5 的写法.
  1. sub a($scalar1, @list, $scalar2) {
  2.     say $scalar2;
  3. }

  4. my @list = "foo", "bar";
  5. a(1, @list, 2);                  # 2
复制代码
这也意味着, 默认的情况下你不能使用一个列表做为参数列表:
  1. my @indexes = 1, 4;
  2. say "abc".substr(@indexes)       # 不能实现你想做的
复制代码
( 实际的情况是, 这的第一个参数需要是一个 Int, 需要被强制转换成 Int, 所以你可以写成 "abc."substr(@indexes.elems) 来放在第一位 ).

当然, 你也可以使用前缀 | 来完成所需的行为
  1. say "abcdefgh".substr(|@indexes) #  结果 bcde, 等同于 "abcdefgh".substr(1, 4)
复制代码
Multi Subs

实际上, 你其实可以定义多个 sub 来使用相同的名字, 但接收不同的参数列表:
  1. multi sub my_substr($str) { ... }                          # 1
  2. multi sub my_substr($str, $start) { ... }                  # 2
  3. multi sub my_substr($str, $start, $end) { ... }            # 3
  4. multi sub my_substr($str, $start, $end, $subst) { ... }    # 4
复制代码
现在, 当你调用这个 sub 时, 所述的参数会有一个匹配上并选择使用的.

这个 multis 并不只是可以工作在参数数量不等的情况上, 也可以用于在不同的参数类型的时候:
  1. multi sub frob(Str $s) { say "Frobbing String $s"  }
  2. multi sub frob(Int $i) { say "Frobbing Integer $i" }

  3. frob("x");      # Frobbing String x
  4. frob(2);        # Frobbing Integer 2
复制代码
动机

没有人会怀疑明确的子函数参数的实用性: 少打字, 少重复的参数检查, 更多的安全文档代码.

这些功能还有益于自省. 例如, 当传递给一个块或者子函数使用 Array.sort, 并且这段代码预期只有一个参数, 完成 Schwartzian 转换( 见 http://en.wikipedia.org/wiki/Schwartzian_transform ) 是自动的 - 这些功能在 Perl 5 中不太可能, 由于少了明确的参数, 意味着排序代码块永远不知道有多少个参数.

Multi subs 这个功能也非常有用, 因为它可以使用新类型来覆盖内建命令. 比如, 你想有一个版本的 Perl6 是本地化上来正确处理土耳其字符串,这对大小写转换是使用的不同寻常的规则时非常好用.

这时, 不需要修改语言本身. 你只需要加入一个新的 TurkishStr, 并为原生的函数加入一个 multi subs:
  1. multi uc(TurkishStr $s) { ... }
复制代码
现在, 所有这个对字符串处理就会自动对应他们的语言类型, 然后你就可以使用 uc 函数象内置的函数一样.

由于操作也可以使用 subs, 所以这些改进操作是可以正常工作的.

另请参阅

http://perlcabal.org/syn/S06.html

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2014-05-12 16:02 |显示全部楼层
"Perl 5 to 6" Lesson 05 - 对象和类

概要
  1. class Shape {
  2.     method area { ... }    # literal '...'
  3.     has $.colour is rw;
  4. }

  5. class Rectangle is Shape {
  6.     has $.width;
  7.     has $.height;

  8.     method area {
  9.         $!width * $!height;
  10.     }
  11. }

  12. my $x = Rectangle.new(
  13.         width   => 30.0,
  14.         height  => 20.0,
  15.         colour  => 'black',
  16.     );
  17. say $x.area;                # 600
  18. say $x.colour;              # black
  19. $x.colour = 'blue';
复制代码
描述

Perl 6 比起 Perl 5 更加好的地方在于强大完整的对象模型. 它有可以通过关键字创建类, 角色, 属性和方法, 并可以封装私有属性和方法. 事实上, 这个很象 Perl 5 中的 Moose( 这东西的灵感来自 Perl 6 的对象系统).

有两种方法来声明类
  1. class ClassName;
  2. # 类定义放在这里
复制代码
第一个方法是文件一开始就有一个 class ClassName; 并一直延伸到文件的末尾. 第二种方法是类名后跟一个块, 块中所有的内容都被认为是当前类的定义.
  1. class YourClass {
  2.     # 类定义放在这里
  3. }
  4. # 更多的类和其它的代码
复制代码
方法 Methods

方法定义是使用 method 关键字. 在方法内部可以使用 self 来指向对象本身.

你也可以通过参数来给调用者一个不同的名字. 并附加一个冒号 : 来给它.

Public 公有方法可以通过语法 $object.method 来调用, 有参数的话,可以使用 $object.method(@args) 或者 $object.method: @args 来调用.
  1. class SomeClass {
  2.     # these two methods do nothing but return the invocant
  3.     method foo {
  4.         return self;
  5.     }
  6.     method bar(SomeClass $s: ) {
  7.         return $s;
  8.     }
  9. }
  10. my SomeClass $x .= new;
  11. $x.foo.bar                      # same as $x
复制代码
( 这个 my SomeClass $x .= new 其实是 my SomeClass $x = SomeClass.new 的简写. 这之所以正常工作是因为, 这同时也是类型声明, 声明这个变量的类型是一个 SomeClass 的 "typo object", 这个类型对象就表示类的对象)

对象中的方法可以象子函数一样接收参数.

Private 的私有方法可以通过 method !methodname 的方式来声明, 调用通过 self!method_name.
  1. class Foo {
  2.     method !private($frob) {
  3.         return "Frobbed $frob";
  4.     }

  5.     method public {
  6.         say self!private("foo");
  7.     }
  8. }
复制代码
私有的方法并不能从类的外面调用.

属性 Attributes

属性声明通过 has 关键字, 有个 "twigil" 的功能 ( 单词前有二个符号, 第二个符号在 Perl 6 中叫 twigil 有特定的意义 ). 对于私有属性, 这是使用的 ! 符号, 对于公有属性, 这是使用 .. 公共属性实际上是有公有的访问权限的私有属性. 所以, 它不能修改, 如果你想修改时, 就需要使用 ! 来访问实际的属性而不是使用存取器 ( 除非它被标记为 is rw ).
  1. class SomeClass {
  2.     has $!a;
  3.     has $.b;
  4.     has $.c is rw;

  5.     method set_stuff {
  6.         $!a = 1;    # ok, 这时才能写入类的属性
  7.         $!b = 2;    # 同上
  8.         $.b = 3;    # ERROR, 不能写, 因为这是私有只读的属性
  9.     }

  10.     method do_stuff {
  11.         # 你可以使用私有的名字来替换掉公有的那个名字
  12.         # $!b and $.b are really the same thing
  13.         return $!a + $!b + $!c;
  14.     }
  15. }
  16. my $x = SomeClass.new;
  17. say $x.a;       # ERROR!
  18. say $x.b;       # ok
  19. $x.b = 2;       # ERROR!
  20. $x.c = 3;       # ok
复制代码
继承 Inheritance

继承是通过 is 这个关键字.
  1. class Foo is Bar {
  2.     # 类 Foo  继承类 Bar
  3.     ...
  4. }
复制代码
根据常用的继承规则 - 方法会先直接检查自己的类型, 如果失败, 操作父类 ( 递归 ). 同样的, 一个子类的类型是否符合父类:
  1.     class Bar { }
  2.     class Foo is Bar { }
  3.     my Bar $x = Foo.new();   # ok, since Foo ~~ Bar
复制代码
在这个例子中 $x 的类型是 Bar, 它允许分配一个对象类型 Foo 给它, 因为每天个 "Foo 都是 Bar 之下".

类也可以继承多个其它的类:
  1. class ArrayHash is Hash is Array {
  2.     ...
  3. }
复制代码
尽管多重继承会附加很多问题, 人们通常会建议反对这么使用. 所以角色往往是一个更安全的选择.

角色 Roles

现实的世界是不分层, 所以有时很难给一切都使用层次结构继承. 这也是为什么 Perl 6 中有角色的原因之一. 角色和类十分类似, 除了你不能由角色直接创建对象, 也不能使用相同的名字组成. 相同方法名的角色会互相混淆发生冲突, 但类就不会, 因为类是包含有继承关系的, 可以很好的解决这种命名冲突.

虽然类主要针对的是类型一致性, 但角色才是在 Perl6 的代码重用的主要手段。
  1. role Paintable {
  2.     has $.colour is rw;
  3.     method paint { ... }
  4. }
  5. class Shape {
  6.     method area { ... }
  7. }

  8. class Rectangle is Shape does Paintable {
  9.     has $.width;
  10.     has $.height;
  11.     method area {
  12.         $!width * $!height;
  13.     }
  14.     method paint() {
  15.         for 1..$.height {
  16.             say 'x' x $.width;
  17.         }
  18.     }
  19. }

  20. Rectangle.new(width => 8, height => 3).paint;
复制代码

另请参阅


http://perlcabal.org/syn/S12.html
http://perlcabal.org/syn/S14.html
http://www.jnthn.net/papers/2009-yapc-eu-roles-slides.pdf
http://en.wikipedia.org/wiki/Perl_6#Roles
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP