免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: iakuf
打印 上一主题 下一主题

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

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
31 [报告]
发表于 2014-05-27 10:03 |只看该作者
"Perl 5 to 6" Lesson 23 - 引号和解析

概要
  1. my @animals = <dog cat tiger>
  2. # or
  3. my @animals = qw/dog cat tiger/;
  4. # or

  5. my $interface = q{eth0};
  6. my $ips = q :s :x /ifconfig $interface/;

  7. # -----------

  8. sub if {
  9.     warn "if() calls a sub\n";
  10. }
  11. if();
复制代码
描述

引号

Perl 6 对引号字符的处理有强大的机制, 你可以对你想要处理的字符串的特性进行精确的控制.

Perl 5 中有单引号, 双引号和 qw(...) ( 单引号, 按分割的空格 ) 和形式上就是单引号和双引号的同义的 q(..) 与 qq(...).

Perl 6 又定义了一个名为 Q 的引号操作来修饰变量. 这 :b ( 反斜杠 ) 修饰符让 \n 之类可以让反斜杠插值, 这个 :s 修饰符可以让标量进行插值. 这个 :c 可以让闭包的函数进行插值 ("1 + 2 = { 1 + 2 }"), :w 用于象 qw/.../ 一样分割单词.

你可以任意组合这些修饰符. 例如, 你也许想 qw/../ 只插标量, 但没其它的? 没问题:
  1. my $stuff = "honey";
  2. my @list = Q :w :s/milk toast $stuff with\tfunny\nescapes/;
  3. say @list[*-1];                     # prints with\nfunny\nescapes
复制代码
下面是修饰符可用的列表, 基本大部分直接来自 S02 , 所有的这些有很长的名字, 我这个地方省略了.

  1. 特性:
  2.     :q          内插 \\, \q 和 \'
  3.     :b          其他的反斜杠转义序列 \n, \t
  4. 操作:
  5.     :x          执行 shell 命令, 返回其结果
  6.     :w          分割空格
  7.     :ww         分割空格, 使用引号保护
  8. 变量内插:
  9.     :s          内插值 scalars   ($stuff)
  10.     :a          内插值 arrays    (@stuff[])
  11.     :h          内插值 hashes    (%stuff{})
  12.     :f          内插值 functions (&stuff())
  13. 其它:
  14.     :c          内插闭包 closures  ({code})
  15.     :qq         插值下面这些 :s, :a, :h, :f, :c, :b
  16.     :regex      解析正则
复制代码
还有一些短的形式:
  1. q       Q:q
  2. qq      Q:qq
  3. m       Q:regex
复制代码
你也可以省略第一个冒号 : 如果使用引号的简短形式:
  1. symbol      short for
  2. qw          q:w
  3. Qw          Q:w
  4. qx          q:x
  5. Qc          Q:c
  6. # and so on.
复制代码
注意, 有一种形式不能工作, 有些 Perl 5 的程序员容易搞错: 你并不能在 Perl 6 中写 qw(...) 这个圆括号. 它现在是插值调用子函数叫 qw.

解析

解析开始发挥作用时: 象 identifier(...) 这种都会解析成子函数调用.
  1. if($x<3)
复制代码
它会解析成调用子函数 if. 你可以用空格来防止歧义:
  1. if ($x < 3) { say '<3' }
复制代码
或者干脆省略括号:
  1. if $x < 3 { say '<3' }
复制代码
这也意味着 Perl 6 没有关键字, 其它象 use 或 if 关键字, 这也只是特定作用的特殊的语法.

动机

引号修饰符的各种组合都已经在内部使用, 例如 q:w 用于解析 <...>, 和 :regex 用于 m/.../.

这些暴露给用户, 可以获得非常好的灵活性, 并且可以非常容易的编写宏, 使用提供的引号的语义实现成快捷方式.

当你限制关键字的特性, 你会有很多向后兼容的麻烦, 如果你想改变一个关键字的话.

