Perl 6 中的操作符(三)

范圍和范圍迭代器語法

.. 范圍操作符有各種在兩端帶有 ^符號的變體以表明把那個(gè)端點(diǎn)排除在范圍之外泣矛。 它總會產(chǎn)生一個(gè) Range 對象吮廉。 Range 對象是不可變的许师, 主要用于匹配間隔洋闽。

1..2 是從1到2包含端點(diǎn)的間隔瓤球, 而 1..2 不包含端點(diǎn)但是匹配任何在它倆之間的實(shí)數(shù)。

對于不同類型的數(shù)字參數(shù)咏连, 范圍會被強(qiáng)制為更寬的類型盯孙,所以:

1 .. 1.5

被看作為:

1.0 .. 1.5

這些強(qiáng)制由 multi 簽名定義。(其它類型可能有不同的強(qiáng)制策略祟滴。)特別要說明的是振惰, 使用 Range 作為末端是非法的:

0 ..^ 10  # 0 .. 9
0 .. ^10  # ERROR

如果范圍右側(cè)是非數(shù)字類型, 那么右側(cè)的參數(shù)被強(qiáng)轉(zhuǎn)為數(shù)字垄懂, 然后按上面那樣使用骑晶。

因此,第二個(gè)參數(shù)中的 Array 類型會被假定用作數(shù)字草慧, 如果左側(cè)的參數(shù)是數(shù)字的話:

0 ..^ @x    # okay
0 ..^ +@x   # same thing

對于字符串也類似:

0 .. '1.5'  # okay
0 .. +'1.5' # same thing

Whatever 類型也支持代表 -Inf/+Inf桶蛔。 如果端點(diǎn)之一是一個(gè) WhateverCode, 那么范圍會被引導(dǎo)為另一個(gè) WhateverCode。

Range 對象支持代表它們的左側(cè)和右側(cè)參數(shù)的 .min 和 .max 方法漫谷。 .bounds 方法返回一個(gè)含有那兩個(gè)值的列表以代表間隔仔雷。 Ranges 不會自動反轉(zhuǎn):

2..1 總是一個(gè) null 范圍。(然而舔示, 序列操作符 .. 能夠自動反轉(zhuǎn)碟婆,看下面。)

在 Range 的每個(gè)端點(diǎn)處惕稻, Range 對象支持代表排除(有)或包含(沒有)的 .excludes_min and .excludes_max 方法竖共。

Range      | .min | .max | .excludes_min | .excludes_max
-----------+------+------+---------------+------------
1..10      | 1    | 10   | Bool::False   | Bool::False
2.7..^9.3  | 2.7  | 9.3  | Bool::False   | Bool::True
'a'^..'z'  | 'a'  | 'z'  | Bool::True    | Bool::False
1^..^10    | 1    | 10   | Bool::True    | Bool::True

如果用在列表上下文中, Range 對象返回一個(gè)迭代器俺祠, 它產(chǎn)生一個(gè)以最小值開頭公给,以最大值結(jié)尾的序列。

任一端點(diǎn)可以使用 ^ 排除掉锻煌。因此 1..2 產(chǎn)生 (1,2) 但是 1^..^2 等價(jià)于 2..1 并不產(chǎn)生值妓布, 就像 () 做的那樣。要指定一個(gè)倒數(shù)的序列宋梧, 使用反轉(zhuǎn):

reverse 1..2
reverse 'a'..'z'

作為選擇匣沼, 對于數(shù)字序列, 你能使用序列操作符代替范圍操作符:

100,99,98 ... 0
100, *-1 ... 0      # same thing

換句話說捂龄,任何用作列表的 Range 會假定 .succ 語義释涛, 絕對不會是 .pred 語義。 沒有其它的增量被允許倦沧;如果你想通過某個(gè)不是 1 的增量數(shù)字來增加一個(gè)數(shù)字序列唇撬,

你必須使用 ... 序列操作符。(Range 操作符的 :by 副詞因此被廢棄了展融。)

0, *+0.1 ... 100    # 0, 0.1, 0.2, 0.3 ... 100

