2008年9月28日日曜日

Ruby, Python, Haskell の条件式

Ruby の if は値を返す

以前、 Java しか知らなかった頃、Ruby で if が値を返すと読んだときは驚いた。 (@_@;)

if 式は、条件が成立した節(あるいは else 節)の最後に評価した式の結果を返します。else 節がなくいずれの条件も成り立たなければ nil を返します。

(制御構造 - Rubyリファレンスマニュアル より)

例えば、「テストで 80 点以上だったら `A’, 79 ~ 60 点では `B’, それ以下は `C’ 」としたい場合、

x = 30

result = if x >= 80 then 'A' elsif x >= 60 then 'B' else 'C' end
p result 

p x >= 80 ? 'A' : x >= 60 ? 'B' : 'C'

上記のように 条件演算子 を用いて書くこともできる。

テストの点数の配列に対して適用する場合には、

p [50, 100, 80, 60].map{|x| if x >= 80 then 'A' elsif x >= 60 then 'B' else 'C' end}

 

Python の条件式で値を返す

1 PEP 308: Conditional Expressions によると、Python では 2.5 から値を返す条件式を書くことができる。

x = 30
print 'A' if x >= 80 else 'B'

条件を追加するには、

print 'A' if x >=80 else 'B' if x >= 60 else 'C'

elif は使わないようだ。

はじめて見たときは、見にくかったので括弧を付けてみると、

print 'A' if a >=80 else ('B' if a >= 60 else 'C')

ん~ (@_@;) なくてもいいかなぁ。

 

リスト内包表記 で 条件式 を使う

例えば、テストの結果のリストがあった場合、次のように lambda と リスト内包表記 を使うことができる。

print [(lambda x: 'A' if x >=80 else 'B' if x >= 60 else 'C')(e)
        for e in [50, 100, 80, 60]]

なるほど、 (lambda)() という形式で呼出せばいいのか。

 

Haskell の場合はもちろん値を返す

Haskell では 3.6 条件式 if  または ガード を使って、

result x = if x >= 80 then "A" else if x >= 60 then "B" else "C"

result2 x
    | x >= 80 = "A"
    | x >= 60 = "B"
    | otherwise = "C"

main = putStrLn $ result 30

あ~、そうか elsif みたいなのは必要ないわけか。

追記 (2010.1.5) : Haskell 98 Report: 式 の「3.6 条件式」 によると、

以下の同一性が保存される

if e1 then e2 else e3 = case e1 of { True -> e2 ; False -> e3 }

だから、 case 式で同等な式を記述できる。