連環比較運算式

作者:   發佈於: ,更新於:   #perl #raku #python3

連環比較運算式這種語法,如 $a < $b < $c ,在數學界是很常見的表示法,一式可以表示多項變數之間的關系,但在程式語言裡似乎並不常看到

Raku 是在發展最初期就有這種語法了。比方說,以下這程式 num-within 能自 STDIN 中取得數字,並將 $from...$until 這範圍之內的數字印出,範圍之外的則丟棄。

#!/usr/bin/env raku
## Usage: num-within <from> <until>

my ($from, $until) = @*ARGS[0, 1];

for $*IN.lines() -> $num {
    if $from <= $num < $until {
        say $num
    }
}

用起來如下:

# bash -c 'while true; do echo $RANDOM; done' | num-within 100 120
114
165
155
130
161
199
108
115
153
166
...

Python 3 也支援這語法。以下是 num-within 改寫為 python3:

#!/usr/bin/env python3
## Usage: num-within.py <from> <until>

import sys

num_from  = int(sys.argv[1])
num_until = int(sys.argv[2])

for line in sys.stdin:
    n = int(line)
    if num_from <= n < num_until:
        print(str(n))

Perl5 終於也在 Perl 5.31.10 版之中加入了一部份之支援,並已於 Perl 5.32 中正式問市。以下為 num-within 改寫為 Perl5

#!/usr/bin/env perl
## Usage: num-within.pl <from> <until>
use v5.31.10;

my ($from, $until) = @ARGV[0,1];

while(defined(my $num = <STDIN>)) {
    if ($from <= $num < $until) {
        print $num;
    }
}

除了檢查數值的上下邊界之外,也可以用來做實做其他的。比方說實做 max3(a,b,c) (取三變數中最大者)

sub max3($x, $y, $z) {
    return $x if $y <= $x >= $z;
    return $y if $z <= $y >= $z;
    return $z;
}

不過 Perl5 中的實做似乎尚不完美,以下這種表示式在 Raku 與 Python3 的意義與其數學意義相同:

$a < $b == $c < $d

也就是與下等價:

($a < $b) and ($b == $c) and ($c < $d)

但在 Perl5 中被解析為:

($a < $b) == ($c < $d)

看來在 Perl5 中 == 算符並不能做為連環比較算式中的一節,使得此表示式之意義與其數學上的意義有所差距。從目前 perl-5.31.11 中的 perlop 文件 看來,這算是有明文寫著的一件事(雖然是並非寫得很明白,需要從運算子優先序表格推敲得出)。或許這部份尚有待發展。


2020/09/12 更新:Perl 5.32 確實加入了連環比較運算式之語法。