Perl6 | Examples & 9 ^ junction

26 May 2005


Preface

junction, 中文可以翻译成结。强大得你会立刻爱上它。

Examples

先举几个例子:
  • 判断 $a 要么等于 1 要么等于 2 要么等于 3 ....
    # Perl 5
    if ($a == 1 || $a == 2 || $a == 3 || ....) {
    # Perl 6
    if $a = 1|2|3|.. {
  • 判断 $a $b 都不等于 $c $d (两个用 Perl 5 写还不算麻烦,但十个呢?)
    # Perl 5
    if ($a != $c) && ($a != $d) && ($b != $c) && ($b != $d) {
    # Perl 6
    if all($a, $b) == none($c, $d) {
  • 判断一个文件存在,然后大小不为零,可读可写(这个不是 junction)
    # Perl 5
    if (-e $_ && -s $_ && -r $_ && -w $_) {
    # Perl 6
    if -e -s -r -w $_ {
  • 判断数组 @a 中的任意元素都不在 @b 中(不是说 Perl 5 中无法实现,要用 %hash 来曲线救国),Perl 6 中用 junction 就很简单:
    if any(@a) ne any(@b) {
  • 判断数组 @a 中只有一个元素在 @b 中:(听起来非常像集合的运算,并,交,补,包含等)
    if one(@a) eq one(@b) {
  • 一个变量不是对象 A 也不是对象 B 也不是对象 C,或定义一个变量不是 Dog 就是 Cat.
    if $a ~~ none(A|B|C) {
    my Dog|Cat $pet;

详细描述

junction 其实是将一些数据值叠加,表现为一个数据值。junction 有四种形式:

列表操作符中缀(infix)操作符关系简单解释
all&AND所有的值必须都为 true
any|OR至少有一个值为 true
one^XOR有且仅有一个值为 true
noneNOT所有的值都得为 flase

注意中缀操作符是列表相关("list-associative")的:

$a | $b | $c 与 any($a,$b,$c) 同,而不是 any(any($a,$b),$c)
$a & $b & $c 与 all($a,$b,$c) 同,而不是 all(all($a,$b),$c)
$a ^ $b ^ $c 与 one($a,$b,$c) 同,而不是 one(one($a,$b),$c)

junction 与 向量操作符 有点类似。不同的是 junction 大多运行在判断正确与否里。

我们还是用例子来说明 junction 的运算:
$junc = any(1, 2);
$junc += 5; # $junc is now any(6, 7)
    junction 方法:
  • 我们用 .values 将 junction 展平为列表:(这种情况下或许向量操作符看起来更清晰点)
    my $junc = all(1, 2, 3);    # create a junction
    my $sums = $junc + 3;       # add 3
    my @set  = $sums.values();  # (4, 5, 6)
  • 我们用 dump 来输出某一 junction 的结构:
    $string = $sums.dump( ); # $string = "all(4,5,6)"
  • pick 只能从 any 或只有一个值的 one 里取得随机值,对于 all, none 和多于一个值的 one, 返回 undef
    my $junc = any(1, 2, 3);
    say $junc.pick();  # may be 1, 2, or 3
    
    my $junc = all(1, 2, 3); # none is the same as all
    say $junc.pick();  # undef
    
    my $junc = one(1, 2, 3);
    say $junc.pick();  # undef
    
    my $junc = one(1);
    say $junc.pick();  # 1

use junction;

have fun, guys.

ppt for PM Shanghai meeting

25 May 2005


I have roughly finished my powerpoint doc for the upcoming PM meeting in Shanghai.
It's related to "Perl 6 Subroutine". I want to show the attender how powerful Perl6 is.

Perl 6 is at hand. Autrijus ship the pugs in a high speed.
Today he announced that we can use CPAN in pugs. Amazing.

So I think the Perl6 syntax is a interesting && popular topic.

I'm not sure how long will it take? maybe more than 5 minites. Does it matter a lot?
For my limitation of knowledge, I doubt if it's beyond my ability.
It's also my virgin-show, and I doubt if I have the courage to express myself well.

God bless me.


let @Examples[8] = 'Perl6';

24 May 2005


let's go

my 是在当前词汇作用域里声明一个变量。

state

state 与 my 有点相似,它也是声明一个词汇作用域变量。所不同的是:my 对每次运行子程序块时都初始化变量,而 state 只在第一次运行时初始化。
sub count {
    state $x = 2;
    $x++;
    return $x
}
say &count(); # 3
say &count(); # 4
say &count(); # 5
你可以理解为它能记住上一次运行后的结果。

let && temp

temp 和 let 都不是声明符,它们是运行时的命令。temp 与 let 不同的是:temp 当退出当前词法作用域时恢复变量的值,而 let 只在当前作用域返回一个错误时(比如 undef, 空列表,或者异常等),才恢复变量的值。
my $a = 42;
my $get_a = { $a };
{
    temp $a = 23;
    say $a; # 23
    say $get_a(); # 23
}
say $a; # 42
say $get_a(); # 42
my $a = 42;
my $get_a = { $a };
{
    let $a = 23;
    say $a; # 23
    say $get_a(); # 23
    1;
}
say $a; # 23
say $get_a(); # 23
my $a = 42;
my $get_a = { $a };
{
    let $a = 23;
    say $a; # 23
    say $get_a(); # 23
    0;
}
say $a; # 42
say $get_a(); # 42

It's easy but powerful

God bless us.

sub infix:<(7)> ($Perl6, @Examples)

24 May 2005


Description

关于操作符重载的笔记。

Details

操作符只是带有特殊名字的子程序。我们这里对上一章 multi sub Examples (6, Perl6) {...} 里介绍的 multi sub 的例子用操作符重新写一次:
multi sub infix:<(+)> (Num $a, Num $b) { return $a + $b; }
multi sub infix:<(+)> (Str $a, Str $b) { return $a ~ $b; }
multi sub infix:<(+)> ($a, $b) { return $a ~ '-' ~ $b; }

say 1 (+) 2; # 3
say 'a' (+) 'b'; # ab
say 0 (+) 'a'; # 0-a
这里唯一需要介绍的是 infix 的意思。

(pre|in|post|circum)fix

操作符我们分为一元操作符和二元操作符,当然还有三元和 circumfix/圆周型。
  • 一元操作符按操作符在前在后分为两种,分别对应 prefix 和 postfix
    sub prefix:<(+)> ($a) { return "pre~$a~"; }
    sub postfix:<(+)> ($a) { return "~$a~post"; }
    
    say (+) 2; # pre~2~
    say 2 (+); # ~2~post
  • 二元操作符只能放中间,所以我们用 infix. 就是最前面的例子中所用的。
    二元操作符中有个特性,可以用 is commutative 定义成可交换的。如:
    multi sub infix:<(+)> (Str $a, Num $b) is commutative { return "$a-$b"; }
    
    say 0 (+) 'a'; # 0-a
    say 'a' (+) 0; # a-0
    这样不管前后顺序,只要有一个是 Str 有一个是 Num 就可以了。
  • 还有种圆周型操作符。最常见的是 HTML 中的注释:<!-- -->, 这时候我们就要用 circumfix
    sub circumfix:«<!-- -->» ($text) { ... }

You should know

What I said is a part of Perl6.

The Shanghai PerlMonger meeting

24 May 2005


We'll have a meeting @ Shanghai this weekend -- May 29th. Details @ 5月asterlink赞助的上海Perl聚会
cause it's not conflict with my course&exam, I'm very glad to join the perlgeeks at Shanghai.

Joe want me to give a lighting talk to the attender. I seem to be adding to my grey hair.
It's too difficult to determine what should be referred. I should say that I'm familiar with but not good at any topic in Perl.
I know a little about such things:

  • Catalyst, but have no idea about the plugin and member auth etc. and I think chunzi is more familar with it.
  • How 2 tarball a module to CPAN. I think the guys there all know it well.
  • Maybe Ajax. but nothing to say, it's so simple and perlish-less.
  • Perl6 syntax. maybe it's a good idea, but a u guys interesting in? Sigh, I'm not Larry or Damain, not the expert of Perl6.
  • CGI::Application, Template, Class::DBI, or something else. o, I'm not the author of such modules. My modules are not worth talking with.

It's 4 days left. Time is limited.

Of course, my another choice is to forget it. :)

Now what boring me most is

  • which train should I take?
  • When should I start to go?
  • How can I get the Fudan University? which bus or subway station?
  • How much will it cost?

Yap, God bless me all move smoothly.


multi sub Examples (6, Perl6) {...}

23 May 2005


Continuation

接着上一篇 sub Perl6 (*@Examples[5] is copy) 来接着讲 sub.

multi sub

如果你需要一个子程序对于传递进来参数类型的不同而区别对待的话,用 multi sub 是个很简单的方法。
比如定义一个 add 子程序,如果传递进来的是字符串将他们合并起来,数字的话则加起来;如果都不是的话中间用 - 连起来。
multi sub add (Num $a, Num $b) { return $a + $b; }
multi sub add (Str $a, Str $b) { return $a ~ $b; }
multi sub add ($a, $b) { return $a ~ '-' ~ $b; }

say add(1, 2); # 3
say add('a', 'b'); # ab
say add(0, 'a'); # 0-a
非常的方便。我想 multi 运用的比较多的是重载 op/操作符。这个下次讲。multi 还能操作方法:multi method

assuming

如果你要重复调用很多次子程序,而调用中子程序的某参数都是一样的。你可以使用 assuming(假设某参数):
sub multiply ($multiplicand, $multiplier) {
    return $multiplicand * $multiplier;
}
my $six_times = &multiply.assuming(multiplier => 6);

say $six_times(9); # 54
say $six_times(7); # 42

my $seven_times = &multiply.assuming(multiplier => 7);

say $seven_times(9); # 63
每一个子程序都有 assuming 这方法,我们管这种叫做 Curried Subroutines。

wrapping

有些时候你想在一个已定义的子程序里加些东西进去。可你又不方便改源代码(那子程序在一个模块里),而且你想实现原来子程序的功能(Perl 5 中可以试试 NEXT 模块),拷贝源代码是不方便的做法。
这样的例子在 log 时是非常常见的。在 Perl 6 中可以用 wrap 来实现这功能:
sub someaction (*@a) {
    say @a;
}

my $id = &someaction.wrap( {
    say 'start someaction'; # log start
    call;
    say 'end someaction'; # log end
} );

&someaction(1,2);
这样我们就非常简单的加进去了 log 功能。
这里的 call 是调用原子程序。
而如果你不想要这功能的时候,可以使用 unwrap 来去掉。
&someaction.unwrap($id);
当然,如果你是临时想重新定义改子程序的话,可以使用 temp (不仅对子程序,对变量也是有用的。)
{
   temp &someaction.wrap( {...} );
   # ...
}
wrap 可以多重嵌套

To be continued

See u next time.

sub Perl6 (*@Examples[5] is copy)

22 May 2005


Bubble

以前在 @Examples[0] is Perl6 里一开始就稍微讲了点子程序,而在 my Perl6 @Examples[3] 中也讲了子程序参数和返回类型。
现在接着讲 sub/子程序

Perl 5 的代码在 Perl 6 中会怎么样?

虽然说 Perl 5 这样的代码在 Perl 6 中也是可行的:
sub say { print qq{"@_"\n}; }
但要注意一点,这里的 @_ 是只读的。下面的代码会出错:
sub cap { $_ = uc $_ for @_ }   # Error: elements of @_ are constant
如果你想要更新 @_, 用 is rw 来指定。
sub swap (*@_ is rw) { @_[0,1] = @_[1,0] }
而预先声明却不定义一个子程序,Perl 5 中可以这么写:
sub foo;
这在 Perl 6 中会报错,Perl 6 必须得这么写:(那三个点是语法的一部分。)
sub foo {...}

如何定义一个全局子程序

我们在 say q:2 '@*Examples.[4] &Perl6()'; 中说用 * 来声明一个真正的全局变量,而子程序也一样:
# from S06.pod
    $*next_id = 0; # 全局变量
    sub *saith($text)  { print "Yea verily, $text" } # 全局子程序

    module A {
        my $next_id = 2;    # hides any global or package $next_id / 隐藏任何全局或包变量 $next_id
        saith($next_id);    # print the lexical $next_id; / 输出词汇变量 $next_id,这里为 2
        saith($*next_id);   # print the global $next_id; / 输出全局变量 $next_id, 这里为 0
    }

    module B {
        saith($next_id);    # Unambiguously the global $next_id / 显然是全局变量 $next_id,这里为 0
    }

参数分配

    在 Perl 5 中因为没有名字参数,所以传递任意几个参数给子程序都是可以的。
    但 Perl 6 不同,如果你定义了两个命名参数却只有传递一个,编译器就会报错。如果你定义了要数组参数而传递了标量也会报错。
  • 而有时候我们不能确定某命名参数是否传递的话,需要在前面加一个 ?. 例子:
    sub func ($a, ?$b) {
        say $a, $b;
    }
    这样调用 &func(1) 和 &func(1, 2) 都不会报错。
  • 有时候你不想通过传递一个带顺序的参数列表给子程序,而想指定某些参数的名字用以传递,在 Perl 6 中这是可以的。我们用 + 来指定一个 Named Parameters/有名参数。例如:
    sub func ($a, ?$b, +$c) {
        say $a, '-', $b, '-', $c;
    }
    &func(1,c => 2); # 输出 1--2
    注意以下几点:
    1. 带名参数是可选的。所以上面用 &func(1) 不会报错,输出 1--
      不过按 S06 的说法,我们可以使用 is required 使之必须。
    2. 带名参数必须在位置参数(顺序参数)的后面。(S06 中虽然这么写,但是我在 pugs 里运行了是不用一定在后面的)
    3. 如果没有提供带名参数,那就按顺序参数来操作。如 &func(1,2,3) 输出 1-2-3。再举个稍微复杂点的例子:
      sub func ($a, ?$b, +$c, ?$d) {
          say $a, '-', $b, '-', $c, '-', $d;
      }
      &func(1,2,3);
      没有提供带名参数,按顺序来操作,结果为 1-2-3-
      而 &func(1,2,3,:c<4>); 的话,结果为 1-2-4-3
    4. 带名参数也可以用 Pair 写法:&func(1,:c<3>); 输出 1--3
    5. + 可以不写。(我在 pugs 里试过不写是可以的。)
  • 对于可选和带名参数来说,可以使用 = 来提供默认值:
    sub func ($a, ?$b = 2) {
        say $a, '-', $b;
    }
    &func(1); # 1-2
  • 还记不记得最上面的 sub swap (*@_ is rw),* 在此的作用是接收所有未被分配的参数。例如:
    sub func ($a, ?$b, *@c) {
        say $a, '-', $b, '-', @c, '-';
    }
    
    &func(1,2,3,4,5); # 1-2-345
    这里的 @c 将接收 3,4,5; 如果没有 * 会报错。

is rw/is copy

  • 默认命名参数是原传递参数的别名,并且该命名参数是只读的。如:
    sub func ($a) {
        # $a = 2 会报错,因为默认是只读的
        say $a;
    }
    my $o = 1;
    &func($o);
    这里 $a 是 $o 的别名($a := $o;),且 $a 是只读的。
  • 如果想在子程序里改变 $a 的值并且同时改变 $o 的值。可以使用 is rw.
    sub func ($a is rw) {
        say $a;
        $a = 2;
    }
    my $o = 1;
    &func($o); # 输出 1
    say $o; # $o 变为了 2
  • 如果想在子程序里改变 $a 的值但对应改变 $o 的值,可以使用 is copy.
    sub func ($a is copy) {
        $a = 2;
        say $a;
    }
    my $o = 1;
    &func($o); # 输出 2
    say $o; # $o 还是为 1
  • 可以说 is rw 是按址传递,而 is copy 是按值传递。

OUTER::

如果你在子程序里定义了 $x, 又想获得子程序外面的 $x 的话,可以使用 OUTER::
{ my $a = 1; {
   my $a=2; {
      my $a=3;
      say $a; # 3
      say $OUTER::a; # 2
      say $OUTER::OUTER::a; # 1
}}}

want

在 Perl 5 中如果区别返回值是数组和标量时我们用 wantarray, 在 Perl 6 中将不再有这东西,而用更强大的 want 来代替。例子:
given want { 
   when Scalar {...} # 返回一个标量 
   when List   {...} # 要一个列表
   when 2      {...} # 要两个值
}

Correct me when I'm wrong

Exercise more.

say q:2 '@*Examples.[4] &Perl6()';

22 May 2005


Variables

  • 真正意义上的全局变量生存在包 * 里。如 $*UID, @*ARGS, %*ENV
    打印所有环境变量:
    for %*ENV.kv -> $key, $val {
        say "$key => $val";
    }
    如果我们只写 %ENV, 那编译器将从最里面包依次往外搜索到全局包。
    for %ENV.kv -> $key, $val {
        say "$key => $val";
    }
    上面这段代码与 %*ENV 相同。但如果定义了 %ENV 就不一样了:
    my %ENV = ( 'a' => 'b', 'c' => 'd' );
    
    for %ENV.kv -> $key, $val {
        say "$key => $val";
    }
    # output is
    # a => b
    # c => d
  • 文件范围的变量的第二标记为 =. 例如 $=DATA 是你文件内 =begin DATA 句柄的变量名。
    所有的 pod 结构可以通过 %=POD (或类似的)来获得。
  • 词汇范围的变量的第二标记为 ?. 它们是是编译器所知道的值。(运行期的值进入了包 *.)
    例如:$?FILE 和 $?LINE 是你当前的文件和当前行数字。
    #!/usr/bin/pugs
    # the filename is t.pugs
    say $?FILE, $?LINE; #t.pugs3
    可能的变量有:(请参考 S02.pod
    变量名英文解释中文解释举例说明
    $?OSWhich os am I compiled for?当前编译的操作系统如 Win2000 下为 MSWin32
    $?OSVERWhich os version am I compiled for?当前编译操作系统的版本号
    $?PERLVERWhich Perl version am I compiled for?当前编译的 Perl 版本号
    $?FILEWhich file am I in?当前的文件名
    $?LINEWhich line am I at?所在的行号
    $?PACKAGE
    @?PACKAGE
    Which package(s) am I in?所在的包名
    $?MODULE
    @?MODULE
    Which module am I in?所在的模块名
  • 因为 *, =, ? 都可以做为包名使用,所以你可以这么写:%*::ENV, $=::DATA, @?::MODULE

内插/interpolate

  1. 数组内插:要内插整个数组,现在必须使用空中括号[]做下标。
    my @a = ('p', 'e', 'r', 'l');
    say "array @a"; # array @a
    say "array @a[]"; # array p e r l
  2. 散列内插:要内插整个散列,必须得使用空括号或三角符号:
    my %bar = ( 'a' => 'b', 'c' => 'd' );
    print "hash are:\n%bar{}";
    # output is
    # hash are:
    # a       b
    # c       d
    对于一个 Pair 来说,键和值之间插入 tab (制表),整个 Pair 后面插入一个换行。
  3. 子程序内插:为了内插子程序调用结果,必须在前加 & 后加括号:
    sub func {
        return ('f', 'u', 'n', 'c');
    }
    
    print "call &func return &func()"; # call &func return f u n c
    在标量上下文调用函数。(如果返回一个列表,那么列表将做为数组内插。)
  4. 方法内插:为了内插一个没有参数的方法返回值,括号是必须的:
    print "The attribute is $obj.attr().\n"
    同样的,在标量上下文调用方法。(如果返回列表,将其作为数组内插。)
  5. 裸包内插,例子如下:
    my $i = 2;
    say "now \$i is { $i * 2 }"; # now $i is 4
    如果你想让双引号不内插大括号,你可以明确地去掉这功能:
     qq:c(0) "Here are { $two uninterpolated } curlies"; # c(0) 去掉了内插
    q 后面的副词可以设置你只内插标量或数组或散列或什么(见下面详细解说)。例如:
    my $two = 2;
    say q:s 'Here are { $two * 2 } curlies'; # Here are { 2 * 2 } curlies
    这里我们用 :s 限定了只内插标量。

引号副词

Short/短名Long/长名Meaning/意思
:x:execExecute as command and return results / 当成命令运行并返回结果
:w:wordsSplit result on words (no quote protection) / 按字分割(不考虑引号保护)
:ww:quotewordsplit result on words (with quote protection) / 按此分割 (考虑引号保护)
:t:toInterpret result as heredoc terminator / 以 heredoc 形式内插结果
:0:rawNo escapes at all (unless otherwise adverbed) / 无转义(除非有其他副词)
:1:singleInterpolate \\, \q and \' (or whatever) / 内插 \\, \q 和 \' (或其它)
:2:doubleInterpolate all the following / 内插下面所有
:s:scalarInterpolate $ vars / 内插 $ 变量
:a:arrayInterpolate @ vars / 内插 @ 变量
:h:hashInterpolate % vars / 内插 % 变量
:f:functionInterpolate & calls / 内插 & 调用
:c:closureInterpolate {...} expressions / 内插 {...} 表达式
:b:backslashInterpolate \n, \t, etc. (implies :m) / 内插 \n, \t, etc.(暗指 :m)

当以 q 开头时,上面的所有都可以省略冒号,所以我们自动就有了如下形式:

    Form    Same as
    ====    =======
    qx//    q:x//
    qw//    q:w//
    qww//    q:ww//
    qt//    q:t//
    q0//    q:0//
    q1//    q:1//    (same as q//)
    q2//    q:2//    (same as qq//)
    qs//    q:s//
    qa//    q:a//
    qh//    q:h//
    qf//    q:f//
    qc//    q:c//
    qb//    q:b//

你可以定义你自己的引号副词和操作符。所有的大写副词都是保留给用户定义的。 所有在 Latin1 上的 Unicode 也是保留给用户定义的。

Others

  • 根据上面的副词,<< 再也没有了,我们现在这么来写 Heredoc:
    print qq:to/END/
    Give $amount to the man behind curtain number $curtain.
    END
  • 再也没有 C<$#foo> 记法了。用 C<@foo.end> 来代替,空数组返回 -1。
    (多唯数组用 C<@foo.shape[$dimension]> )
    my @a1 = (1,2,4);
    my @a2 = ();
    say @a1.end, @a2.end; # 2-1
  • 而数组的个数可以用 @foo.elems 或 [email protected] 得到。

All is welcomed

Thank God.

my Perl6 @Examples[3]

21 May 2005


Perl 6 中引进了类型(Type). 当然,你也可以像 Perl 5 一样不使用这东西。但类型所带来的诱惑是不能抵挡的。

Perl 6 中内建的对象类型以大写字母开头:Int, Num, Str, Bit, Ref, Scalar, Array, Hash, Rule 和 Code.
非对象(值)类型全是小写字母:int, num, str, bit, 和 ref.

指定变量的类型

在 Perl 5 中你没有(简单的)方法来生成一个只能存储数字的标量或生成一个引用只指向 Dog 这个类的对象。
同样的,你也很难生成一个只能含字符串的数组或是指定一个散列的值只能是数字数组的引用。
在 Perl 6 中,这种指定将变得非常简单。
my Int $number;
my Dog $obj_ref;
my Str @strings;
my Array of Num %counters;
看看下面的例子:
my int @array is MyArray;
它的意思是你声明了 @array 里的元素都为整数,而这个数组本身是一个 MyArray 类。

类型在子程序里的应用

sub Num mean(Int @vals) {
  return sum(@vals)/@vals;
}
指定 mean 函数接受一个整数数组并返回一个数。你也可以这么写:
sub mean(Int @vals) returns Num {
   return sum(@vals)/@vals;
}
我们进一步扩展这功能,要求返回的是数组,并且数组里的元素只能是整形:
sub hist(Int @vals) returns Array of Int {
  my Int @histogram;
  for @vals { @histogram[$_]++ }
  return @histogram;
}
这里我们用 of 来生成了一个复合类型。“内部类型”(of 后面)指定了“外部类型”(of 后面)的数据存储类型。

传递多个数组

在 Perl 5 中传递多个数组我们一般都得用引用。如
sub func {
    my ($a_ref, $b_ref) = @_;
    my @a = @$a_ref;my @b = @$b_ref;

    # &func(\@a, \@b);
在 Perl 6 中可以直接传递多个数组,下面的例子是可行的:
sub func (Array @a, Array @b) {
    say [email protected], [email protected];
}

my @a1 = (1,2,3);
my @a2 = (4,5,6,7);

&func(@a1, @a2); # 3,4
散列也一样,用 Hash %hash 就能传递整个散列。
甚至我们可以省略 sub func (Array @a, Array @b) 里的 Array, Perl 6 会自动搞定。
不过请注意:省略类型 Array 的话,我们传递两个标量参数给 func 时是不会报错的。

Am I correct?

It's not finished. I'll add something later.

@Perl6 >== @Examples xx 2

20 May 2005


本文介绍了一些新的操作符,未完成。

~, ??::, //, x, xx, ==>, <==, :, :=, ::=, =:=, »«, >><<

  1. ~ 将它的参数强制为字符串上下文,+ 强制为数字上下文,? 强制为布尔型上下文,* 为列表上下文。
    [email protected]        # @foo.elems 获得数组的个数
    [email protected]        # join ' ', @foo
    [email protected]        # ? @foo.elems
    +%foo        # +%foo.keys
  2. 条件操作符由原来的 ?: 变为 ??::
  3. 操作符 // 与 || 不同的是查看左侧的是否定义(即使为假也没事),而 || 查看是否为真。
  4. xxx, x 操作 scalar, xx 操作 array
    my $twin = "Lintilla";
    $twin x= 2;          # "LintillaLintilla"
    
    @array = "Lintilla" xx 3; # ("Lintilla", "Lintilla", "Lintilla")
    
    @array = (4, 2);
    @array xx= 2;              # now (4, 2, 4, 2)
  5. 新操作符 ==><== 它作用于参数和返回值都是列表的函数。以前用 map grep 写很长的代码,要从右往左看比较别扭。用这两操作符可以看起来比较清晰。
    # Perl 5
    @result = map { floor($^x / 2) } grep { /^ \d+ $/ } @data;
    # Perl 6
    @data ==> grep { /^ \d+ $/ }
          ==> map { floor($^x / 2) }
          ==> @result;
    # or
    @result <== map { floor($^x / 2) }
            <== grep { /^ \d+ $/ }
            <== @data;
  6. : 的意思:
    feed $hacker: 'Pizza and cola'; # 等同于 $hacker.feed('Pizza and cola');
  7. :=, ::=, =:=. := 称为绑定,我们将不再有 typeglob 类型,而用 := 来代替。::= 与 := 做相同的事情,不同的是 ::= 是运行在编译时。=:= 用以比较两个变量是否绑定。
    my $x = 'Just Another';
    my $y := $x;
    $y = 'Perl Hacker'; # $x 和 $y 都变为 'Perl Hacker'
    
    print '$x is the same as $y' if $x =:= $y; # true
    
    my $z := $y;
    print '$x is the same as $y' if $x =:= $z; # true
    
  8. 我们管这种操作符 »«, >><< 为向量操作符。它对数组操作并返回数组。每一个操作符(包括你自己定义的)都有对应的向量操作符。因为它默认的上下文是数组,所以当一边是标量时会将标量扩充为数组。例子:
    print join('-', (1,1,2,3,5) »+« (1,2,3,5,1)); # 2-3-5-8-6
    print join('-', (1,4,2,3,5) >>-<< 1); # 右边为标量扩充为 (1,1,1,1,1), 结果为 0-3-1-2-4
    print join('-', (1,4,2,3,5) »-« (1,1)); # 目前 pugs 是将右边补齐为 (1,1,undef,undef,undef), 结果为 0-3-2-3-5
    我们不仅有二元向量操作符,还有一元的(左操作符加«,»加右操作符):
    @negatives = -« @positives; # 所有元素前加负号
    @a »++; # 每个元素加 1
    ("f","oo","bar")».length;   # (1,2,3)
    @objects ».run(); # 每个 @objects 元素都执行 run()
    方法调用为 postfix, 不是 infix, 所以是加 ». 后面没有 «
    因为在 ASCII 下不能输出 »«, 所以我们用 >><<来代替。

Correction is welcomed

God bless us.