【发布时间】:2021-09-16 13:07:05
【问题描述】:
作为爱好项目的一部分,我想动态创建一个函数,当提供浮点数组时,它可以使用数组元素执行一些算术并返回结果。
请注意,该函数必须在运行时创建。
我相信这可以通过使用 FSharp.Quotations.Expr 模块构造一个 lambda 表达式来完成。
举个简单的例子:
fun (arr: float array) -> 2.0 * arr.[0]
我可以使用以下代码引用重新创建它:
<@ fun (arr: float array) -> 2.0 * arr.[0] @>
将其打印到控制台会产生:
Lambda (arr,
Call (None, op_Multiply,
[Value (2.0), Call (None, GetArray, [arr, Value (0)])]))
我可以看到提到的GetArray 是位于FSharp.Core.LanguagePrimitives.IntrinsicFunctions.GetArray 的那个。
我的问题是... 如何在运行时创建Call (None, GetArray, [arr, Value (0)])?
到目前为止,我的(令人尴尬的)尝试是:
open System
open FSharp.Quotations
let arr = Var("arr", typeof<float array>, false)
let getArray = FSharp.Core.LanguagePrimitives.IntrinsicFunctions.GetArray.GetType().GetMethods().[0]
Expr.Lambda(arr, Expr.Call(getArray, [Expr.Var(arr); Expr.Value(0)]))
这会产生以下异常:
System.ArgumentException:“构建“args”时的类型不匹配:方法或索引器属性的参数无效。应为“System.Object[]”,但收到类型“System.Double[]”。
鉴于GetArray 看起来是一个通用函数,我不清楚为什么会这样。
我显然误解了这里相当基本的东西!
感谢您提供的任何建议。
【问题讨论】:
标签: f# metaprogramming