2016-06-27 5 views
3
let (->>>) lst exp = for i in lst do exp 

let result = [0..5] ->>> ([1..5] ->>> printf "hi") 
let result2 = for i in [0..5] do for x in [1..5] do printf "hi" 

私はとresult2が同じことをすると予想していました。しかし、結果はちょうど1回しか印刷されません。ただし、result2は30回印刷します。ここには何が欠けていますか?F#インフィクスオーバーロードが機能しない

答えて

9

オペレータの定義では、expは必ずしも関数である必要はありません。演算子を定義した方法は、expです。何も機能するexpパラメータを必要とし、あなたのオペレータの定義ではありませんので、これは、コンパイルしても、実行します

[0..1] ->>> 42 

:たとえば、あなたがこれを行うことができます。それ以外に何か

expをループの本体内で何度も繰り返し評価したい場合は、それを関数にしてループの本体が呼び出していることを確認する必要があります。あなたにはそれのための要件が​​ないので、最も簡単なものはunit -> 'aでしょう。彼らはこのように表現exp()機能を作り、タイプunitの値を意味 - 括弧exp

let (->>>) lst exp = for i in lst do exp() 

注意:あなたは本当にあなたがその使用から推論コンパイラを持つことができます、しかしその型を宣言する必要はありませんアプリケーション(すなわち、機能expは値()に適用されます)。

printf "hi"は機能ではないので、もちろんこの定義では[1..5] ->>> printf "hi"と書くことはできません。だから代わりに書く必要があります:

[1..5] ->>> (fun() -> printf "hi") 

これで5つの "hi"がプリントアウトされます。

これは、for .. doの構文が実際には言語の特別な部分であり、標準ライブラリで定義された「ただ別の機能」ではないためです。巧妙な関数や演算子の定義では、実際には同じ効果を作り出すことはできません。

関数と演算子よりも複雑な構文を作成する方法を知りたい場合は、computation expressionsを参照してください。

+0

ありがとうございます。この回答は高く評価されています。 – ozgur

+0

より現実的な解決策は、ラムダが要素を受け取るようにすることです: '... do exp i'。これは 'printf" hi%d "'を使うことを可能にし、不器用な 'fun i - >'ラップアラウンドを必要としません。 – bytebuster

+0

これはOPがやろうとしたことではありません。 –