只有正念叨的類型支持 .succ 方法的 Range 才能被迭代窖认。如果它不支持, 任何迭代嘗試都會失敗。

一元區(qū)間

一元操作符 ^ 生成一個(gè)從 0 直到 其參數(shù)(不包括該參數(shù))的區(qū)間扑浸。所以 ^4 等價(jià)于 0..^4.

for ^4 { say $_ } # 0, 1, 2, 3

范圍的自動填充

[這一節(jié)是推斷的烧给,并且可能會在 6.0 中被忽略.]
因?yàn)樵?item 上下文中 Range 對象通常是無意義的,用作標(biāo)量操作符的 Range 對象一般會嘗試把操作分配給終點(diǎn)并返回另外一個(gè)適當(dāng)?shù)男薷倪^的 Range 代替喝噪。
很像兩個(gè)項(xiàng)的連結(jié)(junction), 但是只使用合適的間隔語義础嫡。 (值得注意的這種自動線程化的例外包括 infix:<~~>, 它是做智能匹配的, 還有 prefix:<+>, 它返回范圍的長度。) 因此如果你想使用長度而不是終點(diǎn)來做切片酝惧, 你可以這樣說:

@foo[ start() + ^$len ]

它是下面這種形式的簡寫:

@foo[ start() + (0..^$len) ]

它有點(diǎn)等價(jià)于:

@foo[ list do { my $tmp = start(); $tmp ..^ $tmp+$len } ]

換句話說榴鼎,數(shù)值化的操作符和其它有順序的類型通常被重載以在 Range 身上完成某些有意義的事情。

鏈?zhǔn)奖容^

S03-operators/relational.t lines 102–238

Perl 6 支持比較操作符的自然擴(kuò)展, 它允許多個(gè)操作數(shù):

 if 1 < $a < 100                        { say "Good, you picked a number *between* 1 and 100." }
 if 3 < $roll <= 6                      { print "High roll"  }
 if 1 <= $roll1 == $roll2 <= 6          { print "Doubles!"   }

如果第一個(gè)比較失敗了則產(chǎn)生比較短路鏈:

S03-operators/short-circuit.t lines 236–297

1 > 2 > die("this is never reached");

鏈子中得每個(gè)參數(shù)至多會被求值一次:

S03-operators/short-circuit.t lines 226–235

1 > $x++ > 2    # $x 只精確地增長一次

注意: 任何以 < 開頭的操作符必須在前面擁有空格晚唇,否則它會被解釋為散列的下標(biāo)巫财。

調(diào)用者標(biāo)記

當(dāng)使用 Perl 6 方法調(diào)用的「間接對象」語法時(shí)追加的 : 標(biāo)記了調(diào)用者(invocant)。下面的兩個(gè)語句是等價(jià)的:

$hacker.feed('Pizza and cola');
feed $hacker: 'Pizza and cola';

冒號也可以用在普通方法調(diào)用中以標(biāo)示它應(yīng)該被解析為列表操作符:

$hacker.feed: 'Pizza and cola';

這個(gè)冒號是一個(gè)單獨(dú)的令牌(token)哩陕。副詞前面的冒號不是單獨(dú)的令牌(token)翁涤。因此,在最長令牌(longest-token)規(guī)則下,

$hacker.feed:xxx('Pizza and cola');

被標(biāo)記為應(yīng)用到方法上作為它的「最高層級的在前面的操作符」("toplevel preceding operator")的副詞:

$hacker.feed :xxx('Pizza and cola');

不是作為 .feed 參數(shù)列表中的 xxx sub:

$hacker.feed: xxx('Pizza and cola');  # wrong

如果你兩種意義的冒號你都想要萌踱,為了既提供副詞又提供某種位置參數(shù), 你必須放置兩次冒號:

$hacker.feed: :xxx('Pizza and cola'), 1,2,3;

(因?yàn)轭愋偷脑蛩枰芽崭穹旁跇?biāo)簽的冒號之后。)

要特別注意因?yàn)楦痹~的優(yōu)先級:

1 + $hacker.feed :xxx('Pizza and cola');

