サーチ…
0タプルは何が良いですか?
2タプルまたは3タプルは、関連項目のグループを表します。 (2D空間内の点、色のRGB値など)1タプルは、1つのint
で簡単に置き換えることができるのであまり役に立ちません。
0タプルは絶対に何も含んでいないので、さらに無駄に見えます。それにもF#のような関数型言語で非常に有用なプロパティがあります。たとえば、0タプル型はちょうど1つの値を持ち、通常は()
表されます。すべての0タプルはこの値を持つため、本質的にシングルトン型です。 F#を含むほとんどの関数型プログラミング言語では、これをunit
型と呼びます。
C#でvoid
を返す関数は、F#のunit
を返しvoid
:
let printResult = printfn "Hello"
それをF#対話インタプリタで実行すると、次のように表示されます:
val printResult : unit = ()
これは、値のことを意味するprintResult
型であるunit
、及び値を有する()
空のタプルの唯一の値unit
型)。
関数は、 unit
もパラメータとして取ることができます。 F#では、関数がパラメータを取っていないように見えるかもしれません。しかし、実際には、彼らはタイプのunit
単一のパラメータを取っている。この関数:
let doMath() = 2 + 4
実際には次のものと同等です:
let doMath () = 2 + 4
つまり、 unit
型の1つのパラメータをとり、 int
値6を返す関数です。この関数を定義するときにF#インタラクティブインタプリタが出力する型シグニチャを見ると、次のようになります。
val doMath : unit -> int
すべての関数が少なくとも1つのパラメータをとり、値を返すという事実は、たとえその値が()
ような "役に立たない"値であっても、関数の構成がF#ではより簡単であることを意味しますunit
。しかし、それは後で説明するより高度なテーマです。今のところ、ちょうどあなたが見たときにということを覚えているunit
、関数のシグネチャで、または()
関数のパラメータには、それは言うための方法としての役割を果たす0・タプル型だ「この関数が取る、あるいは戻り、意味のない値。」
コードの実行を延期する
unit
型を関数の引数として使用して、後で実行したくない関数を定義することができます。これは、主スレッドがバックグラウンドスレッドのいくつかの事前定義された機能をトリガしたい場合(非同期バックグラウンドタスクを新しいファイルに移動するなど)、またはレットバインディングをすぐに実行しない場合に便利です。
module Time =
let now = System.DateTime.Now // value is set and fixed for duration of program
let now() = System.DateTime.Now // value is calculated when function is called (each time)
次のコードでは、2秒ごとに作業している値を単純に出力する「ワーカー」を開始するコードを定義します。作業者は、それを制御するために使用される2つの関数、すなわち、次の値に移動する関数と、それが動作しなくなる関数を返します。これらは関数でなければなりません。私たちが選択するまではボディを実行したくないからです。さもなければ、ワーカーはただちに2番目の値に移動し、何もせずにシャットダウンします。
let startWorker value =
let current = ref value
let stop = ref false
let nextValue () = current := !current + 1
let stopOnNextTick () = stop := true
let rec loop () = async {
if !stop then
printfn "Stopping work."
return ()
else
printfn "Working on %d." !current
do! Async.Sleep 2000
return! loop () }
Async.Start (loop ())
nextValue, stopOnNextTick
私たちは、
let nextValue, stopOnNextTick = startWorker 12
作業が始まります - F#対話型の場合、2秒ごとにコンソールに出力されたメッセージが表示されます。その後、
nextValue ()
作業中の値が次の値に移動したことを示すメッセージが表示されます。
作業を終えるときは、
stopOnNextTick ()
関数は、終了メッセージを出力し、終了します。
unit
はここでは重要であり、「入力なし」を意味しています。機能にはすでに組み込まれている作業に必要なすべての情報が含まれており、呼び出し元はその情報を変更できません。