构建平面引用 lambda
Building flat quoted lambda
我在 F# 中使用引号来构建一个函数,该函数检查单个输入是否满足多种情况中的任何一种。也就是说,函数体类似于 ... || ... || ...
,其中 ||
的数量在运行时确定。稍微简化一下,我现在有的是
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 @>
生成)
是否有任何简单的方法可以使第一个表达式变平,使其看起来更像第二个?
您可以编写代码,使其不 return 引用函数 而是 return 一个 函数 在给定输入时生成报价:
let vals = [|1..3|]
let currentfilter =
vals |> Array.fold (fun acc i ->
fun j -> <@ %(acc j) || %j = i @>)
(fun _ -> <@ false @>)
折叠:
- 初始值是returns
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))))
我在 F# 中使用引号来构建一个函数,该函数检查单个输入是否满足多种情况中的任何一种。也就是说,函数体类似于 ... || ... || ...
,其中 ||
的数量在运行时确定。稍微简化一下,我现在有的是
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 @>
生成)
是否有任何简单的方法可以使第一个表达式变平,使其看起来更像第二个?
您可以编写代码,使其不 return 引用函数 而是 return 一个 函数 在给定输入时生成报价:
let vals = [|1..3|]
let currentfilter =
vals |> Array.fold (fun acc i ->
fun j -> <@ %(acc j) || %j = i @>)
(fun _ -> <@ false @>)
折叠:
- 初始值是returns
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))))