會把 :xxx 副詞應(yīng)用到 + 操作符上, 而不是應(yīng)用到方法調(diào)用上号阿。這是不可能成功的并鸵。

S03-operators/adverbial-modifiers.t lines 7–201

流操作符

S03-feeds/basic.t lines 6–163

新的操作符 ==><== 就像Unix里的管道一樣,但是它作用于函數(shù)或語句扔涧,接受并返回列表.因?yàn)檫@些列表由不相關(guān)聯(lián)的對象組成并不流動园担, 我們把它們叫做喂食(feed)操作符而非管道。例如:

     @result = map { floor($^x / 2) },
              grep { /^ \d+ $/      },
              @data;

也能寫成向右偏的流操作符:

    @data ==> grep { /^ \d+ $/       }
          ==> map  { floor($^x / 2)  }
          ==> @result;

或者使用左方向的流操作符:

    @result <== map { floor($^x / 2) }
            <== grep { /^ \d+ $/     }
            <== @data;

每一種形式更清晰地表明了數(shù)據(jù)的流動枯夜。查看 S06 了解更多關(guān)于這兩個(gè)操作符的信息弯汰。

元操作符

Perl 6 的操作符被極大地規(guī)范化了,例如湖雹,通過分別在數(shù)字咏闪、字符串和布爾操作符前前置 +~摔吏、? 來表明按位操作是作用在數(shù)字鸽嫂、字符串還是單個(gè)位身上。但是那只是一種命名約定征讲,并且如果你想添加一個(gè)新的按位 ? 操作符据某, 你必須自己添加 +?, ~?, 和 ?? 操作符。 類似地诗箍,范圍中排除末端的脫字符(^)在那里只是約定而已癣籽。

和它相比, Perl 6 有 8 個(gè)標(biāo)準(zhǔn)的元操作符用于把已存在的給定操作符轉(zhuǎn)換為相關(guān)的更強(qiáng)大的操作符(或者至少不是一般的強(qiáng)大)。換句話說筷狼,這些元操作符正是高階函數(shù)(以其它函數(shù)作為參數(shù)的函數(shù))的便捷形式瓶籽。

包含元操作符的結(jié)構(gòu)被認(rèn)為是 "metatokens", 這意味著它們不受普通匹配規(guī)則的制約桑逝, 盡管它們的部件受制約棘劣。 然而,像普通的 tokens 那樣楞遏, metatokens 不允許在它們的子部件之間有空格茬暇。

賦值操作符

S03-operators/autovivification.t lines 4–111

C 和 Perl 程序員對于賦值操作符已經(jīng)司空見慣了。(盡管 .= 操作符現(xiàn)在意味著在左邊對象的身上調(diào)用一個(gè)可變方法寡喝, ~= 是字符串連結(jié)糙俗。)

大部分非關(guān)系中綴操作符能通過后綴 = 被轉(zhuǎn)換為對應(yīng)的賦值操作符。

A op= B;
A = A op B;

否定關(guān)系操作符

任何能返回 Bool 值的中綴關(guān)系操作符都可以通過前置一個(gè) ! 將它轉(zhuǎn)換為否定的關(guān)系操作符预鬓。有幾個(gè)關(guān)系操作符還有傳統(tǒng)的便捷寫法:

    Full form   Shortcut
    ---------   --------
    !==         !=
    !eq         ne

但是大部分關(guān)系操作符沒有傳統(tǒng)的便捷寫法:

    !~~
    !<
    !>=
    !ge
    !===
    !eqv
    !=:=

為了避免 !! 操作符迷惑視線巧骚, 你不可以修改任何已經(jīng)以! 開頭的操作符。

否定操作符的優(yōu)先級和基(base)操作符的優(yōu)先級相同格二。

你只可以否定那些返回 Bool 值的操作符劈彪。 注意諸如 ||^^ 的邏輯操作符不返回 Bool 值, 而是返回其中之一的操作數(shù)。

翻轉(zhuǎn)操作符

在任意中綴操作符上前置一個(gè) R,會翻轉(zhuǎn)它的兩個(gè)參數(shù)寞忿。例如之斯,反向比較:

  • Rcmp
  • Rleg
  • R<=>

