ぺんぎんメモ

プログラミングのメモです。たまに私生活のことや鬱っぽいことを書きます。

F#雑記

基本

  • a = 123=は比較演算子
  • 変数に値をバインドするためには、let a = 123のようにletを付ける
  • 変数の値を変更するときはa <- 234のように記述する
  • データと関数を繋ぐときには|>を、関数と関数を繋ぐときは>>を使用する

データ構造

  • 各種データ構造に対する操作の計算量は、こちらに記載されている
  • Setの各操作
let s = Set.ofList([1; 2; 3])
let t = s.Contains(4)
printfn "%A" t //=> false
  • Mapの各操作
let m = Map.ofList([(1, "a"); (2, "b"); (3, "c")])
match m.TryFind(4) with
    | Some(x) -> printfn "%A" x
    | None -> printfn "None"

  • let sum a b = a + bというsum関数はint -> int -> intと推論される
  • 戻り値の型を明示したい場合はlet sum a b: int = a + bと書く
  • 型を全て明示したい場合はlet sum (a: int) (b: int): int = a + bと書く
  • seqを受け取ってseqを返す関数は次のように宣言・定義する
let f: seq<int> -> seq<string> =
    Seq.map(fun v -> v * 2) >>
    Seq.map(fun v -> v * 2) >>
    Seq.map(fun v -> v.ToString())

色々な書き方

※各コードは空白行で独立しているので、すべてのコードを一度に実行するとコンパイルエラーが発生する。

Seq.ofList([1;2;3]) |> Seq.length |> printfn "%d"
//=> 3

Seq.initInfinite(fun i -> i * 2) |> printfn "%A"
//=> seq [0; 2; 4; 6; ...]

Seq.initInfinite(fun i -> i * 2) |> Seq.take 3 |> printfn "%A"
//=> seq [0; 2; 4]

Seq.initInfinite(fun i -> i * 2)
    |> Seq.take 10
    |> Seq.map(printfn "%d")
    |> ignore
// 何も出力されない。理由がわからない

// seqの要素を出力したいときはforを利用する
let s = Seq.initInfinite(fun i -> i * 2) |> Seq.take 10
for v in s do
    printfn "%d" v

let s = { 0..2..10 }
// 少し面白い記述。seq { 0; 2; 4; 6; 8; 10 }を表す

let isOdd v = v % 2 = 1
let s = seq { for i in 1..10 do if isOdd i then yield i * i }
// ifを含むシーケンス式

let x = seq { yield 10; yield! { 1..10 } }
// シーケンスの結合にはyield!を使う
// x = seq { 10; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 }

.fsと.fsxの違い

  • .fs:プロジェクトの一部
  • .fsx:単独で実行できるもの