クエリ式に新しいキーワードを拡張/追加する方法に関するドキュメントや例はありますか? これは可能ですか?
たとえば、リード/ラグ演算子を追加したいと思います。
@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>
CustomOperation
属性は操作の名前を定義します。(非常に重要な) パラメータMaintainsVariableSpace
を使用すると、操作が入力として受け取るのと同じタイプの値を返すことができます。その場合、以前に定義した変数は操作後も引き続き使用できます。例えば:
query { for p in db.Products do
let name = p.ProductName
where (p.UnitPrice.Value > 100.0M)
select name }
ここでは、入力をフィルタリングするだけで、リスト内の値を変換しないため、変数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()
そして今、それが使われています。
let a = [1 .. 100]
let specialReverse =
query {
for i in a do
select i
reverse
}