.fsx脚本在向其添加参数时忽略函数调用

时间:2016-07-05 11:48:08

标签: f# f#-scripting

好吧,所以我是一个快乐的fsx脚本程序员,因为我喜欢当我在运行时出现错误之前让编译器对我大喊大叫。

然而,我发现了一个真正困扰我的案例,因为我期望通过做一些重构(即:向函数添加一个参数)我会被编译器警告我所有的地方需要提出新的论点。但是,不仅这发生了,fsharpi运行我的脚本并且完全忽略了函数调用!! :(

如果发生这种情况,我怎么能期望重构我的脚本?

这是我的代码:

let Foo (bar: string) =
    Console.WriteLine("I received " + bar)

Foo("hey")

有效。

现在,稍后,我决定在函数中添加第二个参数(但我忘了将参数添加到对它的所有调用中):

let Foo (bar: string) (baz: bool) =
    Console.WriteLine("I received " + bar)

Foo("hey")

结果是:而不是编译器告诉我我错过了一个参数,它是fsharpi运行脚本并忽略对Foo的调用!为什么呢?

PS:我知道currying和tuples之间的区别,因此我知道Foo("hey")成为一个函数(而不是函数调用),因为部分应用程序。但我想更好地理解为什么编译器不期望在这里进行函数评估,而不是看到函数并忽略它。我能以某种方式启用warningAsError吗?我想避免使用元组来解决这个问题。

1 个答案:

答案 0 :(得分:2)

fsharpi(或fsi,如果你在Windows上)解释器在运行脚本和在交互式提示符下输入代码之间没有区别(或者,通常,通过编辑器提交代码一个select-and-hit-Alt-Enter键盘快捷键。)

因此,如果你得到了你要求的东西 - fsharpi每当脚本行的返回值不是()时发出警告 - 它就会破坏{的值{1}}用于最常见的用例,即人们使用交互式fsharpi会话来测试他们的代码,并快速迭代非工作原型以获得正常工作的原型。这是F#的强大优势之一,给你你所要求的东西将消除这种力量。因此从不会发生。

但是 ......这并不意味着你已经沉没了。如果你有返回fsharpi的函数,并且你希望unit在重构它们以获取更多参数时给你一个编译时错误,你可以这样做。替换所有出现的:

fsharpi

使用:

Foo("hey")

只要函数() = Foo("hey") 只有一个参数(并返回null),这将评估为Foo; true将高兴地忽略true值,您的脚本将会运行。但是,如果您随后更改fsharpi以获取两个参数,以便Foo现在返回一个函数,Foo("hey")行将不再编译,并且您将收到如下错误:< / p>

() = Foo("hey")

因此,如果您希望error FS0001: This expression was expected to have type unit but here has type 'a -> unit 在重构函数时拒绝编译脚本,请通过并将调用更改为fsharpi。对于不返回() = myfunc arg1 arg2的函数,请根据该函数的返回类型的值来设置您正在测试的值。例如,给定此功能:

unit

你可以做到

let f x = x * 2

当然,这将是0 = f 5 ,但它会编译。但如果你重构false

f

现在,行let f x y = x * 2 + y 将无法编译,但会显示错误消息:

0 = f 5

总结一下:你永远不会得到你正在寻找的功能,因为它会损害语言。但是通过一些工作,你可以做一些符合你需求的事情。

或者换句话说,正如着名哲学家米克贾格尔曾经说过的那样:

  

你不能总是得到你想要的东西。但是,如果你尝试,有时你可能会发现你得到了你需要的东西。