【问题标题】:Insert a variable value inside F# quotation在 F# 引号内插入变量值
【发布时间】:2014-03-31 13:06:49
【问题描述】:

所以我有一个名为 evalExpr 的函数,它接受引号 作为参数,并返回一个值。 例如,如果我写

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

那么,v 等于 111。

现在,我想在引号内放置一个字符串变量而不是表达式,但是这样做,变量是引号的一部分,因此没有定义。

如何在 F# 中的引号内使用变量值?

【问题讨论】:

标签: f# quotations


【解决方案1】:

Unquote 具有运算符evalWith : Map&lt;string,obj&gt; -&gt; Quotations.Expr&lt;'a&gt; -&gt; 'a,允许您使用提供变量值的环境映射来评估具有未绑定变量的合成报价。

首先,打开Swensen.Unquote 命名空间,使evalWith 运算符可用。

open Swensen.Unquote;;

接下来,构造一个表示x 类型的变量int 的引号:

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

接下来,用拼接的xvar构造一个引用:

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

现在您可以使用提供的变量x 评估您的报价q,如下所示:

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

答案是12

【讨论】:

  • 在代码valWith (Map.ofList [("x", box 2)]) q 框中,需要一个整数值。在我的示例中,我采用了更复杂的表达式。出于这个原因,用户将能够在输入中插入一个数字,然后它会处理计算。如果我插入一个字符串(如“2 + 2 * 2”),它不起作用,所以我没有解决问题。无论如何你为什么要放双;;? F# 甚至不需要它们。
  • 引号可以用文字字符串或综合构造,但没有现成的工具将 F# 代码的动态字符串转换为引号。但是你可以自己编写这样一个例程:即一个函数parse : string -&gt; Quotations.Expr,它将一个字符串解析为一个AST并从中构建一个引用。显然,您不会为整个 F# 语言编写解析器,而是为一种小型算术语言编写解析器。
  • 我使用了;;,因为我在 FSI 工作。您当然可以在 F# 源文件中省略它们。
  • 这似乎不适用于 Unquote 3.1.0 及更高版本。
  • @NikosBaxevanis 是的,不久前需要进行重大更改,新签名是 val inline evalWith : Map&lt;Var,obj&gt; -&gt; Quotations.Expr&lt;'a&gt; -&gt; 'a ...来自此问题:github.com/Microsoft/visualfsharp/issues/575
【解决方案2】:

目前尚不清楚您到底在要求什么,但也许这样的事情会有所帮助?

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 @>

【讨论】:

  • 我正在尝试在输入中获取表达式并使用该函数解决它。因此,输入中的表达式必须是一个字符串,由 Console.ReadLine() 获取。例如,如果我在输入“22 + 2 * 22 + 45”中插入,它应该像正常引用一样返回 111。无论如何,我无法使用此代码执行此操作,返回的结果是不支持的表达式。 x 和 y 从哪里取值?如何给输入取值?
猜你喜欢
  • 2021-12-24
  • 2020-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多