另请参阅

http://perlcabal.org/syn/S02.html#Literals

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
32 [报告]
发表于 2014-05-27 11:23 |只看该作者
"Perl 5 to 6" Lesson 24 - Reduction 元操作

概要
  1. say [+] 1, 2, 3;    # 6
  2. say [+] ();         # 0
  3. say [~] <a b>;      # ab
  4. say [**] 2, 3, 4;   # 2417851639229258349412352

  5. [\+] 1, 2, 3, 4     # 1, 3, 6, 10
  6. [\**] 2, 3, 4       # 4, 81, 2417851639229258349412352

  7. if [<=] @list {
  8.     say "ascending order";
  9. }
复制代码
Description

这个 reduction 的元操作 [...] 可以放入所有的相关的缀操作符, 并把它变成一个列表操作符. 相当于给在这个操作符后面的列表中所有的元素进行前面的缀操作符的操作. 所以象 [op] $i1, $i2, @rest 返回的结果和你写的 $i1 op $i2 op @rest[0] op @rest[1] ... 是相同的.

这个东西非常强大, 你可要使用加 + 操作符就可以实现 sum 的功能, 使用 ~ 放到这个中就能实现 join ( 使用空分隔 ) 等等. 这个有点类似 List.reduce 的功能, 如果你有一些接触到函数式编程, 你可能知道 foldl 和 foldr ( 在 Lisp 和 Hashell 中有 ). 不同处在于 [...] 会涉及到其中的缀操作符的结合性, 所以 [/] 1, 2, 3 会解释成 (1 / 2) / 3 ( 左结合性 ), [**] 1, 2, 3 可以正常的处理成 1 ** (2**3) ( 右结合性 ).

就象其它的操作符一样, 在操作符中间是禁止出现空格, 所以你可以写 [+], 但你不能写 [ + ].

由于比较操作符可串连, 你也可以这样写
  1. if    [==] @nums { say "all nums in @nums are the same" }
  2. elsif [<]  @nums { say "@nums is in strict ascending order" }
  3. elsif [<=] @nums { say "@nums is in ascending order"}
复制代码
你甚至可以没有赋值操作符:
  1. my @a = 1..3;
  2. [=] @a, 4;          # same as @a[0] = @a[1] = @a[2] = 4;
复制代码
注意这个地方 [...] 总是返回标量, 所以 [,] @list 其实和 [@list] 是一样的.
取得过程中分片的结果

这个操作符有一种特殊形式使用反斜杠象 [\+]. 它会返回列表的运算的结果的列表的每一部分. 所以 [\+] 1..3 返回的列表是 1, 1+2, 1+2+3, 这个结果当然是 1, 3, 6.
  1. [\~] 'a' .. 'd'     # <a ab abc abcd>
复制代码
这个右结合性的操作符是从右到左的列表结果, 所以你可以取得象下面一样的结果:
  1. [\**] 1..3;         # 3, 2**3, 1**(2**3), which is 3, 8, 1
复制代码
多个 reduction 的操作符也可以绑定:
  1. [~] [\**] 1..3;     # "381"
复制代码
动机

程序员是懒惰的, 所以我们并不想我们花了很多时间写了个循环, 其中只放一行用于操作列表所有元素的二元运算符.

