计算 PowerPack 中的合成报价表达式时出错
我正在尝试修改报价然后评估它们。在这里,我从基础开始,只是尝试使用 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
I am trying to figure out to modify quotations and then evaluate them. Here I am starting basic and just trying to create a quotation using the Quotations api. The quotation binds OK, but I get an error when evaluating.
#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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
要使用全局变量使其工作,您需要这样编写:
Var.Global
和Expr.Global
使用 F# 引用的一些共享全局变量字典使用库可以获取相同的变量实例,而无需显式传递Var
值(如 Stringer 的解决方案)。但是,我认为仅创建一次
Var
值,然后保留对对象的引用(并在表达式中使用相同的对象)会导致代码更具可读性,因此我更喜欢 Stringer 的解决方案。关于我的代码的几点:
Var.Global
而不是new Var
因为第二个选项不会将变量存储在全局字典中。Expr.GlobalVar
中显式指定类型 - 如果您不这样做,F# 将使用obj
并且这是一个不同的变量(它们按名称 < 进行索引) em>和类型)。To get this working using global variables, you'd need to write it like this:
Var.Global
andExpr.Global
use some shared global dictionary of variables that the F# quotations library uses to make it possible to get the same variable instance without explicitly passingVar
values around (as in Stringer's solution).However, I think that creating
Var
value only once and then keeping a reference to the object (and ussing the same object in the expression) leads to more readable code, so I'd prefer Stringer's solution.A few points about my code:
Var.Global
instead ofnew Var
because the second option doesn't store the variable in the global dictionary.Expr.GlobalVar
- if you don't do that, F# will useobj
and that's a different variable (they are indexed by name and type).我不知道如何使用
GlobalVar
所以我让其他人回答这个问题。这是等待更好解决方案的解决方法:I don't know how to use
GlobalVar
so I let others answer on this. Here's a workaround in waiting for a better solution:Unquote 具有一个基于反射的自定义评估引擎,允许您通过传入一个变量环境,而不需要使变量绑定成为表达式本身的一部分。因此,您可以执行以下操作:
这很有趣,因为您传入的环境正是在整个表达式求值过程中用于所有变量绑定和解析的环境,因此变量作用域规则得到遵守:
Unquote has a custom reflection-based evaluation engine which allows you to evaluate synthetic quotations by passing in a variable environment rather than needing to make the variable binding part of the expression itself. So you could do the following:
This is interesting because the environment you pass in is the very environment used for all variable bindings and resolutions throughout the expression evaluation so variable scoping rules are honored: