Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

F#で遊んでみる(5)

5章を読んでいこう。

  • inline
    • ここにinlineの説明があるのは唐突感があるなあ・・・
  • プリミティブ型
    • intは符号付き32bit(符号なし32bit整数はuint32。こっちは32がつく)
    • 符号付きbyteはsbyte、符号なしがbyte。リテラルはyがつく
    • floatは64bit。32bitはfloat32。リテラルはfloat32の方にfをつける
    • decimalプリミティブ。リテラルはMを付ける
    • charとstringもプリミティブ。中身はUnicodeリテラルは'a'と"a"。コードポイントは'\u0061'のように表す
      • ASCIIのcharリテラルにBを付けると、byteが得られる('A'B -> 65uy)
      • ASCIIのstringリテラルにBを付けると、byteの配列が得られる
    • boolのリテラルはtrueとfalse
    • unitのリテラルは()

stringのインデックスとスライスはこんな感じ。...はないみたい。

> let str = "1234567890";;
val str: string = "1234567890"

> str.[3];;
val it: char = '4'

> str.[5..8];;
val it: string = "6789"

> str.[5..];;
val it: string = "67890"

> str.[..8];;
val it: string = "123456789"

> str.[5...8];;

  str.[5...8];;
  --------^

/Users/tambara/study/fs_study/stdin(10,9): error FS0010: 予期しない シンボル '.' です 式内。']' または他のトークンを指定してください。

> str.[*];;
val it: string = "1234567890"
  • 型変換
    • 型名の演算子があるのでそれを使う
    • 文字/文字列から数値へも変換可能(float "2" -> 2.0)
  • オーバーフロー
    • 普通はオーバーフローしない。intの範囲を超えたら循環する
    • オーバーフローしたら例外にするにはopen Checkedを実行しておく
      • ただし、型変換ではやっぱり循環する・・・と本には書いてあるけど、やってみるとしない。動作変わったっぽい
> let i = 2147483647;;
val i: int = 2147483647

> i+1;; // オーバーフローすると循環する
val it: int = -2147483648

> let i64 = int64 i;;
val i64: int64 = 2147483647L

> i64+1;; // int64とintは足せない

  i64+1;;
  ----^

/Users/tambara/study/fs_study/stdin(4,5): error FS0001: 型 'int' は型 'int64' と一致しません

> i64+1L;; // int64なのでオーバーフローしない
val it: int64 = 2147483648L

> int(i64+1L);; // これをintに戻すと循環する
val it: int = -2147483648

> open Checked;; // おまじない
> i+1;; // オーバーフローしたら例外
System.OverflowException: Arithmetic operation resulted in an overflow.
   at <StartupCode$FSI_0011>.$FSI_0011.main@()
エラーのため停止しました

> int(i64+1L);; // 型変換でオーバーフローしても例外
System.OverflowException: Arithmetic operation resulted in an overflow.
   at <StartupCode$FSI_0010>.$FSI_0010.main@()
エラーのため停止しました
  • nanとinfinity
    • これはfloatの値。float32にはnanfとinfinityfがある
    • nanかどうかのチェックはSystem.Double.IsNaN()を使う
  • printfがある。printfなので可変長引数。F#で可変長引数をどうやって扱うかというと、コンパイラが特別扱いするからなのでとりあえずは気にしなくてよいらしい。printfはいつも謎
  • 演算子オーバーロードがある
    • OCamlにはない(んだっけ。全然覚えてない)
    • オーバーロードがあると、型推論が1つの型に決められないことがある。その場合、デフォルトの型に決められる

たとえば、(+)だと、とりあえずでintにされてしまう(笑)

> let 足し算 x y = x + y;;
val 足し算: x: int -> y: int -> int

ここで、例えば戻り値の型を与えると、引数の型も決まる

> let 文字列連結 x y : string = x + y;;
val 文字列連結: x: string -> y: string -> string

inlineを指定すると、展開された時点で決まることになるんだそうな。

> let inline add x y = x + y;;
val inline add:
  x:  ^a -> y:  ^b ->  ^c
    when ( ^a or  ^b) : (static member (+) :  ^a *  ^b ->  ^c)

いったん、今日はここまで。また5章の続きからやる。