F# Code Quotations

The code quotations feature enables you to generate and work with F# code expressions programmatically.

  • It generates an abstract syntax tree that represents F# code.
  • The abstract syntax tree can then be traversed and processed according to the needs of your application.
  • For example, you can use the tree to generate F# code or generate code in some other language.

Quoted Expressions

A quoted expression is delimited in such a way that it is not compiled as part of your program, but is compiled into an object that represents an F# expression.

  • You can mark a quoted expression either with type information or without type information.
  • If you want to include type information, you use the symbols <@ and @> to delimit the quoted expression.
  • If you do not need type information, you use the symbols <@@ and @@>.

The following code shows typed and untyped quotations.

open Microsoft.FSharp.Quotations

// A typed code quotation.
let expr1 : Expr<float> = <@ 9.0 * 3.9 + 4.2 @>

// An untyped code quotation.
let expr2 : Expr = <@@ 9.0 * 3.9 + 4.2 @@>

The resulting type of an expression quoted with the typed symbols is Expr<'T>, where the type parameter has the type of the expression as determined by the F# compiler's type inference algorithm.

  • When you use code quotations without type information, the type of the quoted expression is the non-generic type Expr.
  • You can call the Raw property on the typed Expr class to obtain the untyped Expr object.

To evaluate F# quotations, you must use the F# Quotation Evaluator.

  • It provides support for evaluating and executing F# expression objects.
  • F# quotations also retain type constraint information.

The following example shows how to evaluate F# quotations.

open FSharp.Linq.RuntimeHelpers

let eval q = LeafExpressionConverter.EvaluateQuotation q

let inline negate x = -x
// val inline negate: x: ^a ->  ^a when  ^a : (static member ( ~- ) :  ^a ->  ^a)

<@ negate 1.0 @>  |> eval

The constraint generated by the inline function is retained in the code quotation. The negate function's quoted form can now be evaluated.

Splicing Operators

The splicing operators enable you to combine literal code quotations with expressions that you have created programmatically or from another code quotation.

  • The % and %% operators enable you to add an F# expression object into a code quotation.
  • You can use the % operator to insert a typed expression object into a typed quotation and the %% operator to insert an untyped expression object into an untyped quotation.

If an expr is an untyped expression of type Expr, the following code is valid.

<@@ 3 + %%expr @@>

But if expr is a typed quotation of type Expr<int>, the following code is valid.

<@ 3 + %expr @>