任何翻轉(zhuǎn)操作符的優(yōu)先級和根操作符的優(yōu)先級是一樣的。結(jié)合性沒有被翻轉(zhuǎn)。

    [R-] 1,2,3   # produces 2 from 3 - (2 - 1)

要得到另外一種效果,可以先翻轉(zhuǎn)列表:

    [-] reverse 1,2,3  # produces 0

超運(yùn)算符

Unicode 字符 ? (\x[BB]) 和 ? (\x[AB]) 和它們的 ASCII連字 >><< 用于表示列表操作, 它作用于列表中的每個(gè)元素, 然后返回單個(gè)列表(或數(shù)組)作為結(jié)果. 換句話說, 超運(yùn)算符在 item 上下文中計(jì)算它的參數(shù), 但是隨后將操作符分派到每個(gè)參數(shù)身上,結(jié)果作為列表返回疮绷。

當(dāng)書寫超運(yùn)算符時(shí), 里面不允許出現(xiàn)空格嚣潜, 即冬骚, 兩個(gè) "hyper" 標(biāo)記之間不能有空格, 并且該操作符是能修改參數(shù)的郑原。 在外面空格策略和它的 base 操作符相同唉韭。 同樣地, 超運(yùn)算符的優(yōu)先級和它的 base 操作符相同犯犁。 這意味著對于大部分操作符属愤,你必須使用圓括號括起你使用逗號分割的列表。酸役。

例如:

     -? (1,2,3);                   # (-1, -2, -3)
     (1,1,2,3,5) ?+? (1,2,3,5,8);  # (2,3,5,8,13)住诸,尖括號都朝內(nèi)時(shí)驾胆,兩邊列表元素的個(gè)數(shù)必須相同

(如果你發(fā)現(xiàn)你自己這樣做了, 問問你自己是否真的在使用對象或列表贱呐; 在后一種情況中丧诺, 可能其它的諸如 Z 或 X 的元操作符更合適, 并且不需要括號)

一元超運(yùn)算符(要么前綴奄薇,要么后綴)只有一個(gè) hyper 標(biāo)記驳阎, 位于它的參數(shù)那邊, 而中綴操作符通常在參數(shù)的每一邊以表明有兩個(gè)參數(shù)馁蒂。

一元超運(yùn)算符

一元超運(yùn)算符的意思取決于操作符是否是結(jié)構(gòu)非關(guān)聯(lián)的操作符呵晚。 大部分操作符不是結(jié)構(gòu)的。

對于中綴操作符沫屡,如果兩者其中之一的一個(gè)參數(shù)的長度不夠饵隙,那么 Perl 會「提高」它,但是只有你把 hyper 標(biāo)記「尖」的那一端指向它時(shí)沮脖,Perl 才會提升長度不夠的那一端金矛。

 (3,8,2,9,3,8) >>->> 1;          # (2,7,1,8,2,7)
 @array ?+=? 42;                 # add 42 to each element

實(shí)際上,對于一個(gè)無序的諸如 Bag 的類型來說勺届,一個(gè)提升過的標(biāo)量是唯一能工作于該類型中的東西:

 Bag(3,8,2,9,3,8) >>->> 1;       # Bag(2,7,1,8,2,7) === Bag(1,2,2,7,7,8)
 # Cannot modify an immutable Bag
>  Bag(3,8,2,9,3,8)  # Bag 的用法以改變
bag(9, 8(2), 3(2), 2)

換句話說驶俊,把小于號那端指向一個(gè)參數(shù)告訴超運(yùn)算符在那邊做我想要做的(dwim, do what i means)。如果你不知道一邊或是另一邊會是 underdimensioned免姿,那么你可以在兩邊都做我想做的:

$left ?*? $right

注意:如果你擔(dān)心 Perl 會被像這樣的東西所迷惑:Note: if you are worried about Perl getting confused by something like this:

func ?*?