List.reduce 也可以做类似的事情, 但它并不是简洁的元操作符 ( [+] @list 比起@list.reduce(&infix:<+>)` ), 注意要小心的的运算符的结合性.

If you're not convinced, play a bit with it (pugs mostly implements it), it's real fun.

另请参阅

[http://perlcabal.org/syn/S03.html#Reduction_operators], [http://www.perlmonks.org/?node_id=716497]

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
33 [报告]
发表于 2014-05-28 10:37 |只看该作者
"Perl 5 to 6" Lesson 25 - Cross 元操作符

概要
  1. for <a b> X 1..3 -> $a, $b {
  2.     print "$a: $b   ";
  3. }
  4. # output: a: 1  a: 2  a: 3  b: 1  b: 2  b: 3

  5. .say for <a b c> X 1, 2;
  6. # output: a1\n a2\n b1\n b2\n c1\n c2\n
  7. # (with real newlines instead of \n)
复制代码
描述

这个 cross 操作符 X 用于返回两个或多个列表的笛卡儿积, 这表示它会返回所有可能的元组, 其中第一个元素是第一个列表中的元素,第二元素是第二个列表中的元素等..

如果有另一个操作符放在 X 之后, 这个操作符会被运用到所有的元组元素上, 它的结果也会相应换成这样, 所以 1, 2 X+ 3, 6 会返回 1+3, 1+6, 2+3, 2+6 的操作结果 4, 7, 5, 8.

动机

这个很常见的操作, 常常人们必须遍历两个或两个以上列表的所有可能的组合, 以及交叉其它操作符压缩成的单次迭代, 从而大大简化程序, 并只要使用一行缩进就搞定了.

使用这些元操作符有时不再需要进行循环.

另请参阅

[http://perlcabal.org/syn/S03.html#Cross_operators]

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
34 [报告]
发表于 2014-05-28 10:45 |只看该作者
"Perl 5 to 6" Lesson 26 - 异常和异常控制

概要
  1. try {
  2.     die "OH NOEZ";

  3.     CATCH {
  4.         say "there was an error: $!";
  5.     }
  6. }
复制代码
描述

异常在 Perl 6 中是正常的正常控制流的一部分.

异常隐含着错误 ( 如除以零, 调用不存在的方法, 类型检查失败 ) 或者通过显示的调用 die 之类其它的产生的异常.

当异常发生时, 程序会在所有的函数中寻找相关的 CATCH 关键字或 try 代码段. 如果没有 catch 和 try 被找到, 程序退出, 这个时候可能会打印出一些错误提示但更可能是不会的. 如果 catch 或 try 被找到了, 错误信息会被存在特殊变量 $! 中, catch 中的内容会被执行. 另外, 当只有一个 try 代码段而没有对应的 catch 的时候, try 代码段会返回 undef.

到目前为止讲的异常处理都还比较常规, 但错误处理对程序来说是很复杂的, 有的时候甚至一个普通的函数返回 "return" 也会抛出异常. 这种情况被叫做 "control exceptions",可以用 CONTROL 块获取到, 或是在每个 routine 定义的时候捕获到。

看下面这个例子:
  1. use v6;
  2. my $block = -> { return "block"; say "still here" };

  3. sub s {
  4.     $block.();
  5.     return "sub";
  6. }

  7. say s();
复制代码
这的 return "block" 会抛出一个控制异常, 使其不仅退出当前块 ( 因此不会在屏幕上打印 "still here" ), 还会退出子函数, 这时会补 sub s... 的声明捕捉. 这是有效返回是字符串, 它被做为返回值, 并在最后一行的 say 来打印出来.

嵌入调用 $block.() 中放入 $block.() 块或者增加 CONTROL { ... } 块到程序的主体中可以使其捕获到异常.

和其它编程语言不一样的, 这个 CATCH/CONTROL 块是工作在错误被捕获( 不是在外面 ) 的范围内, 这会完全进入词法变量, 这使得更容易产生有用的错误信息, 并且可以防止在处理错误之前, 这个块就被 DESTROY 掉.

不抛出异常

Perl 6 中全部包含了多线程的想法, 尤其是自动并行化. 为了确保不是所有的线程要遭受从一个单独的线程中止而中断, 发明了一种 "软" 异常.

当一个函数调用 fail($obj), 它会返回一个特定的 undef 的值, 其实是包含了 $obj ( 通常是一个错误消息 ) 和 back trace ( 文件名和行号 ). 进程需要在外面对这个特定的未定义的值进行检查, 如果它是未定义的来由自己控制异常抛出.
  1. my @files = </etc/passwd /etc/shadow nonexisting>;
  2. my @handles = hyper map { open($_) }, @files;
复制代码
在这个例子中 hyper 操作会让 map 尽可能并行的做自己所要做的动作. 当打开一个不存在的文件失败时, 普通的 die "No such file or directory" 会中止所有其它的 open 操作. 但如果使用了失败的打开后启用 fail("No such file or directory") 来替换 die 操作, 它会给调用者让其来检查包含的 @handles, 并且仍然可以访问完整的错误消息.

如果你不喜欢 "软" 异常的处理, 你可以 use fatal; 这会让程序从一开始就给全部的异常的 fail() 变成立即抛出的所有异常.

动机

一个好的编程语言需要异常来处理错误的条件. 总是检查返回值是一种折磨也容易忘记.

由于传统的异常处理可能会影响隐式的并行性. 所以我们需要一个二全其美的解决方案: 不会立即 kill 掉一切, 并且仍然不会丢失任何信息.

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
35 [报告]
发表于 2014-05-29 10:18 |只看该作者
"Perl 5 to 6" Lesson 27 - 常用的 Perl 6 数据处理的习惯用法

概要
  1. # 从键和值的列表创建哈希
  2. # 方案 1: slices 切片
  3. my %hash;
  4. %hash{@keys} = @values;

  5. # 方案 2: meta operators 元操作
  6. my %hash = @keys Z=> @values;

  7. # 从数组创建哈希, 给每个数组元素 true 值:
  8. my %exists = @keys Z=> 1 xx *;

  9. # 限制值的范围, 这是 0 .. 10.
  10. my $x = -2; say 0 max $x min 10;

  11. # dubugging: 给容器中的值 dump 出来, 包含名字, 输出到标准错误
  12. note :$x.perl;

  13. # 不区分大小写排序
  14. say @list.sort: *.lc;

  15. # 强制属性
  16. class Something {
  17.     has $.required = die "Attribute 'required' is mandatory";
  18. }

  19. Something.new(required => 2); # no error
  20. Something.new() # BOOM
复制代码
描述

学习一门语言只靠规范是不够的, 它必须在生产中使用. 相反, 你们需要知道如何解决具体问题. 常用的处理模式叫 idioms 惯用用法, 可以帮助我们在每次有问题的时候不用重新发明轮子.

所以这是一些常用的 Perl 6 的习惯用法来操作数据结构.

哈希
  1. # 从键和值的列表创建哈希
  2. # 方案 1: slices 切片
  3. my %hash;
  4. %hash{@keys} = @values;

  5. # 方案 2: meta operators 元操作
  6. my %hash = @keys Z=> @values;
复制代码
这个第一个方案和你的 Perl 5 是基本相同的: 使用切片来分配. 第二个方案是使用的 zip 操作符的 Z 操作, 这会 zip 成一个列表象: 1, 2, 3 Z 10, 20, 30 变成 1, 10, 2, 20, 3, 30. 这的 Z=> 是元操作, 在这通过 => ( Pair 创建的操作 ) 来绑定 zip . 所以 1, 2, 3 Z=> 10, 20, 30 相当于 1, 2, 3 Z=> 10, 20, 30. 赋值给哈希一个数组列表变量.

对于存在检查, 这个哈希的值是不什么重要, 主要他们在布尔上下文返回 True. 在这种情况下, 有一个不错的方式来初始化哈希, 给 keys 一个数组或者列表
  1. my %exists = @keys Z=> 1 xx *;
复制代码
这是一个 lazy, 在右侧 1 组成无穷列表, 并依赖 Z 来结束这个列表.

[Numbers]

有时你从一些其它的地方取得一个数字, 但这个数字有一个自己预先定义的范围 ( 例如, 这样它可以作为一个数组索引 ).

在 Perl 5 中, 你常常会遇到什么 $a = $b > $upper ? $upper : $b, 其它的限制是 lower. 在这个地方我们使用 max 和 min 的中缀运算符, 可以简化成
  1. my $in-range = $lower max $x min $upper;
复制代码
因为 $lower max $x 返回两个数中较大的, 因此切出了这个范围的下端.

这为 min 和 max 是中缀运算符, 你也可以这样使用:
  1. $x max= 0; $x min= 10;
复制代码
[Debugging]

Perl 5 中我们常常使用 Data::Dumper, 在 Perl 6 的中我们使用对象的 .perl 方法. 这二个都能尽可能生成, 真实的原始数据结构.

这个 :$var 生成 => 的键值对 ("colonpair"), 使用变量名做为关键字 ( 但前标记会剥离开 ). 因些, 它们会是 var => $var 一样的结构. note() 是用于写入标准错误, 并追加一个换行. 所以 `:$var.perl 是一个获得用于调试, 名称, 目标的变量的值的快捷方式.

[Sorting]

象 Perl 5 中一样, 这个 sort 是内置的. 它可根据所采取的比较函数来比较两个值, 然后排序. 不同于 Perl 5 的是, 这更加智能, 如果你的参数只有一个值会自动使用 transformation.

如果你想过一个 transformed 对值进行比较, 在 Perl 5 中你可以这样:
  1. # WARNING: Perl 5 code ahead
  2. my @sorted = sort { transform($a) cmp transform($b) } @values;

  3. # or the so-called Schwartzian Transform:
  4. my @sorted = map { $_->[1] }
  5.              sort { $a->[0] cmp $b->[0] }
  6.              map { [transform($_), $_] }
  7.              @values
复制代码
上面二个的解决方案的在进行比较的时候, 第一个需要不断重复转换的输入. 第二个方案通过存储原始值转化后的值避免了重复输入, 但它多写了相当多的代码.

Perl 6 会自动使用第二种方案 ( 使用更加有效的 Schwartzian 转换, 避免数组的每个值重复转换 ), 这个转换函数只有一个参数:
  1. my @sorted = sort &transform, @values;
复制代码
强制属性

通常我们强制一些属性必须存在, 是为了检查其构造函数中是否存在.

在 Perl 6 中也是这样工作的, 但它更加容易, 更加安全, 当请求每个需要存在属性时:
  1. has $.attr = die "'attr' is mandatory";
复制代码
这利用了默认值的机制. 当提供一个值, 这个就永远不会执行, 会用于生成默认值, 这个 die 不会触发. 如果有任何构造函数没设置这个值, 就会抛出异常.

动机

N/A

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
36 [报告]
发表于 2014-05-29 10:45 |只看该作者

"Perl 5 to 6" Lesson 28 - Currying 柯里化

概要
  1.   use v6;

  2.   my &f := &substr.assuming('Hello, World');
  3.   say f(0, 2);                # He
  4.   say f(3, 2);                # lo
  5.   say f(7);                   # World

  6.   say <a b c>.map: * x 2;     # aabbcc
  7.   say <a b c>.map: *.uc;      # ABC
  8.   for ^10 {
  9.       print <R G B>.[$_ % *]; # RGBRGBRGBR
  10.   }
复制代码
描述

Currying 和 partial application 用于用一个函数产生新的函数, 或是用一个方法提供一些参数再产生新的方法. 因为可以动态产生很多函数, 这样就省去很多码字的时间, 当函数需要返回一个回调的时候也会非常有用.

假设你想要一个函数用于从 `"Hello, World"` 做各种提取子串操作, 这样做的经典方法是写自己的函数:
  1.   sub f(*@a) {
  2.       substr('Hello, World', |@a)
  3.   }
复制代码
通过 `assuming` 方法来实现柯里化

Perl 6 提供了一个方法 `assuming` 在代码的对象上, 它可以传递参数给它的调用者成为一体, 并返回调用者的功能的函数.
  1. my &f := &substr.assuming('Hello, World');
复制代码
现在 `f(1, 2)` 相当于 `substr('Hello, World', 1, 2)`.

这个 `assuming` 方法也可以工作在操作符上, 因为操作符只是一个奇怪名字的函数. 你想实现一个子函数, 给任何传递给它的数值都增加 2 , 你可以这样写.
  1. my &add_two := &infix:<+>.assuming(2);
复制代码
但这是一种很无聊的写法, 所以有另一种选择.

通过 Whatever-Star ( * 号 ) 来实现柯里化
  1.   my &add_two := * + 2;
  2.   say add_two(4);         # 6
复制代码
星号, 叫 _Whatever_, 是一个占位符参数, 所以整个表达式返回一个闭包. 多个星号 "Whatevers" 在单个表达式中也是可以的, 这样也会创建闭包, 但希望提供更多的参数, 通过形参替换每个 "*" 元素. 所以 `* * 5 + *` 相当于 `-> $a, $b { $a * 5 + $b }`.
  1.   my $c = * * 5 + *;
  2.   say $c(10, 2);                # 52
复制代码
注意第二个 `*` 是一个中缀运算符, 不是术语, 所以不会被 Whatever-currying 影响.

这的东西是由星号和闭包组成, 直接在语法驱动层实现的, 所以这些是在编译时完成, 所以:
  1.   my $star = *;
  2.   my $code = $star + 2
复制代码
如果这不构造成一个闭包的话, 就会出现 die 并给出一个信息, 必须由这个来做为占位符并返回闭包
  1.   Can't take numeric value for object of type Whatever
复制代码
Whatever-Star ( * 号 ) 的柯里化比起 `.assuming` 更加灵活, 因为它可以有其它的东西做为第一个参数:
  1.     say  ~(1, 3).map: 'hi' x *    # hi hihihi
复制代码
这的柯里化的第二个参数是一个字符重复中缀操作 `x`, 所以它在这个地方返回一个闭包. 然后调用前面的数字做为参数, 根据参数生成指定数量的字符.

这对象的方法的调用者也可以是星号.
  1.       say <a b c>.map: *.uc;      # ABC
复制代码
涉及一个闭包, 给其内容做为参数为其调用 `uc` 的方法.

动机

Perl 5 中也可用于函数式编程, 你可以看看 Jason Dominus' book _Higher Order Perl_.

Perl 6 努力使用这些更加容易, 从而提供工作让你更加容易构造函数式编程. Currying 和容易的构造闭包是函数式编程的关键. 并且可以很容易的与 map 或者 grep 之类一起使用.

另请参阅

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

<http://hop.perl.plover.com/>

<http://en.wikipedia.org/wiki/Currying>

论坛徽章:
0
37 [报告]
发表于 2014-06-04 11:24 |只看该作者
perl6 未知因素太多,观望中!楼主辛苦了。这么卖力的翻译啊!!!

论坛徽章:
7
戌狗
日期:2013-12-15 20:43:38技术图书徽章
日期:2014-03-05 01:33:12技术图书徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16赛季CBA联赛之青岛
日期:2016-03-17 20:36:13
38 [报告]
发表于 2014-06-18 05:54 |只看该作者
{:3_188:} ~ 3Q

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
39 [报告]
发表于 2014-07-06 18:55 |只看该作者
我发现 Perl6 支持宏。果断学习。

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
40 [报告]
发表于 2014-07-17 19:36 |只看该作者
my $x = 1;
my $x = 2;
报错

安装模块很困难啊。

ufo 提示要升级 rakudo, 但已经是最高版本了。

难道 Windows 的系统不能使用 Perl 6 吗?

our $x 还是全局的吗? local 找不到了。

$x = [1,2,3]; 定义的标量是引用吗?当参数传递后,是不是就传递引用了呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP