2011-12-14 9 views
1

let ra = ResizeArray<int>()を考える:F#:Seq.forall weirdness?

Seq.forall (fun i -> 
        let q = i % 2 
        if 0 = q then ra.Add i 
        true) <| seq { 1..10 } 

私はra.Count戻り5、それを行う場合。

Seq.forall (fun i -> 
        let q = i % 2 
        if 0 = q then ra.Add i 
        0 = q) <| seq { 1..10 } 

私はra.Count0を返し、それを行う場合。

だから、ラムダ関数のすべての反復が真と評価されない限り、関数内のコードは実質的に実行されません。

ここでは何が起こっているのですか?

+8

[docs](http://msdn.microsoft.com/en-us/library/ee370522.aspx)の引用: "*アプリケーションが' false'を返す場合、全体的な結果は 'false'であり、それ以上はありません* " – ildjarn

+1

forall +副作用は悪い組み合わせです。 –

+0

@MauricioScheffer状況によって異なります。この場合(すなわち、機能の簡単な説明)、それは著しく実用的であった。 – MiloDC

答えて

5

Seq.forall関数の処理を中止するには、値 "false"を使用します。

1 % 2 = 0はfalseであるため、最初の繰り返しで評価が停止します。

+0

ありがとうございました。リストを完全に反復する必要があります。Seq.mapとSeq.forallを使用する必要がありますか? – MiloDC

+4

@MiloDC - あなたは 'Seq.iter'を考えましたか? –

+0

@JoelMuellerはい、ただしSeq.iterはユニットを返します。ラムダ関数のどれかがfalseに評価されたかどうかを知る必要があります。 Seq.map |> Seq.forallが私のために働いています。 – MiloDC

1

次のアプローチは、より多くの機能のようになります。

let (anyOdds, evens) = 
    seq {1..10} 
    |> Seq.fold (fun (anyOdds, xs) x -> 
     if x % 2 = 0 then 
      anyOdds, x :: xs 
     else true, xs) (false, []) 

は、特定の要件がない限り、彼らは一般的に効率的なF#のリストの賛成でResizeArray年代を捨てるために快適に感じます。

+0

皆さん、私の例は機能性を実証するために、本当に速く入力されました。私は実際に偶数を探す関数を実装していません。 :)(私の実際の機能は根本的に異なり、意図的に完全に無関係です。) – MiloDC

+2

私は理解していますが、副作用のない機能的な方法で行うことはできません。 –

+0

確かに、私は単純に、私の例(私の実際のプログラムの文脈では意味をなさない)を副作用を排除するために肛門保持的に調整することに興味がありませんでした。 – MiloDC