寓言 F# 到 Javascript:无参数函数在引用时被赋予参数

Fable F# to Javascript: Parameterless functions being given a parameter when referenced

我在 Fable 中引用无参数函数时遇到困难。

以这个例子:

let f1 () = 
    1

let someRefTof1 = f1

我希望生成的 js 看起来像这样:

function f1() {
    return 1;
}

var someRefTof1 = f1;

但我实际得到的是:

function f1() {
    return 1;
}

var someRefTof1 = exports.someRefTof1 = function someRefTof1(arg00_) {
    return f1(arg00_);
};

我不清楚 arg00_ 的目的或如何避免生成它?

(作为背景知识,我正在努力调用外部 js 库中的函数,该库希望将函数作为参数传递)


编辑:

背景

以上是我认为是对我的问题的最小的、可验证的复制,但在评论之后,我认为提供更多关于为什么这会导致问题的上下文可能是有用的。我实际上想做的是使用 Fable 中的 angularjs。

所以我的例子看起来更像这样:

let app = AngularFable.NgFable.angular.``module``("app",[||])

type TestCtrl() = 
    member this.Val1() = "boom";

app?controller("test", TestCtrl)

编译为:

var app = exports.app = angular.module("app", []);

var TestCtrl = exports.TestCtrl = function () {
    function TestCtrl() {
        _classCallCheck(this, TestCtrl);
    }

    TestCtrl.prototype.Val1 = function Val1() {
        return "boom";
    };

    return TestCtrl;
}();

_fableCore.Util.setInterfaces(TestCtrl.prototype, [], "App.TestCtrl");

app.controller("test", function (unitVar) {
    return new TestCtrl();
});

其中 unitVar 是本例中引入的有问题的参数。当我在我的 html 中使用它时:

  <div ng-app="app">
    <div ng-controller="test as vm">
      {{vm.Val1()}}
    </div>
  </div>

I 运行 进入 unknown provider 错误,而如果我只是更改编译的 javascript 以从最后一行删除 unitVar 参数,如下所示:

app.controller("test", function () {
    return new TestCtrl();
});

然后我的示例按预期工作。

我很想知道是否有办法避免 Fable 编译器生成此参数。我 99% 确定这会归结为与我原来的问题相同的问题,但我包含了这个额外的上下文以更好地解释为什么这是一个问题

非常感谢您的提问和详细的解释。这里有两件事有点棘手,它们是由 F# 编译器和 Fable 的优化引起的。

  • 在 F# 编译器提供的 AST 中,方法(作为类型或模块成员的函数)被编译为 普通 方法,与 C# 中一样。这是为了优化。
  • 但是,当您创建匿名 lambda 或对方法进行引用时,F# 编译器将保留 F# 语义,即所有函数都有一个参数(正如 John Palmer 所说,unit 是也是一个论点)并且可以被柯里化。

好的,此信息只是为了阐明为什么 F# compiler/Fable 以不同方式表示方法和 lambda。让我们来看看无参数函数的问题:显而易见的解决方案当然是删除 F# 编译器为接受 unit 的函数生成的参数(因为它已经为方法完成了)。事实上,我也因此遇到了像 Mocha 这样的库的问题。

我确实尝试在开始时删除 unit 参数,但在某些情况下我因此失败了。 TBH,我现在不记得到底是哪些测试失败了,但由于期望总会有一个参数,在某些情况下,当 unit 参数被删除时,函数组合或内联失败。

其他在 JS 运行时修改 F# 函数语义的尝试总是失败,因为它们没有涵盖所有场景。但是,我们可以对委托 (System.Func<>) 更加宽容,因为通常可以安全地假设这些委托的行为应该更像 C# 或 F# 等语言中的函数。我可以尝试删除代表的单位参数,看看会发生什么:)

有关将 F# 函数发送到 JS 代码的更多信息,您可以查看 documentation

更新:从头开始,请尝试 fable-compiler@0.6.12 和 fable-core@0.6.8。这个版本消除了 unit 个参数,解决方案实际上比我想象的要简单,并且(希望)不应该对现有项目造成问题。 (关于不同编译的方法和 lambda 的解释仍然适用。)