我在F#中使用引号来构建一个函数,该函数检查单个输入是否满足许多情况中的任何一种。也就是说,函数的主体类似于... || ... || ...,其中||s的数量是在运行时确定的。稍微简化一下,我现在的情况是
let vals = [|1..3|]
let currentfilter =
vals
|> Array.fold (fun acc i ->
<@ fun j -> (%acc) j || j = i @>)
<@ fun _ -> false @>生成树
val currentfilter : Expr<(int -> bool)> =
Lambda (j,
IfThenElse (Application (Lambda (j,
IfThenElse (Application (Lambda (j,
IfThenElse (Application (Lambda (_arg1,
Value (false)),
j),
Value (true),
Call (None,
op_Equality,
[j,
Value (1)]))),
j),
Value (true),
Call (None, op_Equality,
[j, Value (2)]))), j),
Value (true), Call (None, op_Equality, [j, Value (3)])))最优的情况是,我想要生成的更像是
Lambda (j,
IfThenElse (IfThenElse (Call (None, op_Equality, [j, Value (1)]),
Value (true),
Call (None, op_Equality, [j, Value (2)])),
Value (true), Call (None, op_Equality, [j, Value (3)])))(这是<@ fun j -> j = 1 || j = 2 || j = 3 @>生成的)
有什么简单的方法可以使第一个表达式变得更像第二个表达式呢?
发布于 2015-10-15 11:58:19
您可以编写代码,这样它就不会返回带引号的函数,而是返回在给定输入时生成引号的函数:
let vals = [|1..3|]
let currentfilter =
vals |> Array.fold (fun acc i ->
fun j -> <@ %(acc j) || %j = i @>)
(fun _ -> <@ false @>)在折叠中:
false表达式的函数。i进行比较的表达式组合在一起。现在,为了创建完整的引用函数,我们想编写如下内容:
<@ fun j -> %(currentfilter <@ j @>) @>遗憾的是,这是行不通的--因为F#编译器在这里有点严格,并且不允许我们编写变量j可以脱离其作用域的代码(非常合理,但很不幸)。
因此,您可以通过手动构造引号来编写此代码:
open Microsoft.FSharp.Quotations
let v = Var.Global("j", typeof<int>)
Expr.Lambda(v, currentfilter (Expr.Cast(Expr.Var(v))))https://stackoverflow.com/questions/33147688
复制相似问题