在F#中以编程方式构建lambda表达式

时间:2014-09-11 12:59:10

标签: f# quotations

让我们有以下功能定义:

module Helpers =

    [<ReflectedDefinition>]
    let dummy (x:int) = x.ToString()

通过使用以下引用,我们将其表示为lambda表达式:

<@ dummy @>;;

val it : Expr<(int -> string)> =
Lambda (x, Call (None, dummy, [x]))

this previous question中,声明引号代表语法引用的代码,这意味着我们无法通过在同一函数中包含相同的函数来获得相同的表达式:

let qwrap f = <@ f @>
qwrap dummy;;

val it : Expr<(int -> string)> =
Value (<fun:it@6-3>)

是否有可能以编程方式构建前一个表达式(Lambda(x,Call(None,dummy,[x]))?目标是为简单函数实现动态qwrap(&#39; a - &gt;&#39; b)。得到的表达式将被分析,我感兴趣的是能够保留函数和args名称,因为它们是在原始函数中编写的。

1 个答案:

答案 0 :(得分:2)

为了确保我正确理解你的问题,你想写一些包装函数的函数(可能表示为引用)并在其周围添加一些其他东西?

qwrap函数返回Value的原因是<@ f @>只创建一个代表f值的引号并将其作为对象嵌入 - 它不是知道f是什么。

如果要创建包含其他引用的引用,则您的参数f也必须是引号。然后,您可以使用<@ %f @>创建包含原始引文的新引文(%语法是拼接运算符)。

这是一个添加检查零的简单示例:

let qwrap f = 
  <@ fun x -> 
      if x = 0 then failwith "No!" 
      else (%f) x @>

您可以使用任何带引号的函数作为参数调用qwrap

let dummy (x:int) = x.ToString()
qwrap <@ dummy @>