寓言 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 的解释仍然适用。)
我在 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 的解释仍然适用。)