Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 扩展查询表达式_F# - Fatal编程技术网

F# 扩展查询表达式

F# 扩展查询表达式,f#,F#,有没有关于如何向查询表达式扩展/添加新关键字的文档或示例?这可能吗 例如,我想添加一个超前/滞后运算符。除了@pad提到的,还有来自F#团队的Wonseok Chae关于包含查询表达式的计算表达式的演讲。我不确定会议是否被录制,但有一个关于生成.NET IL代码的查询语法的很酷的例子 对于找出支持哪些类型的操作以及如何使用属性对其进行注释,可能是最好的资源 where子句演示了您可能需要的关键属性: [<CustomOperation("where",MaintainsVariableSp

有没有关于如何向查询表达式扩展/添加新关键字的文档或示例?这可能吗

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

除了@pad提到的,还有来自F#团队的Wonseok Chae关于包含查询表达式的计算表达式的演讲。我不确定会议是否被录制,但有一个关于生成.NET IL代码的查询语法的很酷的例子

对于找出支持哪些类型的操作以及如何使用属性对其进行注释,可能是最好的资源

where
子句演示了您可能需要的关键属性:

[<CustomOperation("where",MaintainsVariableSpace=true,AllowIntoPattern=true)>]
member Where : 
  : source:QuerySource<'T,'Q> * 
    [<ProjectionParameter>] predicate:('T -> bool) -> QuerySource<'T,'Q>
在这里,变量
p
name
where
之后仍然可以访问,因为
where
仅过滤输入,而不转换列表中的值

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

query { for p in .. do
        take 10 }

这里,参数
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()

看一看。我的答案中的最后一个链接可能会引起您的兴趣。也许值得一提的是,这些可以是标准查询生成器类型上的扩展方法。非常酷!谢谢你的链接。有趣的是,可以使用现有的linq扩展来实现他们在这里想要的功能。@kvb这太酷了!但是,您还需要补充的是,它们不会与LINQ to SQL和LINQ to Entities的标准提供程序一起工作:-((除非您编写一些预处理器,将它们转换为表达式树中支持的其他内容?)是的,它们只适用于IEnumerables,而不适用于IQueryables。这可以通过确保输入和输出类型更加具体来实现(参见我对davewolfs的其他答案的评论)。请注意,您可能希望在您拥有
'Q
的两个位置都使用
System.Collections.IEnumerable
,因为标准IQueryable提供程序不知道如何处理您的操作,如果使用它,将抛出运行时异常。它似乎运行良好,但会添加。您能更详细地解释一下吗?他们知道如何处理吗处理?基本上,IQueryable提供程序针对带引号的查询版本工作,并且只识别内置运算符。因此,如果执行类似于
query的操作{for x in myDatabaseTable do reverse}
其中
myDatabaseTable
是LINQ表,则查询在运行时将失败。如果将
'Q
类型参数限制为
IEnumerable
,则查询将在运行时成功,但在客户端运行所有逻辑(而不是尝试生成服务器端查询)。
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
    }