1

私は簡単な DB パフォーマンス テストを作成しており、より多くの練習ができるように F# を選択しました。

measureSelectTimes署名を持つメソッド を作成しましたGuid list * Guid list -> IDbCommand -> TimeSpan * TimeSpan

次に、私はそれを呼び出します:

let runTests () =
    let sqlCeConn : IDbConnection = initSqlCe() :> IDbConnection
    let sqlServerConn : IDbConnection = initSqlServer() :> IDbConnection
    let dbsToTest = [ sqlCeConn; sqlServerConn ]
    let cmds : seq<IDbCommand> = dbsToTest |> Seq.map initSchema
    let ids : seq<Guid list * Guid list> = cmds |> Seq.map loadData
    let input = Seq.zip ids cmds
    let results = input |> Seq.map (fun i -> measureSelectTimes (fst i) (snd i))
    // ...

明確にするために、型で明示的に注釈を付けました。

私が理解できないのはmeasureSelectTimes、ラムダなしで呼び出す方法です。idsこのように を部分的に適用したいのですが、ids |> Seq.map measureSelectTimes部分的に適用された結果の関数を にマッピングする方法がわかりませんcmds。これの構文は何ですか?

4

3 に答える 3

9

使用できますSeq.map2

Seq.map2 measureSelectTimes ids cmds

または

(ids, cmds) ||> Seq.map2 measureSelectTimes
于 2011-05-25T17:57:04.540 に答える
3

関数measureSelectTimesは 2 つの引数を個別の引数として受け取りますが、代わりにそれらをタプルとして受け取る関数が必要です。1 つのオプションは、タプルを取るように関数を変更することです (引数をタプルにすることが論理的である場合)。

別の方法として、2 つの引数を取る関数をタプルを取る関数に変換するコビネータを作成することもできます。これは通常呼び出されuncurry、関数型言語で存在します。

let uncurry f (a, b) = f a b

次に、次のように記述できます。

input |> Seq.map (uncurry measureSelectTimes)

これは、このような単純な使用には問題ないように見えますが、F# でコンビネーターを使いすぎると、経験の浅い関数型プログラマーにとってコードが読みにくくなるため、お勧めできません。私はおそらくこのようなものを書くでしょう(より読みやすいと思うので):

[ for (time1, time2) in input -> measureSelectTimes time1 time2 ]
于 2011-05-25T17:53:51.840 に答える
0

1 つのアプローチは、署名をに変更するmeasureSelectTimesことです。

(Guid list * Guid list) * IDbCommand -> TimeSpan * TimeSpan

map次に、呼び出しを次のように変更できます

let results = input |> Seq.map measureSelectTimes
// or
let results = Seq.map measureSelectTimes input
于 2011-05-25T17:56:36.920 に答える