2016-12-08 23 views
3

クエリ式の演算子の順序は重要ですか? Idkですが、場合によっては(一部の選択肢で)実行されますが、時にはそうではありません(または、暗黙的にいくつかの特定の機会を処理します)。F#クエリ式の演算子の順序

を選択すると、オペレータが最後に行く必要がありますか?あなたが最後の文としてそれを書いていないが、テイクのnの場合には、このオペレータは後に行くことができるならば、それは文句を言いほとんどすべての組み合わせで私はどのようにプロセスでちょうど興味

を選択執行行為?

これは別の質問につながります。反復可能なコレクションを反復して、最初の反復で何らかの1番目の値を選択した場合、の順序がその最初の値にどのように作用するのでしょうか?最初にシーケンスを返してからそのシーケンスで命令を実行するのは明らかですが、反復(?)ごとにsortByを実行するようです。私は、実行されたアルゴリズムの設計が何であるかに興味があります。

ここに、クエリ式の例を示します。

let sq = query { 
    for p in datasource do 
    where p.age>20 
    sortBy p.age 
    select p 
} 

説明を非常に感謝します。

おかげ

+2

この質問には正しくタグ付けされていますか?私はそれを標準のF#と認識しません。また、具体的なコード例は、一般的に多くの手助けをします。 –

+0

あまり説明はありませんが、おそらくhttps:// githubです。com/fsharp/fsharpであり、より具体的にはhttps://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/Query.fsおよびhttps://github.com/fsharp/fsharp/ blob/master/src/fsharp/FSharp.Core/Query.fsiまた、CEを初めてお使いの場合:https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/computation-expressions。 https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/query-expressions –

+0

@AntonSchwaighoferで細かいところを読んだとします。 /docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/query-expressions –

答えて

2

我々は見つけることができ、推測する必要はありません。

IL_006c: callvirt instance [...] For<class Program/Person,  
IL_0076: callvirt instance [...] SortBy<class Program/Person, 
IL_0080: callvirt instance [...] Where<class Program/Person,  
IL_008a: callvirt instance [...] Select<class Program/Person, 

IL_004e: newobj instance void Program/[email protected]::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) 
IL_0053: callvirt instance [...] For<class Program/Person,  
IL_005d: callvirt instance [...] Where<class Program/Person,  
IL_0067: callvirt instance [...] SortBy<class Program/Person, 
IL_0071: callvirt instance [...] Select<class Program/Person, 

は、我々は新しいILはなりSORTBY

let sq = query { 
    for p in sample do 
    sortBy p.age 
    where (p.age > 20)  
    select p 
} 

の順序を変更したと同様に生成されたILは、(クリーンアップ)になります

let sample = Seq.init 10 (fun i -> i * 10) |> Seq.map (fun i -> { age = i }) 
let sq = query { 
    for p in sample do 
    where (p.age > 20)  
    sortBy p.age 
    select p 
} 

sq |> Seq.toList |> ignore 

あなたは、それがクエリを定義する正確な順序。 クエリがExpressionの訪問者によって翻訳されるため、これはT-SQLの包摂については問題ありませんが、オブジェクトクエリの場合、クエリ式はほとんどあなたのための構文的な砂糖です。

1

方法#2:

あなたは副作用のための演算子が含まれるようにクエリ式モジュールを拡張することができます。これは単にInteractive ExtensionsのDoActionメソッドのポートです。

module QueryExtensions = 

    type QueryBuilderEx() = 
     inherit Linq.QueryBuilder() 

     [<CustomOperation("doAction", MaintainsVariableSpace = true)>] 
     member __.Do(source : Linq.QuerySource<'T,System.Collections.IEnumerable>, action) =    
      new Linq.QuerySource<'T,System.Collections.IEnumerable>(source.Source |> Seq.map (fun v -> action(v); v)) 


let query = QueryExtensions.QueryBuilderEx() 

今あなたがwhereの上に移動した場合、あなたはそれがフィルタリングする前にそれらのレコードを反映していることがわかりますので

let sq = query { 
     for p in sample do 
     sortBy p.age  
     where (p.age > 20)  
     doAction (printfn "Next -> %A") 
     select p 
    } 

のような順序をデバッグすることができます。

+0

@Astriは、 'query' [計算式](https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/computation-expressions)を拡張しています。この素晴らしい小さなトリックのために@astriをありがとう。 –

+0

@PhillipScottGivensあなたは大歓迎です!私が望む 'System.Interactive'には、FSharp' Seq'に来ることを望む多くの素敵な演算子があります。 – Asti