扩展查询表达式

Dav*_*ave 8 f#

关于如何将新关键字扩展/添加到查询表达式,是否有任何文档或示例?这甚至可能吗?

例如,我想添加一个超前/滞后运算符.

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)

在这里,变量pname仍然之后访问where,因为where只有过滤输入,但它并没有在列表中变换的值.

最后,ProjectionParameter允许您说p.UnitValue > 100.0M实际上应该转换为获取上下文(可用变量)并计算此表达式的函数.如果未指定此属性,则操作只获取参数的值,如下所示:

query { for p in .. do
        take 10 }
Run Code Online (Sandbox Code Playgroud)

这里,参数10只是一个不能使用值的简单表达式p.


Dav*_*ave 6

非常酷的语言功能.刚刚实现了反向查询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)