假设以下F#函数:
let f (x:int) (y:int) = 42
我怀疑我需要在下面的示例z2中括起参数的原因是因为类型推断;我的例子可能不是很好,但很容易想象事情会变得如此毛茸茸:
let z1 = f 2 3
let z2 = f 2 (f 3 5)
但是,以下情况对我来说不太清楚:
let rng = System.Random()
let z3 = f 1 rng.Next(5)
z3不起作用,带有明确的错误消息:
错误FS0597:连续参数应以空格或分隔 tupled,涉及函数或方法应用程序的参数应该 用括号括起来。
修复它是微不足道的(括号所有的东西),但我不清楚的是为什么这样的表达式是一个问题。我认为这再次与类型推断有关,但是天真地,在我看来,在这里,具有由括号括起来的参数列表的方法实际上会使事情变得不那么模糊。这是否与rng.Next(5)
等同于rng.Next 5
的事实有关?
有人可以暗示,举例或解释为什么需要这条规则,或者如果不存在会出现什么类型的问题?
答案 0 :(得分:13)
我认为这里的问题是代码可以被视为:
let z3 = f 1 rng.Next (5)
这相当于省略了括号,因此它将使用3个参数调用f
(第二个是函数值)。这听起来有点傻,但编译器实际上并没有严格坚持在参数之间留一个空格。例如:
let second a b = b
add 5(1) // This works fine and calls 'add 5 1'
add id(1) // error FS0597
add rng.Next(5) // error FS0597
add (rng.Next(5)) // This works fine (partial application)
我认为问题在于,如果你看一下上述代码片段中4个例子的序列,就不清楚你应该在第二个和第三个案例中得到哪种行为。
仍然以特殊方式处理调用rng.Next(5)
,因为如果它们由没有空格的单参数应用程序形成,则F#允许您链接调用。例如rng.Next(5).ToString()
。但是,例如,允许编写second(1)(2)
,但second(1)(2).ToString()
将不起作用。