proc: объявление процедуры

Разбираемся, как в Nim оформить кусок кода в процедуру: с параметрами, типами и возвращаемым значением.

Процедура (procedure) — именованный блок кода, который можно вызывать много раз с разными входными данными. В Nim процедуры объявляют через ключевое слово proc.

Зачем это нужно

Представь, что ты пишешь программу, которая несколько раз считает площадь прямоугольника: в одном месте — для комнаты, в другом — для участка земли, в третьем — для баннера. Если каждый раз писать ширина * высота заново, велика вероятность где-нибудь ошибиться или забыть учесть новое условие (например, что стороны не могут быть отрицательными). Гораздо надёжнее написать код один раз, дать ему имя и потом просто вызывать это имя с нужными числами.

Именно для этого в любом языке программирования есть процедуры и функции. В Nim их называют procedures и объявляют ключевым словом proc. Отдельного слова «function» для чистых функций (которые не имеют побочных эффектов) в базовом синтаксисе нет — Nim различает это через ключевое слово func, но об этом позже. Пока используем proc — это рабочая лошадка, с которой начинают все.

Синтаксис proc

Вот процедура, которая складывает два целых числа:

proc sum(a: int, b: int): int =
  result = a + b

echo sum(3, 4)

Вывод:

7

Разберём эту запись по кусочкам, потому что в Nim каждая часть здесь значима и ничего лишнего нет.

Построчный разбор

  • proc — ключевое слово, с которого начинается объявление любой процедуры.
  • sum — имя процедуры. По нему её потом вызывают.
  • (a: int, b: int) — список параметров в круглых скобках. Каждый параметр записывается как имя: тип. В Nim типы параметров указывать обязательно — компилятор не станет угадывать, что именно ты хочешь туда передать.
  • : int после закрывающей скобки — тип возвращаемого значения. Он тоже обязателен, если процедура что-то возвращает.
  • = — открывает тело процедуры. В Nim отступы (пробелы) значимы, как в Python: всё, что написано с отступом ниже строки с proc, — это тело процедуры.
  • result = a + b — здесь происходит магия: result — это специальная переменная, которую Nim создаёт автоматически внутри каждой процедуры с возвращаемым типом. Присвоить ей значение — то же самое, что сказать «вот что нужно вернуть».

Заметь: в этом примере нет отдельного слова return. Оно в Nim тоже есть и работает (можно написать return a + b), но чаще используют именно переменную result — она изначально уже создана с «нулевым» значением подходящего типа (для int это 0), и в конце процедуры её значение возвращается автоматически.

Вариант с явным return

Если тебе привычнее явный возврат, как в большинстве других языков, вот та же процедура иначе:

proc multiply(a: int, b: int): int =
  return a * b

echo multiply(5, 6)

Вывод:

30

Оба варианта — с result и с return — рабочие и дают одинаковый результат. return удобен, когда нужно выйти из процедуры досрочно (например, внутри условия), а result — когда значение собирается постепенно, шаг за шагом.

Процедура без возвращаемого значения

Не всякая процедура обязана что-то возвращать. Если она просто выполняет действие — например, печатает текст, — тип результата в объявлении не указывают вовсе:

proc greet(name: string) =
  echo "Привет, " & name & "!"

greet("Аня")

Вывод:

Привет, Аня!

Здесь после списка параметров нет двоеточия с типом — сразу идёт = и тело. Такая процедура выполняет побочное действие (вывод на экран) и ничего не возвращает вызывающему коду.

Мини-пример: процедура с несколькими шагами

Процедуры не обязаны быть однострочными. Внутри может быть сколько угодно логики — важно лишь, чтобы в конце (через result или return) было понятно, что процедура отдаёт наружу:

proc isEven(n: int): bool =
  if n mod 2 == 0:
    result = true
  else:
    result = false

echo isEven(10)
echo isEven(7)

Вывод:

true
false

Процедура isEven принимает целое число и возвращает bool — логическое значение true или false. Внутри мы используем mod — это оператор остатка от деления (в других языках его часто пишут как %). Если остаток от деления на 2 равен нулю, число чётное.

Частые ошибки

  • Забыли указать тип параметра. Запись вида proc sum(a, b): int без типов не скомпилируется — Nim статически типизированный язык, и каждый параметр должен знать свой тип. Правильно: proc sum(a: int, b: int): int или короче — proc sum(a, b: int): int, если оба параметра одного типа (тип указывается один раз после запятой).
  • Забыли тип возвращаемого значения при его наличии. Если процедура использует result или return, но в объявлении нет : тип после скобок — компилятор пожалуется, что result не определён.
  • Перепутали отступы. Так же, как в Python, тело процедуры определяется отступом. Если строка тела написана без отступа или с отступом, отличным от остальных строк тела, компилятор выдаст ошибку синтаксиса.
  • Ожидают, что result нужно объявлять вручную. Не нужно писать var result: int — Nim создаёт эту переменную сам на основе типа, указанного после скобок.

Итоги

  • Процедура в Nim объявляется словом proc, дальше — имя, параметры с обязательными типами в скобках и (если нужно) тип возвращаемого значения после двоеточия.
  • Тело процедуры отделяется знаком = и записывается с отступом, как блоки в Python.
  • Вернуть значение можно двумя способами: присвоить его переменной result (она создаётся автоматически) или использовать явный return.
  • Если процедура ничего не возвращает, тип результата в объявлении просто не указывают.
Проверьте себя
1. Как называется специальная переменная, которая автоматически создаётся внутри процедуры Nim для возврата значения?
Aresult
Breturn
Coutput
Dvalue
2. Что произойдёт при попытке скомпилировать proc sum(a, b): int = result = a + b без указания типов a и b?
AКомпилятор сам определит типы по контексту вызова
BКод не скомпилируется — типы параметров обязательны
Ca и b станут типом string по умолчанию
DКод скомпилируется, но a и b будут равны нулю