Raku 中的 Or Junction

作者:   發佈於:   #raku

寫了 PWC 080 後經 @holli-holzer 提醒,想說再來用 Or Junction 寫一回好了。

解 PWC 080 一文之中,將 N 個整數 @N 做成集合的寫法是:

my @N = @*ARGS.map({ .Int })
my $seen = @N.Set();

這之後,在使用之時,是把 $seen 當成 Hash 在用。以 $seen{$n} 來表示「測看看 $n 是否在 $seen 這個集合中」。

不過,若是以「測看看某個值是否在某個集合類的容器之中」為目的的話,Raku 裡有非常多寫法。以下以整數集合為例來列舉,令 $x 表示要找尋的值,@N$N 表示集合類容器。

(elem) 算符與 算符

if $x (elem) @N { ... }
if $x ∈ @N      { ... }

if $x (elem) $N { ... }
if $x ∈ $N      { ... }

此列中 @N 為 Array, 而 $N 可為 Seq (無限大的容器)或 Set(有限大的容器)。

Set 這部份另有 Sets, bags, and mixes 這篇文章可以參考。凡是「有限集合」類的容器物件,都可以與 ∈、∉、∋、∌、⊆、⊈、⊂、⊇、⊉、⊃、⊅、∪、∩、∖、⊖、⊍、⊎ 這一套數學符號算符來配合使用。或許對於看慣數學表示法的人而言會有些親切感。

另外一套寫法,就是透過 OR Junction 物件。

any

# any
if $x == any(@N) { ... }

infix || 為一般 US 鍵盤能打出的 pipe 字符。把任何中綴算符放在 [ ] 當中,就可變成前綴算符。例如 1 + 2 + 3 + 4 + 5 亦可表示為 [+] (1..5)。因此也可利用前綴化的 | 來建立 Junction 物件。

if $x == [|] (1,2,3,4,5) { ... }
if $x == [|] @N { ... }

如果將 Junction 物件存在純量變數中,使用起來就與一般純量無異。

$N = [|] @N;

或寫做:

$N = any(@N);

使用時:

if $x == $N { ... }

或許 Junction 這特性對於功能之延伸與程式碼之重構很有利。

附帶一提,之前寫到的連環比較運算式,也可以透過算符前綴化來將表示式簡化。比方說有一陣列整數 @N,要確認這陣列是否是完全由小到大排好,可以很苦力地寫出(@N 長度一變就破功):

if @N[0] < @N[1] < @N[2] < @N[3] { ... }

也可寫:

if [<] @N { ... }

這種簡短無比的表示式。