samedi 27 juin 2015

F# Code Quotations: how to access variables of a lambda function internally?

I am having trouble at runtime in putting together a code quotation for a lambda function. Below is a highly simplified example to demonstrate the point. I have given the errors yielded at runtime (not compile time) underneath each attempt:

open FSharp.Quotations

// First Attempt
let exprFun (a:int) (b:int) :Expr<int> = <@ a+b @>
let q1:Expr<int->int->int> = <@ fun x y -> %(exprFun x y) @>        // NB: need to pass around and access `x` & `y` within a nested quotation expression
// error: The variable 'x' is bound in a quotation but is used as part of a spliced expression. This is not permitted since it may escape its scope. 

// Second Attempt
let x = new Var("x", typeof<int>)
let xe = Expr.Cast<int> ( Expr.Var(x) )
let y = new Var("y", typeof<int>)
let ye = Expr.Cast<int> ( Expr.Var(y) )
let q2 = Expr.Cast< int->int->int > ( Expr.Lambda(x, Expr.Lambda(y, <@ %(exprFun %xe %ye) @> )) )
// System.InvalidOperationException: first class uses of '%' or '%%' are not permitted

I am fully aware that this example doesn't require that the x & y variables be passed to exprFun but in my real-world example I need this behaviour as I am passing these variables into a complex recursive function that will return a Code Quotation/Expression itself.

Effectively, my requirement is that exprFun be able to access/manipulate these variables as part of the generation of the Code Quotation for the rhs of the lambda function being generated.

Aucun commentaire:

Enregistrer un commentaire