F# には厳密な評価戦略があります。これは、引数が関数に渡される前に評価されることを意味します。このため、2/0=1
は関数に渡される前に評価される-->
ため、 の短絡は||
の評価に影響しません。これは の2/0=1
前に評価されるためです||
。
-->
関数 (演算子)を変換して、値ではなく名前で引数を取るようにする必要があります。実際には、これは次のいずれ() -> 'T
かを取ることを意味しLazy<'T>
ます。
let (-->) p q = (not <| p()) || q()
> (fun () -> false) --> (fun () -> 2/0=1);;
true
または、代わりに、組み込みのlazy
構文を使用します。このようにして、もう少し簡潔な構文で同じ結果を得ることができます (計算が副作用に依存しない場合)。
let (-->) (p : Lazy<_>) (q : Lazy<_>) = (not <| p.Force()) || q.Force()
> lazy false --> lazy (2 / 0 = 1)
true
動作していますが、あまり便利ではないようです。残念ながら、 を取り除く簡単な方法はないfun () -> ...
と思いますが、いくつかの定数を定義することでボイラープレートを少し減らすことができると思います:
let True, False = (fun () -> true), (fun () -> false)
すべての引数に対してラムダを作成するボイラープレートをさらに削減するには、コード引用 (およびそれらを評価するUnquoteなどのライブラリ) を使用することができます。
let (-->) p q = (not (eval p)) || (eval q)
<@ false @> --> <@ 2 / 0 = 1 @>