2019/02/12

Common Lispのcond

Pythonにはないcond

Rustをしばらく使い、たまにPythonを触る時、パターンマッチングのための何かが欲しくなることがあります。Pythonでもif文で似たようなことはできますが、何となくすっきり感がありません。
例えば、FizzBuzzプログラムで見てみると、Pythonの場合は以下のようにif文を使うことになります。インデントがおかしく表示されますが、スペース4つです。

def fizzbuzz(x):
    for i in range(0, x):
        if i % 15 == 0:
            print("FizzBuzz")
        elif i % 5 == 0:
            print("Buzz")
        elif i % 3 == 0:
            print("Fizz")
        else:
            print(i)
Rustの場合はif文でも可能ですが、match式を使うと以下のようなこともできます。こちらもなぜかインデントがおかしくなりますが、スペース4つです。

fn main() {
    for i in 0..=30 {
        match (i % 3, i % 5) {
            (0, 0) => {println!("FizzBuzz");},
            (_, 0) => {println!("Buzz");},
            (0, _) => {println!("Fizz");},
            _ => {println!("{}", i);}
        }
    }
}
完全に個人的な意見ではありますが、何となくすっきり感があります。
ではCommon Lispではどうなるのでしょう。私は目下勉強中なので、正解かどうかは自信がありませんが、以下のようなFizzBuzzになりました。インデントのズレは気にしないでください。調整してもどうもうまく表示されません。

(defun fizzbuzz (y)
  (dotimes (i y) (format t "~a~%"
                         (cond
                           ((= 0 (mod i 15)) "FizzBuzz")
                           ((= 0 (mod i 5)) "Buzz")
                           ((= 0 (mod i 3)) "Fizz")
                           (t i)))))
何となくRustのコードに似ている気がします。とてもすっきりとした感じです。
なぜCommon Lispの影響を受けたPythonにcondが無いのか、Pythonにも欲しかった。Pythonは便利なライブラリが多く存在する一方で、言語自体に不便を感じる場面が時々あります。何となく自作したものは、私の技術・知識不足のせいもありますが、なんとか似せようと考えてみたものの、結局はif文を使わざるを得なくなったり、ややこしくなったりという本末転倒な状態で、諦めてif文を使ったほうがよいくらいです。defmacromacro_rules!のような機能があればよかった。