FSharp.Quotations.Evaluator


F# Quotations Evaluator Tutorial

To reference the library:

1: 
2: 
3: 
#r "FSharp.Quotations.Evaluator.dll"
open FSharp.Quotations.Evaluator
open FSharp.Quotations

Evaluation

To evaluate a strongly typed quotation:

1: 
QuotationEvaluator.Evaluate <@ 1 + 1 @>  // 2

To evaluate a weakly typed quotation, use EvaluateUntyped. An object is returned, which you can cast to the expected type when it is known.

1: 
2: 
3: 
4: 
5: 
6: 
let evalTuple n = 
    let v = Expr.NewTuple (List.replicate n (Expr.Value n)) // codegen (fun x -> (x,x))
    v.EvaluateUntyped() 

evalTuple 4 // obj = (4,4,4,4)
evalTuple 5 // obj = (5,5,5,5,5)

Compilation

All evaluation is currently done via compilation. In the future some evalaution may be done via interpretation. To force compilation, use "Compile".

1: 
2: 
3: 
let addPlusOne = QuotationEvaluator.Evaluate <@ fun x y -> x + y + 1 @> 

let nine = addPlusOne 3 5 // 9

Extension methods

Extension methods are available for compilation and evaluation:

1: 
2: 
3: 
let onePlusOneExpression = <@ 1 + 1 @>  //  2

onePlusOneExpression.Evaluate()

On-the-fly code generation

You can generate lambdas and compile them dynamically:

1: 
2: 
3: 
4: 
5: 
6: 
let tupler = 
    let v = Var("x",typeof<int>)
    let v = Expr.Lambda(v, Expr.NewTuple [Expr.Var v; Expr.Var v]) // codegen (fun x -> (x,x))
    v.CompileUntyped() :?> (int -> (int * int))

tupler 78  // (78, 78)

In this example, we generate a lambda (fun x -> (x,...,x)) for tuple size N:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
let invokeFunctionDynamic (f: obj) (x:obj) = 
    // Invoke an F# function dynamically
    f.GetType().InvokeMember("Invoke",System.Reflection.BindingFlags.InvokeMethod,null,f,[| box x |])

let makeTupler n = 
    let xVar = Var("x",typeof<int>)
    let lambdaExpr = Expr.Lambda(xVar, Expr.NewTuple (List.replicate n (Expr.Var xVar))) // codegen (fun x -> (x,...,x))
    let compiledLambda = lambdaExpr.CompileUntyped() 
    fun (v:int) -> 
        // Invoke the function dynamically
        invokeFunctionDynamic compiledLambda v

// tupler4 and tupler7 are compiled functions which can be invoked with different arguments
let tupler4 = makeTupler 4
let tupler7 = makeTupler 7

tupler4 76 // (76, 76, 76, 76)
tupler4 63 // (63, 63, 63, 63)
tupler7 65 // (65, 65, 65, 65, 65, 65, 65)

Convert to LINQ expressions

1: 
2: 
3: 
4: 
5: 
let onePlusTwoExpression = <@ 1 + 2 @>  //  2

let expressionTree = onePlusTwoExpression.ToLinqExpressionUntyped() // an expression tree

expressionTree.ToString() // "(1 + 2)"
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Quotations

--------------------
namespace Microsoft.FSharp.Quotations
namespace FSharp.Quotations.Evaluator
type QuotationEvaluator =
  static member CompileUntyped : Expr -> obj
  static member Evaluate : Expr<'T> -> 'T
  static member EvaluateUntyped : Expr -> obj
  static member private EvaluateUntypedUsingQueryApproximations : Expr -> obj
  static member ToLinqExpression : Expr -> Expression
static member QuotationEvaluator.Evaluate : Expr<'T> -> 'T
val evalTuple : n:int -> obj
val n : int
val v : Expr
Multiple items
type Expr =
  override Equals : obj:obj -> bool
  member GetFreeVars : unit -> seq<Var>
  member Substitute : substitution:(Var -> Expr option) -> Expr
  member ToString : full:bool -> string
  member CustomAttributes : Expr list
  member Type : Type
  static member AddressOf : target:Expr -> Expr
  static member AddressSet : target:Expr * value:Expr -> Expr
  static member Application : functionExpr:Expr * argument:Expr -> Expr
  static member Applications : functionExpr:Expr * arguments:Expr list list -> Expr
  ...

--------------------
type Expr<'T> =
  inherit Expr
  member Raw : Expr
static member Expr.NewTuple : elements:Expr list -> Expr
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
    interface IReadOnlyList<'T>
    interface IReadOnlyCollection<'T>
    interface IEnumerable
    interface IEnumerable<'T>
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    member Tail : 'T list
    ...
val replicate : count:int -> initial:'T -> 'T list
static member Expr.Value : value:'T -> Expr
static member Expr.Value : value:obj * expressionType:System.Type -> Expr
member Expr.EvaluateUntyped : unit -> obj
val addPlusOne : (int -> int -> int)
val x : int
val y : int
val nine : int
val onePlusOneExpression : Expr<int>
member Expr.Evaluate : unit -> 'T
val tupler : (int -> int * int)
val v : Var
Multiple items
type Var =
  interface IComparable
  new : name:string * typ:Type * ?isMutable:bool -> Var
  member IsMutable : bool
  member Name : string
  member Type : Type
  static member Global : name:string * typ:Type -> Var

--------------------
new : name:string * typ:System.Type * ?isMutable:bool -> Var
val typeof<'T> : System.Type
Multiple items
val int : value:'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
static member Expr.Lambda : parameter:Var * body:Expr -> Expr
static member Expr.Var : variable:Var -> Expr
member Expr.CompileUntyped : unit -> obj
val invokeFunctionDynamic : f:obj -> x:obj -> obj
val f : obj
type obj = System.Object
val x : obj
System.Object.GetType() : System.Type
namespace System
namespace System.Reflection
type BindingFlags =
  | Default = 0
  | IgnoreCase = 1
  | DeclaredOnly = 2
  | Instance = 4
  | Static = 8
  | Public = 16
  | NonPublic = 32
  | FlattenHierarchy = 64
  | InvokeMethod = 256
  | CreateInstance = 512
  ...
field System.Reflection.BindingFlags.InvokeMethod: System.Reflection.BindingFlags = 256
val box : value:'T -> obj
val makeTupler : n:int -> (int -> obj)
val xVar : Var
val lambdaExpr : Expr
val compiledLambda : obj
val v : int
val tupler4 : (int -> obj)
val tupler7 : (int -> obj)
val onePlusTwoExpression : Expr<int>
val expressionTree : System.Linq.Expressions.Expression
member Expr.ToLinqExpressionUntyped : unit -> System.Linq.Expressions.Expression
System.Linq.Expressions.Expression.ToString() : string
F# Project
Fork me on GitHub