在 F# 2.0(即 Visual Studio 2010)中,没有办法扩展关键字列表(Ramon 的扩展除外)。但是,F# 3.0 (Visual Sutdio 11) 中的查询机制是可扩展的,您可以定义自己的关键字,类似于select
and count
。
这是一个基本示例,它使用关键字定义了诸如seq
builder之类的东西:reverse
type SeqBuilder() =
// Standard definition for 'for' and 'yield' in sequences
member x.For (source : seq<'T>, body : 'T -> seq<'R>) =
seq { for v in source do yield! body v }
member x.Yield item =
seq { yield item }
// Define an operation 'select' that performs projection
[<CustomOperation("select")>]
member x.Select (source : seq<'T>, [<ProjectionParameter>] f: 'T -> 'R) : seq<'R> =
Seq.map f source
// Defines an operation 'reverse' that reverses the sequence
[<CustomOperation("reverse", MaintainsVariableSpace = true)>]
member x.Expand (source : seq<'T>) =
List.ofSeq source |> List.rev
let mseq = SeqBuilder()
尚未记录其工作原理的详细信息,但该CustomOperation
属性表示该操作应被视为特殊语法(您可以设置各种属性以指定其行为方式 -MaintainsVariableSpace
意味着它不会更改序列内的值)。该Projectionparameter
属性指定关键字后面的表达式应隐式转换为函数。
现在,mseq
构建器同时支持select
和reverse
:
let q = mseq { for i in 1 .. 10 do
select (i + 100)
reverse }