Tom*_*cek 13
除了@pad提到的Rx框架的查询构建器之外,还有来自F#团队的Wonseok Chae关于包含查询表达式的计算表达式的讨论.我不确定会议是否被录制,但是有非常详细的幻灯片,其中有一个关于生成.NET IL代码的查询语法的很酷示例.
标准F#查询构建器的源代码可能是查找支持哪些类型的操作以及如何使用属性注释它们的最佳资源.
您可能需要的关键属性由以下where
子句演示:
[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where :
: source:QuerySource<'T,'Q> *
[<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
Run Code Online (Sandbox Code Playgroud)
该CustomOperation
属性定义操作的名称.(非常重要的)参数MaintainsVariableSpace
允许您说操作返回与输入相同类型的值.在这种情况下,之前定义的变量在操作后仍然可用.例如:
query { for p in db.Products do
let name = p.ProductName
where (p.UnitPrice.Value > 100.0M)
select name }
Run Code Online (Sandbox Code Playgroud)
在这里,变量p
和name
仍然之后访问where
,因为where
只有过滤输入,但它并没有在列表中变换的值.
最后,ProjectionParameter
允许您说p.UnitValue > 100.0M
实际上应该转换为获取上下文(可用变量)并计算此表达式的函数.如果未指定此属性,则操作只获取参数的值,如下所示:
query { for p in .. do
take 10 }
Run Code Online (Sandbox Code Playgroud)
这里,参数10
只是一个不能使用值的简单表达式p
.
非常酷的语言功能.刚刚实现了反向查询QuerySource.
简单的例子,但只是一个演示.
module QueryExtensions
type ExtendedQueryBuilder() =
inherit Linq.QueryBuilder()
/// Defines an operation 'reverse' that reverses the sequence
[<CustomOperation("reverse", MaintainsVariableSpace = true)>]
member __.Reverse (source : Linq.QuerySource<'T,System.Collections.IEnumerable>) =
let reversed = source.Source |> List.ofSeq |> List.rev
new Linq.QuerySource<'T,System.Collections.IEnumerable>(reversed)
let query = ExtendedQueryBuilder()
Run Code Online (Sandbox Code Playgroud)
现在它被使用了.
let a = [1 .. 100]
let specialReverse =
query {
for i in a do
select i
reverse
}
Run Code Online (Sandbox Code Playgroud)