那么你無需擔(dān)心废睦,因?yàn)椴幌胫暗陌姹荆?Perl 6 從來不會猜測下一個(gè)東西是一個(gè)項(xiàng)(term)還是一個(gè)操作符。在這種情況下养泡,它總是期望一個(gè)項(xiàng)除非 func 被預(yù)先定義為一個(gè)類型或值的名字。
升級絕對不會發(fā)生在 hyper 的「鈍」的那一端上奈应。如果你這樣寫:

$bigger ?*? $smaller
$smaller ?*? $bigger

那么會拋出異常澜掩,而如果你這樣寫:

$foo ?*? $bar

那么你要求形狀的兩邊是一樣長的,否則會拋出異常杖挣。

對于所有 hyper dwimminess肩榕,如果運(yùn)算符的另一邊期望列表的地方出現(xiàn)的是一個(gè)標(biāo)量,那么那個(gè)標(biāo)量會被當(dāng)做一個(gè)重復(fù)了 * 次的那個(gè)元素的列表惩妇。

一旦我們有兩個(gè)列表要處理株汉,那么我們不得不決定使兩邊的元素長度相一致。如果兩邊都是 dwimmy歌殃,那么較短的那個(gè)列表會重復(fù)盡可能多的次數(shù)以使元素的個(gè)數(shù)合適乔妈。

如果只有一邊是 dwimmy,那么那一端的列表只會被增長或截?cái)嘁赃m應(yīng)另一邊的 non-dwimmy 的那個(gè)列表氓皱。

不管從數(shù)組的形狀的 dwim 是強(qiáng)制的還是自然發(fā)生的路召,一旦選擇了 dwim 的那一端勃刨,在 dwimmy 端的 dwim 語義總是:

下面是一些例子:

    (1,2,3,4) ?+? (1,2)    # always error,尖括號都朝內(nèi)時(shí)股淡,兩邊元素必須個(gè)數(shù)相同
    (1,2,3,4) ?+? (1,2)    # 2,4,4,6     rhs dwims to 1,2,1,2
    (1,2,3)   ?+? (1,2)    # 2,4,4       rhs dwims to 1,2,1
    (1,2,3,4) ?+? (1,2)    # 2,4         lhs dwims to 1,2
    (1,2,3,4) ?+? (1,2)    # 2,4,4,6     rhs dwims to 1,2,1,2
    (1,2,3)   ?+? (1,2)    # 2,4,4       rhs dwims to 1,2,1
    (1,2,3)   ?+? 1        # 2,3,4       rhs dwims to 1,1,1

當(dāng)使用一元操作符時(shí), 你總是把鈍的那端對準(zhǔn)單個(gè)運(yùn)算對象, 因?yàn)闆]有出現(xiàn)重復(fù)的東西:

     @negatives = -? @positives;
     @positions?++;            # Increment all positions
     @positions.?++;           # Same thing, dot form
     @positions?.++;           # Same thing, dot form 報(bào)錯(cuò)
     @positions.?.++;          # Same thing, dot form
     @positions\  .?\  .++;    # Same thing, unspace form
     @objects.?.run();
     ("f","oo","bar").?.chars; # (1,2,3)

注意方法調(diào)用實(shí)際上是后綴操作符, 而非中綴操作符, 所以, 你不能在點(diǎn)號后面放上一個(gè) ?

超運(yùn)算符在嵌套數(shù)組中是被遞歸地定義的身隐, 所以:

    -? [[1, 2], 3]              #    [-?[1, 2], -?3] 得到 -1 -2 -3
                                # == [[-1, -2], -3]
[[1, 2], 3] ?+? [4, [5, 6]]  #    [[1,2] ?+? 4, 3 ?+? [5, 6]],得到 5 6 8 9
                             # == [[5, 6], [8, 9]]

超運(yùn)算符也能作用于散列唯灵,就像作用于數(shù)組一樣贾铝。

%foo ?+? %bar;

得到兩個(gè)鍵的交集(對應(yīng)的鍵值相加)

