我正在编写一个快速的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))
// ...
我已明确注释了要澄清的类型。
我无法弄清楚如何在没有lambda的情况下调用measureSelectTimes
。我想将ids
部分应用于此ids |> Seq.map measureSelectTimes
,但后来我不知道如何处理生成的部分应用函数,然后映射到cmds
。这是什么语法?
答案 0 :(得分:8)
您可以使用Seq.map2
:
Seq.map2 measureSelectTimes ids cmds
或者
(ids, cmds) ||> Seq.map2 measureSelectTimes
答案 1 :(得分:3)
您的measureSelectTimes
函数将两个参数作为单独的参数,但您需要一个将它们作为元组的函数。一种选择是只更改函数以获取元组(如果参数被逻辑化是合乎逻辑的)。
或者,您可以编写一个cobinator,将一个带有两个参数的函数转换为一个带元组的函数。这通常称为uncurry
,它以某种函数语言存在:
let uncurry f (a, b) = f a b
然后你可以写:
input |> Seq.map (uncurry measureSelectTimes)
对于像这样的简单使用看起来没问题,但我认为在F#中使用组合器太多不是一个好主意,因为它使代码难以为经验不足的函数式程序员阅读。我可能会写这样的东西(因为我发现它更具可读性):
[ for (time1, time2) in input -> measureSelectTimes time1 time2 ]
答案 2 :(得分:0)
一种方法是将measureSelectTimes
的签名更改为
(Guid list * Guid list) * IDbCommand -> TimeSpan * TimeSpan
然后,您可以将map
调用更改为
let results = input |> Seq.map measureSelectTimes
// or
let results = Seq.map measureSelectTimes input