Почему должны быть заключены последовательные аргументы, связанные с применением метода?

Предположим, что следующая функция 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: последовательные аргументы должны быть разделены пробелами или и аргументы, связанные с приложениями функций или методов, должны в скобках.

Фиксирование это тривиально (в скобках все вещи), но я не понимаю, почему такое выражение является проблемой. Я предполагаю, что это снова связано с типом вывода, но наивно, мне кажется, что здесь методы, содержащие список аргументов, окруженных скобкой, фактически сделают вещи менее потенциально двусмысленными. Это связано с тем, что rng.Next(5) эквивалентно rng.Next 5?

Может кто-нибудь намекнуть, привести пример или объяснить, почему это правило необходимо, или какие проблемы возникнут, если он не был там?

Ответ 1

Я думаю, что проблема здесь в том, что код можно рассматривать как:

let z3 = f 1 rng.Next (5)

Это было бы эквивалентно опущению круглых скобок, и поэтому он вызывал бы 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() не будет работать.