Extending Query Expressions

f#

Solution

In addition to the query builder for the Rx Framework mentioned by @pad, there is also a talk by Wonseok Chae from the F# team about Computation Expressions that includes query expressions. I'm not sure if the meeting was recorded, but there are very detailed slides with a cool example on query syntax for generating .NET IL code.

The source code of the standard F# query builder is probably the best resource for finding out what types of operations are supported and how to annotate them with attributes.

The key attributes that you'll probably need are demonstrated by the `where` clause:

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

The `CustomOperation` attribute defines the name of the operation. The (quite important) parameter `MaintainsVariableSpace` allows you to say that the operation returns the same type of values as it takes as the input. In that case, the variables defined earlier are still available after the operation. For example:

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

Here, the variables `p` and `name` are still accessible after `where` because `where` only filters the input, but it does not transform the values in the list.

Finally, the `ProjectionParameter` allows you to say that `p.UnitValue > 100.0M` should actually be turned into a function that takes the context (available variables) and evaluates this expression. If you do not specify this attribute, then the operation just gets the value of the argument as in:

query { for p in .. do
        take 10 }

Here, the argument `10` is just a simple expression that cannot use values in `p`.

Problem

Are there any documents or examples out there on how one can extend/add new keywords to query expressions? Is this even possible? For example, I'd like to add a lead/lag operator.

Original source

Related problems