(函數) multi 聲明符
Perl 6 允許你使用同一個名字但是不同簽名寫出幾個子例程。當子例程按名字被調用時, 運行時環境決定哪一個子例程是最佳匹配, 然后調用那個候選者。你使用 multi
聲明符來聲明每個候選者。
multi congratulate($name) {
say "祝你生日快樂, $name";
}
multi congratulate($name, $age) {
say "祝 $age 歲生日快樂, $name";
}
congratulate 'Camelia'; # 祝你生日快樂, Camelia
congratulate 'Rakudo', 15; # 祝你 15 歲生日快樂, Rakudo
分發/分派(dispatch) 可以發生在參數的數量(元數)上, 但是也能發生在類型上:
multi as-json(Bool $d) { $d ?? 'true' !! 'false' }
multi as-json(Real $d) { ~$d }
multi as-json(@d) { sprintf '[%s]', @d.map(&as-json).join(', ') }
say as-json([True, 42]); # [true, 42]
不帶任何指定例程類型的 multi
總是默認為 sub
, 但是你也可以把 multi
用在方法(methods)上。那些候選者全都是對象的 multi
方法:
class Congrats {
multi method congratulate($reason, $name) {
say "Hooray for your $reason, $name";
}
}
role BirthdayCongrats {
multi method congratulate('birthday', $name) {
say "Happy birthday, $name";
}
multi method congratulate('birthday', $name, $age) {
say "Happy {$age}th birthday, $name";
}
}
my $congrats = Congrats.new does BirthdayCongrats;
$congrats.congratulate('升職', 'Cindy'); #-> 恭喜你升職,Cindy
$congrats.congratulate('birthday', 'Bob'); #-> Happy birthday, Bob
proto
proto 從形式上聲明了 multi
候選者之間的共性
。 proto 充當作能檢查但不會修改參數的包裝器??纯催@個基本的例子:
proto congratulate(Str $reason, Str $name, |) {*}
multi congratulate($reason, $name) {
say "Hooray for your $reason, $name";
}
multi congratulate($reason, $name, Int $rank) {
say "Hooray for your $reason, $name -- you got rank $rank!";
}
congratulate('being a cool number', 'Fred'); # OK
congratulate('being a cool number', 'Fred', 42); # OK
congratulate('being a cool number', 42); # Proto match error
所有的 multi congratulate
都會遵守基本的簽名, 這個簽名中有兩個字符串參數, 后面跟著可選的更多的參數。 |
是一個未命名的 Capture
形參, 它允許 multi
接收額外的參數。第三個 congratulate 調用在編譯時失敗, 因為第一行的 proto 的簽名變成了所有三個 multi congratulate 的共同簽名, 而 42 不匹配 Str
。
say &congratulate.signature #-> (Str $reason, Str $name, | is raw)
你可以給 proto
一個函數體, 并且在你想執行 dispatch 的地方放上一個 {*}
。
# attempts to notify someone -- returns False if unsuccessful
proto notify(Str $user,Str $msg) {
my \hour = DateTime.now.hour;
if hour > 8 or hour < 22 {
return {*};
} else {
# we can't notify someone when they might be sleeping
return False;
}
}
{*}
總是分派給帶有參數的候選者。默認參數和類型強制轉換會起作用單不會傳遞。
proto mistake-proto(Str() $str, Int $number = 42) {*}
multi mistake-proto($str,$number) { say $str.WHAT }
mistake-proto(7,42); #-> (Int) -- coercions not passed on
mistake-proto('test'); #!> fails -- defaults not passed on