> my %foo = "Tom" => 98, "Larry" => 100, "Bob" => "49";
("Tom" => 98, "Larry" => 100, "Bob" => "49").hash
> my %bar = "Tom" => 98, "Larry" => 100, "Vivo" => 86
("Tom" => 98, "Larry" => 100, "Vivo" => 86).hash
> %foo ?+? %bar
("Tom" => 196, "Larry" => 200).hash

而:

>  %foo ?+? %bar;
("Tom" => 196, "Larry" => 200, "Bob" => 49, "Vivo" => 86).hash

得到兩個(gè)鍵的并集(鍵值相加)

不對稱的 hypers 也有用; 例如, 如果你說:

    %outer ?+? %inner;

只有在 %outer 中已經(jīng)存在的 %inner 鍵才會出現(xiàn)在結(jié)果中.

> my %inner = "a" => 11;
> my %outer = "a" => 9, "b" => 12;
> %outer ?+? %inner # a => 20, b => 12

然而埠帕,

%outer ?+=? %inner;

假設(shè)你想讓 %outer 擁有鍵的并集垢揩,累加鍵值

> my %inner = "a" => 11;
> my %outer = "a" => 9, "b" => 12;
> %outer ?+=? %inner;  # a => 20, b => 12
> say %outer           # a => 20, b => 12
> say %inner           # a => 11

注意, hypers 允諾你不必關(guān)心處理以怎樣的順序發(fā)生搞监,只保證結(jié)果的結(jié)構(gòu)和輸入的形式保持一致水孩。從系統(tǒng)角度也不能保證操作是并行化的。

高效的并行化要求某種程度的不帶更多額外工作的工作分割琐驴,系統(tǒng)被允許平衡并行處理的惰性需求俘种。

例如, 一個(gè)算法想把一個(gè)列表分成2個(gè)等長的子列表是不會起作用的绝淡, 如果你不得不提前計(jì)算好列表長度宙刘, 因?yàn)槟悴皇强偰苡?jì)算出長度±谓停可以采取各種方法:

按需切換要并行處理的群組悬包, 或交錯(cuò)循環(huán)地使用一組 N 個(gè)核心的處理器,或任何東西馍乙。在該限制下布近, 一個(gè)簡單、非并行丝格、逐項(xiàng)的惰性實(shí)現(xiàn)就在 sepc 之中了撑瞧,但是不太可能高效的使用多核∠则颍‘

不考慮性能要求预伺,如果算法依賴于這些采用的方法, 那也是錯(cuò)誤的曼尊。

Reduction 操作符

任何中綴操作符(除了 non-associating 操作符)都可以在 term 位置處被方括號圍住酬诀, 以創(chuàng)建使用使用該操作符進(jìn)行換算的列表操作符:

    [+] 1, 2, 3;      # 1 + 2 + 3 = 6
    my @a = (5,6);
    [*] @a;           # 5 * 6 = 30

對于所有的元操作符來說, 在 metatoken 里面是不允許有空格的.

換算操作符和列表前綴的優(yōu)先級相同。 實(shí)際上骆撇, 換算操作符就是一個(gè)列表前綴瞒御,被當(dāng)作一個(gè)操作符來調(diào)用。因此神郊, 你可以以兩種方式的任何一種來實(shí)現(xiàn)換算操作符葵腹。要么你也能寫一個(gè)顯式的列表操作符:

    multi prefix:<[+]> (*@args) is default {
        my $accum = 0;
        while (@args) {
            $accum += @args.shift();
        }
        return $accum;
    }

或者你能讓系統(tǒng)根據(jù)對應(yīng)的中綴操作符為你自動生成一個(gè):

    &prefix:<[*]>  ::= &reduce.assuming(&infix:<*>, 1);
    &prefix:<[**]> ::= &reducerev.assuming(&infix:<**>);

如果換算操作符和中綴操作符的定義是獨(dú)立的高每, 那換算操作符和該操作符的結(jié)合性要相同:

    [-] 4, 3, 2;      # 4-3-2 = (4-3)-2 = -1
    [**] 4, 3, 2;     # 4**3**2 = 4**(3**2) = 262144

