前言
Raku 的運算子較多,甚至已經到過多的程度;有些較少見的運算子,其實很難記憶。本文不會列出所有的運算子,僅列出常見的運算子。
運算子的種類
根據運算子的位置,分為以下五種:
- Prefix,例:
-3
- Infix,例:
3 + 2
- Postfix,例:
$a++
- Circumfix,例:
<foo bar baz>
(字串串列) - Postcircumfix,例:
@arr[0]
(陣列取索引)
平常不需死記這些分類,但了解這個概念對於實作運算子重載 (operator overloading) 會有幫助,我們將於後文說明。
代數運算子
+
:相加-
:相減*
:相乘/
:相除,未整除得小數div
:整數相除%
:取餘數,可用於有理數mod
:整數取餘數**
:指數gcd
:取最大公約數lcm
:最最小公倍數
以下為實例:
3 + 2 == 5 or die "Wrong value";
3 - 2 == 1 or die "Wrong value";
3 * 2 == 6 or die "Wrong value";
3 / 2 == 1.5 or die "Wrong value";
3 div 2 == 1 or die "Wrong value";
3.77 % 0.1 == 0.07 or die "Wrong value";
3 mod 2 == 1 or die "Wrong value";
3 ** 2 == 9 or die "Wrong value";
60 gcd 35 == 5 or die "Wrong value";
30 lcm 45 == 90 or die "Wrong value";
遞增遞減運算子
++
:遞增 1--
:遞減 1
遞增/減放在變數前後的效果略有不同,但刻意操作這種效果不是好習慣,建議將這類運算子分開獨立的一行撰寫。
二元運算子
二元運算子用於二進位數運算。包括以下運算子:
+&
:bitwise AND+|
:bitwise OR+^
:bitwise XOR+<
:左移+>
:右移
以下是實例:
constant $READ = 4;
constant $WRITE = 2;
constant $EXEC = 1;
$READ +^ $WRITE == 6 or die "Wrong priviledge";
$READ +^ $EXEC == 5 or die "Wrong priviledge";
$READ +^ $WRITE +^ $EXEC == 7 or die "Wrong priviledge";
二元運算較不直覺,但會比代數運算快。當速度是重要考量時,可以試著使用二元運算。
比較運算子
要注意的是,Raku 有兩套比較運算子,分別用於數字和字串的比較。
- 比較數字
==
:相等!=
:不相等>
:大於>=
:大於等於<
:小於<=
:小於等於
- 比較字串
eq
:相等ne
:不相等gt
:大於ge
:大於等於lt
:小於le
:小於等於
記憶的方式是符號比符號,文字比文字。
以下是實例:
3 == 3 or die "Wrong condition";
3 != 2 or die "Wrong condition";
3 > 2 or die "Wrong condition";
3 >= 2 or die "Wrong condition";
3 < 5 or die "Wrong condition";
3 <= 5 or die "Wrong condition";
"Perl" eq "Perl" or die "Wrong condition";
"Perl" ne "Ruby" or die "Wrong condition";
"Perl" gt "C++" or die "Wrong condition";
"Perl" ge "C++" or die "Wrong condition";
"Perl" lt "Ruby" or die "Wrong condition";
"Perl" le "Ruby" or die "Wrong condition";
除了以上比較運算子,還有以下幾種相等運算子:
~~
:智能相等運算子,會根據兩邊的值自動比對是否相等eqv
:相等運算子,檢查兩邊的值型別相等且值相等===
:物件相等運算子,對基本型別,同於eqv
,對物件來說,要相同物件才會相等=~=
:浮點數相等運算子,當浮點數誤差夠小時相等,預設誤差值為 10 的 -15 次方
另外還有數種三元運算子:
cmp
:智能三元運算子,會根據兩邊的值自動比對<=>
:數字三元運算子,會將兩邊的值轉為 Real 型別leg
:字串三元運算子,會將兩邊的值轉為字串後比較 ( 註:leg 是 less、equal、greater 的縮寫 )
以下是實例:
(3 cmp 5) ~~ Less or die "Wrong condition";
("Perl" cmp "Perl") ~~ Same or die "Wrong condition";
("Ruby" cmp "Perl") ~~ More or die "Wrong condition";
另外還提供比較順序的運算子,可用於多種型別:
before
after
以下是實例:
(10 before 2) == False or die "Wrong logic";
(10 after 2) == True or die "Wrong logic";
("Perl" before "Ruby") == True or die "Wrong logic";
("Perl" after "Ruby") == False or die "Wrong logic";
筆者以為 Raku 的比較運算子種類過多。如果無法全部記起來也沒關係,先記比較基本的比較運算子即可。
邏輯運算子
要注意的是,Raku 有兩套邏輯運算子,兩者優先度有所不同。
- 低優先度
and
:且or
:或not
:否定
- 高優先度
&&
:且||
:或!
:否定
以下是實例:
(True && True) == True or die "Wrong logic";
(True && False) == False or die "Wrong logic";
(False && True) == False or die "Wrong logic";
(False && False) == False or die "Wrong logic";
(True || True) == True or die "Wrong logic";
(True || False) == True or die "Wrong logic";
(False || True) == True or die "Wrong logic";
(False || False) == False or die "Wrong logic";
(!True) == False or die "Wrong logic";
(!False) == True or die "Wrong logic";
Raku 的邏輯運算子有兩種優先度,比主流程式語言複雜些。如果無法記住運算子的優先度,用括號來改變運算子優先度即可,不需強記運算子優先度。
布林轉換運算子
布林轉換運算子會將值轉為布林值,可用於條件判斷中。
- 前綴的
?
:較高優先度 - 前綴的
so
:較低優先度
# Falsy.
?0 == False or die "Wrong state"; # Zero.
?0.0 == False or die "Wrong state"; # Zero (as float).
?"" == False or die "Wrong state"; # Empty string.
?() == False or die "Wrong state"; # Empty list.
?{} == False or die "Wrong state"; # Empty hash.
?Nil == False or die "Wrong state"; # Nil
my $v; ?$v == False or die "Wrong state"; # Undefined variable.
# Truthy: all non-falsey values.
?1 or die "Wrong state";
?1.0 or die "Wrong state";
?"Hello World" or die "Wrong state";
?(1, 2, 3) or die "Wrong state";
?{"one" => "eins", "two" => "zwei", "three" => "drei"} or die "Wrong state";
my $u = 99; ?$u or die "Wrong state";
使用本運算子的要點在於知道那些值為 falsy,即會判定為 False
的值,例子如下:
- 未定義的變數
Nil
0
(整數零)0.0
(有理數零)""
(空字串)()
(空串列){}
(空雜湊)
其他的值則為 truthy,即會判定為 True
的值。
字串運算子
x
:字串重覆- 二元
~
:字串相接 - 前綴
~
:將值轉為字串
以下是實例:
"Hi" x 3 eq "HiHiHi" or die "Wrong string";
("Hello " ~ "World") eq "Hello World" or die "Wrong string";
範圍運算子
根據不同情境,有以下四種範園運算子:
..
:含頭尾..^
:含頭不含尾^..
:不含頭含尾^..^
:不含頭不含尾
使用範園運算子時,要注意是否包含頭尾值。
見以下實例:
1 .. 5 ~~ (1, 2, 3, 4, 5) or die "Unequal list";
1 ..^ 5 ~~ (1, 2, 3, 4) or die "Unequal list";
1 ^.. 5 ~~ (2, 3, 4, 5) or die "Unequal list";
1 ^..^ 5 ~~ (2, 3, 4) or die "Unequal list";
運算子優先順序
Raku 的運算子優先順序很複雜,但不需強記,因為
- 數學相關的運算子其優先順序和數學知識相同
- 用括號可改變運算子的優先順序
運算子重載
Raku 支援運算子重載 (operator overloading),除了內建型別外,我們也可以為自訂型別自訂相關的運算子操作,這些自訂型別就可以如同內建型別般操作,例如:向量 (vector) 或矩陣 (matrix) 型別。我們將於物件導向程式中介紹運算子重載。