8

Jane Street の Core lib には次のような機能がありますFn.const

https://github.com/janestreet/core_kernel/blob/master/lib/fn.ml

let const c = (); fun _ -> c

val const : 'a -> 'b -> 'a
は、最初の引数を返すだけの関数を生成します

私は本当にそれを理解していません。

  1. この関数の目的は何ですか? どのようなシナリオで使用する必要がありますか?
  2. なぜ();最初に置くのですか?
  3. と書いてみませんlet const c = fun () -> cか?これにより、パラメーターとして受け取る関数が提供unitされ、常に initial が返されますc
  4. すると、パラメータとして取る関数になりlet f = const 5ます。弱いポリモーフィック パラメータを持つ関数を返す目的は何ですか?f'_a

psFnモジュール内のいくつかの関数はすべて();、関数を返す前に持っていることがわかり();ます。

4

2 に答える 2

11

この関数の目的は何ですか? どのようなシナリオで使用する必要がありますか?

引数を取る関数が必要なコンテキストで使用しますが、実際には引数を気にせず、毎回同じ値を返したいだけです。些細な例はList.map (const 42) xs、n 個のアイテムのリストを n 個の 42 のリストに変換する です。

あまりばかげていない (しかしより抽象的な) 例は、値を生成するために何かを行う関数ですが、特定の (たとえば、何かが成功しなかった場合) 条件下では、代わりにユーザー提供の関数を呼び出して、値を与える代わりに値を生成します。引数としての状況に関する情報。状況によっては、情報を気にせず、毎回同じデフォルト値を返すだけなので、constここで機能します。

() を入れる理由; 最初?

生成されたコードだけでなく、その内部表現においても、OCaml コンパイラは実際には多引数関数を持っています。let f x y = ...orのような関数を定義するとlet f x = fun y -> ...、OCaml は実際にこれを (別の関数を返す 1 引数の関数ではなく) 2 引数の関数に変換します。したがって、それf 1 2を呼び出す場合、それは 2 つの引数の関数への単純な呼び出しであり、代替手段よりもはるかに効率的です。ただし、単に実行f xすると、クロージャーを作成するためにいくつかの追加コードが生成されます。これは、クロージャーを直接返すよりも効率的ではありません。

したがって、この最適化により、すべての引数を指定して関数を呼び出すとパフォーマンスが向上しますが、そうでない場合は実際には非生産的です。前に を追加する()と、最適化が無効になります (関数の形式がなくなったためf x = fun y -> ...)。は 1 つの引数だけで呼び出されることを意図しているためconst( を直接呼び出しconst x yても意味がないので、 を記述しても問題ありませんx)、これによりパフォーマンスが向上します。

let const c = fun () -> c と書いてみませんか? これにより、ユニットをパラメーターとして受け取る関数が与えられ、常に初期 c が返されます。

unitその場合、関数は、関数の取得が予想されるコンテキストでのみ機能するため、これは非常に少数のケースです。たとえば、がユニットのリストであるList.map (const 42) xs場合にのみ機能しますxsが、これはほぼ確実ではありません。

于 2014-04-16T22:00:45.073 に答える