我正在试图弄清楚修改报价,然后评估他们。在这里,我从basic开始,尝试使用Quotations api创建报价。引用绑定正常,但在求值时出现错误。
#r @"FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.dll"
#r @"FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.Linq.dll"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
open Microsoft.FSharp.Linq
let hardway =
Expr.Let(
new Var("x", typeof<int>),
Expr.Value(10),
Expr.GlobalVar("x").Raw)
hardway.EvalUntyped()
Binding session to 'FSharp.PowerPack.Linq.dll'...
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at Microsoft.FSharp.Collections.MapTreeModule.find[TValue,a](IComparer`1 comparer, TValue k, MapTree`2 m)
at Microsoft.FSharp.Linq.QuotationEvaluation.ConvExpr(ConvEnv env, FSharpExpr inp) in d:\codeplex\fspowerpack\May2010\src\FSharp.PowerPack.Linq\Linq.fs:line 459
at Microsoft.FSharp.Linq.QuotationEvaluation.ConvExpr(ConvEnv env, FSharpExpr inp) in d:\codeplex\fspowerpack\May2010\src\FSharp.PowerPack.Linq\Linq.fs:line 704
at Microsoft.FSharp.Linq.QuotationEvaluation.ConvExpr(ConvEnv env, FSharpExpr inp) in d:\codeplex\fspowerpack\May2010\src\FSharp.PowerPack.Linq\Linq.fs:line 677
at Microsoft.FSharp.Linq.QuotationEvaluation.CompileImpl[a](a e, Boolean eraseEquality) in d:\codeplex\fspowerpack\May2010\src\FSharp.PowerPack.Linq\Linq.fs:line 837
at Microsoft.FSharp.Linq.QuotationEvaluation.Expr.EvalUntyped(FSharpExpr ) in d:\codeplex\fspowerpack\May2010\src\FSharp.PowerPack.Linq\Linq.fs:line 854
at <StartupCode$FSI_0009>.$FSI_0009.main@()
Stopped due to error发布于 2010-11-18 23:17:26
要使用全局变量使其工作,您需要像这样编写它:
let hardway =
Expr.Let(
Var.Global("x", typeof<int>),
Expr.Value(10),
(Expr.GlobalVar<int>("x")) )
hardway.EvalUntyped() Var.Global和Expr.Global使用一些共享的全局变量字典,Stringer库使用这些字典来获得相同的变量实例,而无需显式地传递Stringer值(就像在F#的解决方案中一样)。
然而,我认为只创建Stringer值一次,然后保持对对象的引用(并在表达式中使用相同的对象)会导致代码更具可读性,因此我更喜欢Var的解决方案。
关于我的代码有几点:
Var.Global而不是new Var,因为第二个选项不在全局dictionary.Expr.GlobalVar中显式指定类型-如果您不这样做,F#将使用obj,这是一个不同的变量(它们按名称和类型进行索引)。发布于 2010-11-18 19:07:56
我不知道如何使用GlobalVar,所以我让别人来回答这个问题。以下是等待更好的解决方案的变通方法:
let hardway =
let v = new Var("x", typeof<int>)
Expr.Let(
v,
Expr.Value(10),
Expr.Var(v))
let res = hardway.EvalUntyped() // res is 10发布于 2011-07-09 03:17:55
Unquote有一个基于反射的自定义计算引擎,它允许您通过传入变量环境来计算合成报价,而不需要将变量绑定部分作为表达式本身的一部分。因此,您可以执行以下操作:
open Swensen.Unquote
open Microsoft.FSharp.Quotations
let unquoteway = Expr.Var(Var("x", typeof<int>))
let environment = Map.ofList [("x", box 10)]
unquoteway.Eval(environment)这很有趣,因为您传入的环境正是在整个表达式求值过程中用于所有变量绑定和解析的环境,因此遵守变量作用域规则:
let unquoteway =
Expr.NewTuple(
[Expr.Var(new Var("x", typeof<int>))
Expr.Let(new Var("x", typeof<string>), Expr.Value("hello"), Expr.Var(new Var("x", typeof<string>)))])
let environment = Map.ofList [("x", box 10)]
unquoteway.Eval(environment)
//FSI output:
val unquoteway : Expr = NewTuple (x, Let (x, Value ("hello"), x))
val environment : Map<string,obj> = map [("x", 10)]
val it : obj = (10, "hello")https://stackoverflow.com/questions/4213012
复制相似问题