查询表达式运算符的顺序是否重要? Idk,但有时(在某些选择中)它确实如此,但有时它不会(或者它可能会隐式处理某些特定场合)。
强烈要求选择运算符必须最后?如果你不把它写成最后一个陈述,它会抱怨几乎所有的组合,但是如果取n ,这个操作员可以追求选择
我只对执行过程如何行动感兴趣?
这让我想到另一个问题。如果它迭代Iterable集合,那么在第一次迭代时它会选择一个(第一个)值, order 如何对那个(第一个)值起作用?很明显,如果它首先返回序列,然后在该序列上执行顺序..但似乎它在每次迭代(?)处执行 sortBy 。我对执行算法的设计感兴趣。
以下是我的查询表达示例。
let sq = query {
for p in datasource do
where p.age>20
sortBy p.age
select p
}
非常感谢解释。
由于
答案 0 :(得分:3)
我们不需要猜测,我们可以找到。
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
生成的IL(已清理)看起来像
IL_004e: newobj instance void Program/sq@16::.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,
假设我们改变了sortBy的顺序
let sq = query {
for p in sample do
sortBy p.age
where (p.age > 20)
select p
}
新的IL将是:
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,
您可以清楚地看到它遵循您定义查询的确切顺序。 这对于T-SQL理解并不重要,因为查询将由Expression访问者翻译,但对于对象查询,查询表达式几乎只是你的语法糖。
答案 1 :(得分: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()
现在您可以像这样调试订单
let sq = query {
for p in sample do
sortBy p.age
where (p.age > 20)
doAction (printfn "Next -> %A")
select p
}
如果您将其移到where
之上,您会在过滤前看到它会反映这些记录。