2
votes

so I have a function named evalExpr which accepts as argument a quotation <@ ... @> and it returns a value. For example if I write

let v = evalExpr <@ 22 + 2 * 22 + 45 @>

then, v is equal to 111.

Now, I want to place inside the quotations a string variable instead of the expressions, but doing this, the variable is part of the quotation and so not defined.

How can I use variable values inside quotations in F#?

2
What is the problem? You can use outer variables inside quotations, as shown here, for example: blog.ploeh.dk/2014/03/21/composed-assertions-with-unquote - Mark Seemann
Are you trying to say that you want to parse expression out of the string? - Dmitry Sevastianov

2 Answers

3
votes

Unquote features an operator evalWith : Map<string,obj> -> Quotations.Expr<'a> -> 'a that allows you to evaluate synthetic quotations with unbound variables using an environment map that provides the variable values.

First, open the Swensen.Unquote namespace to make the evalWith operator available.

open Swensen.Unquote;;

Next, construct a quotation which represents a variable x of type int:

let xvar : Quotations.Expr<int> = Quotations.Expr.Var(new Quotations.Var("x", typeof<int>)) |> Quotations.Expr.Cast;;

Next, construct a quotation with the xvar spliced in:

let q = <@ %xvar + 10 @>;;

Now you can evaluate your quotation q with the variable x provided like so:

evalWith (Map.ofList [("x", box 2)]) q;;

The answer is 12!

0
votes

It's unclear what exactly you're asking for, but maybe something like this would help?

type Vars<'a> private () =
    static let dict = System.Collections.Generic.Dictionary<string,Quotations.Var>()
    static member Var(nm) = 
        match dict.TryGetValue nm with
        | true, v -> v
        | _ -> 
            let v = Quotations.Var(nm, typeof<'a>)
            dict.[nm] <- v
            v

[<GeneralizableValue>]
let x<'a> : Quotations.Expr<'a> = Quotations.Expr.Var(Vars<'a>.Var "x") |> Quotations.Expr.Cast

[<GeneralizableValue>]
let y<'a> : Quotations.Expr<'a> = Quotations.Expr.Var(Vars<'a>.Var "y") |> Quotations.Expr.Cast


let q1 = <@ %x + %y * (1 + %x) @>

let q2 = <@ "test" + %x @>