對于 list-associative 操作符(優(yōu)先級表中的 X),實(shí)現(xiàn)必須把參數(shù)的 listiness 考慮在內(nèi)践宴; 即鲸匿,如果重復(fù)地應(yīng)用一個(gè)二元版本的操作符會產(chǎn)生錯(cuò)誤的結(jié)果,那么它就不會被那樣實(shí)現(xiàn)阻肩。 例如:

    [^^] $a, $b, $c;  # means ($a ^^ $b ^^ $c), NOT (($a ^^ $b) ^^ $c)

對于 chain-associative 操作符(像 <)带欢, 所有的參數(shù)被一塊兒接收, 就像你顯式地寫出:

[<] 1, 3, 5;      # 1 < 3 < 5

對于列表中綴操作符烤惊, 輸入列表不會被展平乔煞, 以至于多個(gè) parcels 可以以逗號分割形式的參數(shù)傳遞進(jìn)來:

  [X~] (1,2), <a b>;  # 1,2 X~ <a b>

如果給定的參數(shù)少于 2 個(gè), 仍然會用給定的參數(shù)嘗試分派柒室, 并根據(jù)那個(gè)分派的接受者來處理少于 2 個(gè)參數(shù)的情況渡贾。 注意,默認(rèn)的列表操作符簽名是最通用的雄右, 所以空骚, 你被允許根據(jù)類型去定義不同的方式處理單個(gè)參數(shù)的情況:

    multi prefix:<[foo]> (Int $x) { 42 }
    multi prefix:<[foo]> (Str $x) { fail "Can't foo a single Str" }

然而, 0 參數(shù)的情況不能使用這種方式定義擂仍, 因?yàn)闆]有類型信息用于分派囤屹。操作符要想指定一個(gè)同一值應(yīng)該通過指定一個(gè)接收 0 個(gè)參數(shù)的 multi 變體來實(shí)現(xiàn)這:

    multi prefix:<[foo]> () { 0 }

在內(nèi)建操作符中,舉個(gè)例子逢渔, [+]() 返回 0 肋坚, [*]() 返回 1 。

默認(rèn)地肃廓, 如果有一個(gè)參數(shù)智厌, 內(nèi)建的換算操作符就返回那個(gè)參數(shù)。 然而盲赊, 這種默認(rèn)對于像 < 那樣返回類型和接收參數(shù)不同的操作符沒有效果峦剔,所以這種類型的操作符重載了單個(gè)參數(shù)的情況來返回更有意義的東西。為了和鏈?zhǔn)秸Z義保持一致角钩, 所有的比較操作符都對于 1 個(gè)或 0 個(gè)參數(shù)返回 Bool::True。

你也可以搞一個(gè)逗號操作符的換算操作符呻澜。 這正是 circumfix:<[ ]> 匿名數(shù)組構(gòu)建器的列表操作符形式:

    [1,2,3]     # make new Array: 1,2,3
    [,] 1,2,3   #  與上相同

