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