リストを生成するとき、リスト内包表記(List comprehensions)で書けると可読性がよくなる。ロゼッタコードの当該部分を参考にしながらHaskell、Python、Clojure、そしてCommon Lispで内包表記を使ってみる。
Haskellでリスト内包表記:
[(a,b,c) |
a <- [1..19],
b <- [a..19],
c <- [b..19],
a^2 + b^2 == c^2]
[(3,4,5),(5,12,13),(6,8,10),(8,15,17),(9,12,15)]
Pythonでリスト内包表記:
[(a,b,c)
for a in range(1,20)
for b in range(a,20)
for c in range(b,20)
if a**2 + b**2 == c**2]
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]
Clojureでリスト内包表記:
(for [a (range 1 20)
b (range a 20)
c (range b 20)
:when (= (+ (* a a) (* b b)) (* c c))]
[a b c])
([3 4 5] [5 12 13] [6 8 10] [8 15 17] [9 12 15])
Common Lispで...:
(loop for a from 1 to 19
append (loop for b from a to 19
append (loop for c from b to 19
when (= (+ (* a a) (* b b)) (* c c))
collect (list a b c))))
((3 4 5) (5 12 13) (6 8 10) (8 15 17) (9 12 15))
最後のは読みにくい。素のCommon Lispではリスト内包表記が使えないみたいなので、残念だ。でもincf-clを使えば大丈夫、Common Lispでも内包表記っぽいものが使えて、万事解決。
Common Lispでリスト内包表記:
(ql:quickload :incf-cl)
(use-package :incf-cl)
(lc (list a b c)
(<- a (range 1 19))
(<- b (range a 19))
(<- c (range b 19))
(= (+ (* a a) (* b b)) (* c c)))
((3 4 5) (5 12 13) (6 8 10) (8 15 17) (9 12 15))