內(nèi)置換算操作符返回下面的同一值:

    [**]()      # 1     (arguably nonsensical)
    [*]()       # 1
    [/]()       # fail  (換算沒有意義)
    [%]()       # fail  (換算沒有意義)
    [x]()       # fail  (換算沒有意義)
    [xx]()      # fail  (換算沒有意義)
    [+&]()      # -1    (from +^0, the 2's complement in arbitrary precision)
    [+<]()      # fail  (換算沒有意義)
    [+>]()      # fail  (換算沒有意義)
    [~&]()      # fail  (sensical but 1's length indeterminate)
    [~<]()      # fail  (換算沒有意義)
    [~>]()      # fail  (換算沒有意義)
    [+]()       # 0
    [-]()       # 0
    [~]()       # ''
    [+|]()      # 0
    [+^]()      # 0
    [~|]()      # ''    (length indeterminate but 0's default)
    [~^]()      # ''    (length indeterminate but 0's default)
    [&]()       # all()
    [|]()       # any()
    [^]()       # one()
    [!==]()     # Bool::True    (also for 1 arg)
    [==]()      # Bool::True    (also for 1 arg)
    [before]()  # Bool::True    (also for 1 arg)
    [after]()   # Bool::True    (also for 1 arg)
    [<]()       # Bool::True    (also for 1 arg)
    [<=]()      # Bool::True    (also for 1 arg)
    [>]()       # Bool::True    (also for 1 arg)
    [>=]()      # Bool::True    (also for 1 arg)
    [~~]()      # Bool::True    (also for 1 arg)
    [!~~]()     # Bool::True    (also for 1 arg)
    [eq]()      # Bool::True    (also for 1 arg)
    [!eq]()     # Bool::True    (also for 1 arg)
    [lt]()      # Bool::True    (also for 1 arg)
    [le]()      # Bool::True    (also for 1 arg)
    [gt]()      # Bool::True    (also for 1 arg)
    [ge]()      # Bool::True    (also for 1 arg)
    [=:=]()     # Bool::True    (also for 1 arg)
    [!=:=]()    # Bool::True    (also for 1 arg)
    [===]()     # Bool::True    (also for 1 arg)
    [!===]()    # Bool::True    (also for 1 arg)
    [eqv]()     # Bool::True    (also for 1 arg)
    [!eqv]()    # Bool::True    (also for 1 arg)
    [&&]()      # Bool::True
    [||]()      # Bool::False
    [^^]()      # Bool::False
    [//]()      # Any
    [min]()     # +Inf
    [max]()     # -Inf
    [=]()       # Nil    (same for all assignment operators)
    [,]()       # []
    [Z]()       # []

[=] $x, @y, $z, 0
[+=] $x, @y, $z, 1

等價(jià)于:

$x = @y[0] = @y[1] = @y[2] ... @y[*-1] = $z = 0
$x += @y[0] += @y[1] += @y[2] ... @y[*-1] += $z += 1

而不是:

$x = @y = $z = 0;
$x += @y += $z += 1;
my :($b, $c);               # okay
sub foo :($a,$b) {...}      # okay

-> "pointy block" token 也引入簽名, 但是這種情況你必須省略冒號和括號. 例如, 如果你在定義 loop block 的 "循環(huán)變量":

    for @dogpound -> Dog $fido { ... }
$foo.bar.baz.bletch.whatever.attr[] = 1,2,3;

空的 [] 和 .[] 后綴操作符被解釋為 0 維下標(biāo), 這返回整個(gè)數(shù)組, 不是作為一個(gè)一維的空切片, 返回空元素. 這同樣適用于散列上的 {} 和 .{} , 還有 <>, .<>,??, 和 .??递礼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市羹幸,隨后出現(xiàn)的幾起案子脊髓,更是在濱河造成了極大的恐慌,老刑警劉巖栅受,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件将硝,死亡現(xiàn)場離奇詭異恭朗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)依疼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門痰腮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人律罢,你說我怎么就攤上這事膀值。” “怎么了误辑?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵沧踏,是天一觀的道長。 經(jīng)常有香客問我巾钉,道長翘狱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任砰苍,我火速辦了婚禮潦匈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘师骗。我一直安慰自己历等,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布辟癌。 她就那樣靜靜地躺著寒屯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黍少。 梳的紋絲不亂的頭發(fā)上寡夹,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音厂置,去河邊找鬼菩掏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛昵济,可吹牛的內(nèi)容都是我干的智绸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼访忿,長吁一口氣:“原來是場噩夢啊……” “哼瞧栗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起海铆,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤迹恐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卧斟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殴边,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡憎茂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锤岸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竖幔。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖能耻,靈堂內(nèi)的尸體忽然破棺而出赏枚,到底是詐尸還是另有隱情,我是刑警寧澤晓猛,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布饿幅,位于F島的核電站,受9級特大地震影響戒职,放射性物質(zhì)發(fā)生泄漏栗恩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一洪燥、第九天 我趴在偏房一處隱蔽的房頂上張望磕秤。 院中可真熱鬧,春花似錦捧韵、人聲如沸市咆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒙兰。三九已至,卻和暖如春芒篷,著一層夾襖步出監(jiān)牢的瞬間搜变,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工针炉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挠他,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓篡帕,卻偏偏與公主長得像殖侵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子镰烧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容