Параметры по умолчанию и именованные аргументы
Разбираемся, как задать параметру значение «по умолчанию» и как вызывать процедуры, называя аргументы по имени.
Параметр по умолчанию — значение, которое подставляется автоматически, если при вызове процедуры аргумент не передан. Именованный аргумент — способ вызова, при котором значение указывается вместе с именем параметра, а не только по позиции.
Зачем это нужно
Представь процедуру, которая создаёт профиль пользователя: имя, возраст, страна, согласие на рассылку. В большинстве случаев страна — «Россия», а согласие на рассылку — «нет» (пользователь сам включит, если захочет). Если бы для каждого вызова приходилось перечислять все четыре значения, даже когда три из них почти всегда одинаковые, код быстро становится многословным и хрупким: легко перепутать порядок аргументов, особенно если их пять и больше.
Параметры по умолчанию решают это: можно указать «типичное» значение прямо в объявлении процедуры, и тогда при вызове его можно не передавать — Nim подставит его сам. А именованные аргументы решают вторую проблему — путаницу с порядком: вместо того чтобы запоминать «какой аргумент по счёту что означает», можно писать явно, каким параметрам какие значения соответствуют.
Синтаксис параметров по умолчанию
proc createProfile(name: string, age: int, country: string = "Россия") =
echo name & ", " & $age & " лет, " & country
createProfile("Иван", 20)
createProfile("Мария", 25, "Казахстан")Вывод:
Иван, 20 лет, Россия
Мария, 25 лет, КазахстанПострочный разбор
country: string = "Россия"— это и есть параметр по умолчанию. После указания типа через=задаётся значение, которое будет использовано, если аргумент не передан явно.- При вызове
createProfile("Иван", 20)мы передали только два аргумента — дляnameиage. ПараметрcountryNim заполнил сам значением"Россия". - При вызове
createProfile("Мария", 25, "Казахстан")мы явно передали третий аргумент, и он переопределил значение по умолчанию — вместо «Россия» подставилась «Казахстан». - Важное правило: параметры со значением по умолчанию обычно ставят после обязательных параметров без значения по умолчанию. Так компилятору проще понять, какие аргументы обязательны, а какие можно опустить.
Синтаксис именованных аргументов
Теперь возьмём процедуру с несколькими параметрами, где легко перепутать порядок:
proc rectangle(width: float, height: float, color: string = "чёрный") =
echo "Прямоугольник " & $width & "x" & $height & ", цвет: " & color
rectangle(width = 10.0, height = 5.0)
rectangle(height = 3.0, width = 8.0, color = "красный")Вывод:
Прямоугольник 10.0x5.0, цвет: чёрный
Прямоугольник 8.0x3.0, цвет: красныйОбрати внимание на второй вызов: аргументы height и width переданы в порядке, обратном тому, в каком они объявлены в процедуре (сначала height, потом width). Это не ошибка — раз мы указываем имя параметра явно через =, Nim смотрит именно на имя, а не на позицию, и подставляет значения правильно.
Почему это удобно
Именованные аргументы особенно полезны, когда у процедуры много параметров одного типа. Например, если бы rectangle принимала два числа подряд без имён, легко перепутать местами ширину и высоту, ведь оба параметра — float, и такая ошибка не будет замечена компилятором (оба значения технически подходящего типа, просто смысл перепутан). Указав имя параметра при вызове, ты защищаешь себя от этой путаницы — код становится ещё и самодокументируемым: читая вызов, сразу видно, что есть что.
Мини-пример: комбинируем оба приёма
proc orderPizza(size: string, toppings: string = "сыр", spicy: bool = false) =
var note = size & " пицца с " & toppings
if spicy:
note = note & " (острая)"
echo note
orderPizza("большая")
orderPizza(size = "средняя", spicy = true)
orderPizza("маленькая", toppings = "грибы", spicy = true)Вывод:
большая пицца с сыр
средняя пицца с сыр (острая)
маленькая пицца с грибы (острая)Здесь видно, как приёмы работают вместе. Первый вызов передаёт только обязательный параметр size — остальные два взяли значения по умолчанию. Второй вызов пропускает toppings (он снова возьмёт значение "сыр" по умолчанию), но явно указывает spicy по имени, хотя тот стоит не сразу после size. Третий вызов смешивает позиционный аргумент ("маленькая" — первый по порядку, без имени) с двумя именованными.
Частые ошибки
- Параметр без значения по умолчанию после параметра со значением. Запись вида
proc f(a: int = 5, b: int)компилятор Nim пропустит с предупреждением о неочевидном порядке — по возможности всегда ставь обязательные параметры первыми, а параметры со значением по умолчанию — в конце списка. - Пропуск параметра «в середине» без указания имени. Нельзя вызвать
rectangle(10.0, , "красный"), оставив пустое место дляheight— если хочешь пропустить параметр не в конце списка, для оставшихся аргументов после пропуска нужно использовать именованный синтаксис (как во втором примере выше). - Путают именованный аргумент с обычным присваиванием. Запись
rectangle(width = 10.0, ...)внутри вызова — это не создание переменнойwidth, а указание, какому параметру процедуры соответствует значение10.0. Внутри списка аргументов при вызове=означает именно связь «параметр — значение». - Ожидают, что значение по умолчанию пересчитывается при каждом вызове по актуальным данным. Значение по умолчанию вычисляется исходя из выражения, заданного в объявлении процедуры, и не «следит» за внешними переменными автоматически — если нужно поведение, зависящее от контекста вызова, значение стоит передавать явно.
Итоги
- Значение по умолчанию задаётся прямо в объявлении процедуры после типа параметра через
=— и подставляется, если аргумент не передан. - Именованные аргументы позволяют указывать значения по имени параметра при вызове, независимо от порядка объявления.
- Комбинация этих приёмов делает вызовы процедур короче, безопаснее и понятнее — особенно когда параметров много или они одного типа.
- Параметры со значением по умолчанию обычно располагают после обязательных параметров в списке.