識別子とか値とか関数とか (F#)

引き続きF#メモ。

#light

(* let キーワードで識別子を設定
   - 識別子(identifier) != 変数(variable)
   - 識別子は値の変更は不可(再定義が出来る場合もある。後述)
*)
let hello = "Hello" // hello という識別子を定義
printfn "%s" hello  // コンソール出力
(* 引数を2つ取り、その和を返す関数を定義
   - 関数も let キーワードで定義
   - C# のような return 文は不要
*)
let plus a b = a + b
printfn "1 + 2 = %d" (plus 1 2)
(* if文を用いて符号を判定する関数を定義
   F# の if 文は値を返すことに注意
*)
let isPositive a = if a >= 0 then true else false

printfn "isPositive: %b" (isPositive 1)
printfn "isPositive: %b" (isPositive (-1))
(* pattern matching を利用して符号を判定する関数
   - 最後の条件式の _ はすべての条件にマッチする
     (C# 等における switch 文の default みたいなもの)
   - 関数の終わりはインデントで表現(Pythonみたい)
*)
let sgn x =
  match x with
  | x when x > 0 -> 1
  | x when x < 0 -> -1
  | _ -> 0

printfn "sgn: %d" (sgn 0)
printfn "sgn: %d" (sgn 10)
printfn "sgn: %d" (sgn (-8))
(* 再帰呼び出しを利用して階乗を計算する関数
   - 再帰呼び出しする場合は rec キーワードをつける
*)
let rec factorial n =
  match n with 
  | 0 -> 1
  | _ -> n * factorial (n - 1)  // 再帰呼び出し

printfn "4! = %d" (factorial 4)
(* 引数なし、戻り値なしの関数定義
   - 「値なし」を表す型は () で表す(要するにC#等のvoidに相当)
   - 引数に () を受け取り、戻り値として () を返す
   - F# はこういう関数型言語っぽくないことも出来る
*)
let printHello () = 
  printfn "Hello World"
  ()

printHello () // 呼び出し
(* 関数の中で識別子を定義
  - 関数の中の識別子は再定義が可能
  - 関数の中で関数が定義できる
*)
let routine () =
  let pi = "PI"             // 関数の中でも識別子を定義
  printfn "value = %s" pi

  let pi = System.Math.PI   // 識別子 pi を再定義
  printfn "value = %f" pi

  let minus a b = a - b     // 関数の中で関数を定義
  printfn "3 - 2 = %d" (minus 3 2)

routine ()