Параметры функции

Последнее обновление: 10.12.2023

Для передачи в функцию некоторых данных извне язык F# позволяет определять для функции параметры. Параметры указываются после названия функции. Если параметров несколько, их названия отделяются пробелом:

let название_функции параметр1 параметр2 ... параметрN = действия_функции

При вызове функции ей передаются через пробел значения для всех ее параметров:

название_функции значение_для_параметра1 значение_для_параметра2 ... значение_для_параметраN

Значения, которые передаются параметрам функции, еще называются аргументами

Функция в F# имеет как минимум один параметр.

В прошлой статье в принципе мы уже рассмотрели функцию с одним параметром:

let printMessage() = printfn "Hello world"		// определение функции

Однако в качестве параметра здесь применяется значение типа unit, которое представляет пустые скобки и не несет какого-то особого смысла. И при вызове данной функции мы указываем соответствующее значение - то есть пустые скобки:

printMessage()		// вызов функции

Теперь рассмотрим пример, где параметр позволяет получить извне некоторые данные:

let printMessage message = printfn $"Message: {message}"            

printMessage "Hello"

Здесь функция printMessage принимает один параметр message, через которых в функцию передается выводимое сообщение.

И при вызове функции мы должны передать ей это сообщение: printMessage "Hello"

Благодая параметру мы можем передавть в функцию для вывода на консоль разные сообщения:

let printMessage message = printfn $"Message: {message}"            

printMessage "Hello"
printMessage "Welcome to F#"
printMessage "F# on METANIT.COM"

Консольный вывод:

Message: Hello
Message: Welcome to F#
Message: F# on METANIT.COM

Подобным образом мы можем определять функции с большим количеством параметров. Например, определим функцию, которая принимает два параметра и выводит их сумму:

let sum x y = 
    let result = x + y
    printfn $"Сумма {x} и {y} равна {result}"

sum 10 2
sum 5 4
sum 31 4

Поскольку здесь функция sum принимает два параметра, при ее вызове ей передается два аргумента: sum 10 2. Консольный вывод программы:

Сумма 10 и 2 равна 12
Сумма 5 и 4 равна 9
Сумма 31 и 4 равна 35

Выведение типа параметров

В F# все значения имеют определенный тип. И параметры функций тоже. Однако выше мы не определяли явным образом тип параметров. Поскольку компилятор сам можем вывести тип параметров исходя из контекста, в частности, исходя из действий, которые производятся внутри функции. Например, в функции из примера выше

let sum x y = 
    let result = x + y
    printfn $"Сумма {x} и {y} равна {result}"

Исходя из операции сложения компилятор выводит для параметров x и y тип int. Соответственно внутри функции далее мы можем производить с этими параметрами все те действия, которые поддерживаются для значений типа int.

Но немного изменим функцию

let sum x y = 
    let result = x + y + 100f
    printfn $"Сумма {x} и {y} равна {result}"

Здесь к сумме x + y прибавляется 100f. Суффикс f указывает, что число 100 представляет значение типа float32. Соответственно параметры x и y также будут рассмотриваться как значения типа float32.

Автоматическая генерализация

Однако если код функции не зависит от типа параметров, то в этом случае компилятор рассматривает параметр как универсальный, который может соответствовать любому типу. Данный подход еще называется автоматической генерализацией (automatic generalization). Он позволяет определять функции с универсальным кодом, где параметрам может соответствовать широкий диапазон типов. В частности, рассмотрим первый пример:

let printMessage message = printfn $"Message: {message}"            

printMessage "Hello"
printMessage 3.14
printMessage 22
printMessage true

Здесь компилятор на основании контекста не может определить точно, какой тип представляет параметр message, поэтому он будет представлять любой тип. Соответственно при вызове функции мы сможем передать ее параметру значения любых типов. Консольный вывод программы:

Message: Hello
Message: 3,14
Message: 22
Message: True

Типизация параметров

Мы также можем явным образом установить для параметров их тип данных. В этом случае тип данных указывается после названия параметра через двоеточие, а параметры, для которых явным образом определяется тип, заключаются в скобки:

let имя_функции (параметр1: тип) (параметр2: тип) (параметрN: тип) = действия_функции

Рассмотрим следующий пример:

let printPerson (name:string) (age:int) = 
    printfn $"Person name: {name}   age:{age}"
 
printPerson "Tom" 37
printPerson "Sam" 45

Здесь определяется функция printPerson, которая принимает два параметра: name и age. Параметр name представляет тип string, а параметр age - тип int. Поэтому при вызове функции нам надо передать функции printMessage значения типа string и int.

printPerson "Tom" 37 

Консольный вывод программы:

Person name: Tom  age: 37
Person name: Sam  age: 45

Если типизированные параметры определяются внутри одной скобки, то они отделяются друг от друга запятой.

let printPerson (name:string, age:int) (company:string)= 
    printfn $"Person name: {name}   age:{age}  company: {company}"
 
printPerson("Tom", 37) "Microsoft"
printPerson("Sam", 45)  "Google"

При чем при вызове функции все значения для типизированных параметров внутри одной скобки также заключаются в скобки и отделяются друг от друга запятой.

Соответствие аргументов параметрам по позиции и типу

Стоит учитывать, что значения передаются параметрам по позиции. То есть первое значение ("Tom") передается первому параметру, второе значение (37) - второму параметру и так далее. Поэтому между параметрами и передаваемыми им значениями должно быть соответствие по типу. То есть если первый тип представляет тип string, то первое значение тоже должно представлять тип string. Если второй параметр представляет тип int, то передаваемое ему значение тоже должно представлять тип int. То есть мы не можем в примере выше написать наподобие

printPerson(37, "Tom") "Microsoft"

Поскольку в этом случае будет несоответствие значений параметрам по типу.

Сочетание типизированных и нетипизированных параметров

При этом функция может сочетать типизированные и нетипизированные параметры:

let printPerson (name:string) age (company: string) = 
    printfn $"Person name: {name}   age:{age}  company: {company}"
 
printPerson ("Tom", "Microsoft") 37
printPerson("Sam", "Google") 45

В данном случае тип явно определен только для параметра name, поэтому он заключается в скобки. А тип параметра age выводится компилятором. Такой параметр указывается через пробел.

Если в функции определено подряд несколько (больше одного) типизированных параметров, то их значения также помещаются в скобки и отделяются запятой, для нетипизированных значения также идут вне скобок и отделяются пробелом.

Если типизированные параметры идут не подряд, то при вызове функции значение для этих параметров можно не помещать в скобки:

let printPerson (name:string) age (company: string) = 
    printfn $"Person name: {name}   age:{age}  company: {company}"
 
printPerson "Tom" 37  "Microsoft"
printPerson("Sam") 45 ("Google")

Игнорирование параметров

В самом первом примере данной статьи мы рассмотрели функцию, которая не использует параметры. Однако тем не менее имеет один параметр типа unit:

let printMessage() = printfn "Hello world"		// определение функции

Однако если нам параметры вообще не нужны и не важны, мы можем применить другой подход - игнорировать их, используя вместо названия параметра прочерк:

let printMessage _ = printfn "Hello"

printMessage()
printMessage ""
printMessage 1

В данном случае опять же функция принимает один параметр, но в теле функции он не используется.

При вызове функции мы опять должны передать для этого параметра значение, но какое это будет значение, уже не важно.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850