扩展查询表达式

时间:2012-12-11 21:21:34

标签: f#

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

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

2 个答案:

答案 0 :(得分:13)

除了@pad提到的query builder for the Rx Framework之外,还有来自F#团队的Wonseok Chae关于包含查询表达式的计算表达式的讨论。我不确定会议是否已录制,但very detailed slides有一个关于生成.NET IL代码的查询语法的很酷示例。

source code of the standard F# query builder可能是查找支持哪些类型的操作以及如何使用属性注释它们的最佳资源。

where子句证明了您可能需要的关键属性:

[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where : 
  : source:QuerySource<'T,'Q> * 
    [<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>

CustomOperation属性定义操作的名称。 (非常重要的)参数MaintainsVariableSpace允许您说操作返回与输入相同类型的值。在这种情况下,之前定义的变量在操作后仍然可用。例如:

query { for p in db.Products do
        let name = p.ProductName
        where (p.UnitPrice.Value > 100.0M)
        select name }

此处,变量pname仍可在where之后访问,因为where仅过滤输入,但不会转换列表中的值。< / p>

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

query { for p in .. do
        take 10 }

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

答案 1 :(得分: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()

现在正在使用它。

let a = [1 .. 100]

let specialReverse = 
    query {
        for i in a do
        select i
        reverse
    }