めざせ自然言語プログラミング by F#

Scalaだけ(http://d.hatena.ne.jp/tanakahisateru/20081208/1228742669)じゃ不公平なので、F#でも素数を求めてみました。

ワンライナーで書くとこんな感じ。

#light
List.filter (fun n ->
    not (List.exists (fun m -> n % m = 0) [2..n-1])
) [2..100];;

面白く書くとこんな感じ。

let of_only_which = List.filter
let join_with sep xs =
    List.fold_left (fun s x -> s + sep + x.ToString())
        ((List.hd xs).ToString()) (List.tl xs)
(* (x :> obj).ToString()ではなくx.ToString()でOK *)

let prime_factor_of n = (fun m -> n % m = 0)
let is_not_in xs f = not (List.exists f xs)
let lessor_nums_than n = [2..n-1]

let is_prime_number n =
    (prime_factor_of n) |> is_not_in (lessor_nums_than n)

System.Console.WriteLine(
    ([2..100] |> of_only_which is_prime_number) |> joined_with ",");;

英単語だけ順番に拾って、体裁を整えました。

Is prime number N? : Prime factor of N is not in lessor numbers than N.
2 .. 100 of only which is prime number joined with ",".

Nは素数ですか? : Nより少ない数にNの素因数がない。
2〜100のうち、素数だけを","で結合したもの。

ま、これはやりすぎだとしても、関数と引数の記述順序を逆転できるのは便利っぽい。思考の順序のとおりに(もちろん一時変数なしで)書けるし、また、読めるし。

そうそう、(x :> obj).ToString()ではまりました。型推論上、ジェネリックな型となる変数は、明示的にobj型にダウンアップキャストしないとToString()メソッドが呼べないようです。どう考えてもキャスト要らないと思うんだけど…これってバグかな。

1.9.6.2では型推論がより強化されたようで、総称型xでobjに定義されたメソッドを呼ぶさい、(x :> obj).ToString()というような回りくどい表現は不要になりました。