如何传递"功能"输入FunScript?

时间:2015-01-05 09:38:00

标签: f# funscript

我遇到了需要传递给Function对象的JQueryAnimationOptions类型。我通常会将lambda传递给回调,但这些似乎是不兼容。我查看了我在FunScript仓库中找到的每个样本。并找不到任何解决方法。

当用作返回语句Function时,它还说Error: Invalid use of interface type实际上是一个接口(用于什么?)。

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

enter image description here

代码:

[<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)

2 个答案:

答案 0 :(得分:2)

在F#和C#之间传递lambda时,这或多或少都有所作为。在F#中,函数可以被curry,而在C#(和JavaScript)中则不能。因此,当您需要将F#中的lambda发送到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#lambdas如何被翻译成JS。为了允许currying,具有两个或更多参数(如fun x y -> x + y)的lambda变为:

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

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

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

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

答案 1 :(得分:0)

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

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