我希望我没有错过一些明显的东西,但我一直在玩 F# 表达式,我想即时评估引用的表达式。例如,我想写这样的东西:
let x = <@ 2 * 5 @>
let y = transform x // replaces op_Multiply with op_Addition, or <@ 2 + 5 @>
let z = eval y // dynamically evaluates y, returns 7
是否有可以评估引用表达式的内置 F# 方法,还是我必须自己编写?
我希望我没有错过一些明显的东西,但我一直在玩 F# 表达式,我想即时评估引用的表达式。例如,我想写这样的东西:
let x = <@ 2 * 5 @>
let y = transform x // replaces op_Multiply with op_Addition, or <@ 2 + 5 @>
let z = eval y // dynamically evaluates y, returns 7
是否有可以评估引用表达式的内置 F# 方法,还是我必须自己编写?
作为Unquote的一部分,我已经实现了一个基于反射的报价评估器(这是 2.0.0 版的新功能)。
> #r @"..\packages\Unquote.2.2.2\lib\net40\Unquote.dll"
--> Referenced '..\packages\Unquote.2.2.2\lib\net40\Unquote.dll'
> Swensen.Unquote.Operators.eval <@ sprintf "%A" (1,2) @>;;
val it : string = "(1, 2)"
我测得它比 PowerPack 的评估器快 50 倍。当然,这会因场景而异。但在解释表达式时,Unquote 通常比 PowerPack 快几个数量级。
它还支持比 PowerPack 的求值器更多的表达式,包括 VarSet、PropertySet、FieldSet、WhileLoop、ForIntegerRangeLoop 和 Quote。事实上,Unquote 的求值器支持除NewDelegate、AddressSet 和 AddressOf 之外的所有引用表达式,我计划最终支持所有这些表达式。
不,没有编译 F# 引用的内置方法。使用 PowerPack LINQ,您可以将一些引用转换为 .NET System.Linq.Expressions.Expression,并使用它来编译它们。
引用是为了允许对代码进行其他解释,例如针对 SQL 或 GPU 卡。
然而,在 hubfs 上的帖子中,有人暗示这是一个常见的请求,将予以关注。
Eval
您可以使用 DLL提供的扩展成员评估 F# 引用FSharp.PowerPack.Linq
,如下所示:
#r "FSharp.PowerPack.Linq.dll"
open Linq.QuotationEvaluation
let f = <@2 + 3@>
f.Eval()
请注意,您必须命名空间才能open
使Linq.QuotationEvaluation
此扩展成员可用。
还有一个Compile
扩展成员返回暂停,但似乎并没有提高性能。
2016年更新
现在Evaluate
可以在 NuGet 包中找到扩展方法FSharp.Quotations.Evaluator
#r "../packages/FSharp.Quotations.Evaluator.1.0.7/lib/net40/FSharp.Quotations.Evaluator.dll"
open FSharp.Quotations.Evaluator
let f = <@ 2 + 3 @>
f.Evaluate()
我认为引文有一个.eval()
方法。