Обычный вызов функции в F # пишется без скобок, а параметры разделяются пробелами. Простой способ определить функцию нескольких параметров - записать это:
let add a b = a + b
Как отметил Паскаль, этот способ задания параметров называется каррированием - идея состоит в том, что функция принимает только один параметр, а в результате получается функция, которая принимает второй параметр и возвращает фактический результат (или другую функцию). При вызове простой функции, подобной этой, вы должны написать add 10 5
, а компилятор (в принципе) интерпретирует это как ((add 10) 5)
. Это имеет некоторые приятные преимущества - например, оно позволяет вам использовать приложение с частичной функцией , где вы указываете только первые несколько аргументов функции:
let addTen = add 10 // declares function that adds 10 to any argument
addTen 5 // returns 15
addTen 9 // returns 19
Эта функция практически полезна, например, при обработке списков:
// The code using explicit lambda functions..
[ 1 .. 10 ] |> List.map (fun x -> add 10 x)
// Can be rewritten using partial function application:
[ 1 .. 10 ] |> List.map (add 10)
Теперь давайте перейдем к запутанной части - в F # вы также можете работать с кортежами, которые являются простыми типами данных, которые позволяют группировать несколько значений в одно значение (обратите внимание, что кортежи не связаны с функциями в любом путь). Например, вы можете написать:
let tup = (10, "ten") // creating a tuple
let (n, s) = tup // extracting elements of a tuple using pattern
printfn "n=%d s=%s" n s // prints "n=10 s=ten"
Когда вы пишете функцию, которая принимает параметры в скобках, разделенных запятой, вы фактически пишете функцию, которая принимает один параметр, который является кортежем:
// The following function:
let add (a, b) = a * b
// ...means exactly the same thing as:
let add tup =
let (a, b) = tup // extract elements of a tuple
a * b
// You can call the function by creating tuple inline:
add (10, 5)
// .. or by creating tuple in advance
let t = (10, 5)
add t
Это функция другого типа - она принимает один параметр, который является кортежем, тогда как первая версия была функцией, которая принимала два параметра (с использованием каррирования).
В F # ситуация немного сложнее - методы .NET отображаются в виде методов, которые принимают кортеж в качестве параметра (так что вы можете вызывать их с записью в скобках), но они несколько ограничены (например, вы не можете сначала создайте кортеж, а затем вызовите метод, предоставив ему только кортеж). Кроме того, скомпилированный код F # на самом деле не создает методы в форме с карри (поэтому вы не можете использовать приложение с частичной функцией непосредственно из C #). Это связано с производительностью - в большинстве случаев вы указываете все аргументы, и это может быть реализовано более эффективно.
Однако принцип заключается в том, что функция либо принимает несколько параметров, либо принимает кортеж в качестве параметра.