如何在 FunScript 中传递 "Function" 类型?

How to pass a "Function" type in FunScript?

我遇到了需要传递给 JQueryAnimationOptions 对象的 Function 类型。我通常会将 lambda 传递给回调,但这些似乎 不兼容 。我在 FunScript 存储库中查找了所有可以找到的示例。并且找不到任何解决方法。

它还说 Function 在用作 return 语句 Error: Invalid use of interface type.

时实际上是一个接口(用于什么?)

那么如何使用这种 Function 类型传递回调参数?

代码:

[<FunScript.JS>]
module Main

open FunScript
open FunScript.TypeScript

let sayHelloFrom (name:string) = 
    Globals.window.alert("Hello, " + name)

let jQuery (selector:string) = Globals.jQuery.Invoke selector

let main() = 
    let options = createEmpty<JQueryAnimationOptions>()
    options.duration <- 3000
    options.complete <- (fun _ -> sayHelloFrom("F#")) 
    let properties = createEmpty<Object>()
    properties.Item("opacity") <- 1
    let mainContent = jQuery "#mainContent"
    mainContent.animate(properties, options) |> ignore
    mainContent.click(fun e -> sayHelloFrom("F#") :> obj)

没关系,我找到了解决方案,我必须 unbox lambda:

options.complete <- unbox<Function> (fun _ -> sayHelloFrom("F#"))

在 F# 和 C# 之间传递 lambda 时,这或多或少会像您预期的那样工作。在 F# 中,可以柯里化函数,而在 C#(和 JavaScript)中则不能。因此,当您需要将 lambda 从 F# 发送到 C# 时,您需要先对其进行转换。在 F# 中,这是通过像这样包装 lambda 来完成的:

open System.Linq
open System.Collections.Generic

let ar = [|1;2;3|]
let f = fun (x: int) (y: int) -> x + y
let acc = ar.Aggregate( System.Func<int,int,int>(f) )

其实F#编译器大部分时候都可以推导出类型,所以你只需要写:System.Func<_,_,_>(f)。此外,当将 F# lambda 传递给需要 C# lambda 的方法时,编译器会自动为您进行包装。那么前面的例子就变成了:

let ar = [|1;2;3|]
let acc = ar.Aggregate( fun x y -> x + y )

(当然,在这种情况下,使用惯用的 Array.reduce 会更好。这只是一个人为的例子。)

这在使用 FunScript 与 JS 交互时完全相同。您唯一需要注意的是 F# lambda 如何转换为 JS。为了允许柯里化,带有两个或更多参数的 lambda 像 fun x y -> x + y 变成:

function (x) {
    return function (y) {
        return x + y;
    }
}

这可能是个问题,因为原生 JS 需要以下签名:function (x, y)。在这种情况下,您必须像与 C# 交互时一样用 System.Func<_,_,_>() 包装 lambda(请记住,如果您将 lambda 传递给方法,这是自动完成的)。

然而,只有一个参数的 lambda 没有任何问题:fun x -> x*x 变成 function (x) { return x*x; }。在这种情况下,您不需要将它们包装起来(无论如何这样做都没有坏处)并且在必要时使用 unbox 来安抚 F# 编译器就足够了。请注意,FunScript 编译器会忽略最终 JS 代码中的 unbox,因此在运行时根本不会进行类型检查。

希望解释清楚。如果不是,请添加评论,我会编辑答案。