Пропустить к содержанию
Руководство Varlig
Главная страница Varlig

Собственные функции

Если вы часто повторяете одну формулу с разными числами, создайте функцию. Один раз задайте её имя и параметры, затем вызывайте там, где нужен результат: для чаевых, ИМТ, прогноза накоплений или счёта клиенту.

Здесь описаны определение и вызов функций, использование других имён из заметки, условия, рекурсия и ограничения. О встроенных функциях Varlig, таких как sqrt и round, см. Справочник встроенных функций.

Определение и вызов функции

Запишите имя функции, параметры в круглых скобках, знак равенства и формулу. Затем вызывайте её со значениями в том же порядке:

calc
tip(bill, pct) = bill * pct
tip($48, 15%) даёт $7.20
tip($120, 12.5%) даёт $15.00
tip($36 + $12, 15%) даёт $7.20

Строка определения не показывает результат. Каждый вызов подставляет ваши значения вместо bill и pct и вычисляет формулу. Аргументом может быть целое выражение, например $36 + $12 выше.

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

calc
bmi(weight, height) = weight / height^2
bmi(81 kg, 1.8 m) даёт 25 kg/m²

Единицы сохраняются такими, как переданы: bmi(81 kg, 180 cm) даёт результат в кг/см². Чтобы единица результата не зависела от входных данных, выполняйте перевод внутри функции:

calc
bmi(weight, height) = (weight / height^2) in kg/m^2
bmi(81 kg, 180 cm) даёт 25 kg/m²
bmi(80 kg, 5.9 ft) даёт 24.7375131668 kg/m²

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

calc
standard_vat() = 20%
£120 * standard_vat() даёт £24.00

Обычная переменная, такая как standard_vat = 20%, обычно выполняет ту же работу с меньшим количеством ввода.

Имена и параметры

  • Имена функций и параметров состоят из одного слова без пробелов. Используйте буквы, цифры и подчёркивания, например net_pay или bmi2. Для записи area of circle(r) = pi * r^2 строка предложит подходящее имя: area_of_circle.
  • Имена функций игнорируют регистр: после определения Tip(bill, pct) вы можете вызвать tip($48, 15%).
  • Каждому параметру нужно собственное имя. f(a, a) = a - это ошибка.
  • Функция может иметь до 32 параметров.
  • Вы не можете повторно использовать имя встроенной функции. round(x) = … или sqrt(x) = … отображают ошибку вместо её замены. Простой переменной всё ещё может использовать одно из этих имен, например floor = 12 m²; см. Имена.
  • Имена avg, total и stdev, знакомые по электронным таблицам, разрешены для собственных функций. Если определить total(order), будет вызываться ваша версия.
  • Функция и переменная могут иметь одно имя. Запись rate читает переменную, а rate(5) вызывает функцию.
  • Всегда вызывайте функцию в скобках. Имя функции само по себе, без переменной с тем же именем, ничего не показывает. Исключениями являются sum, total, subtotal, grand total, average, max и min, которые вычисляют эту цифру для строк над ними; см. Сложение строк выше.

Запятые в аргументах

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

calc
tip(bill, pct) = bill * pct
tip($1,200, 15%) даёт $180.00
tip($1200,15%) даёт $180.00

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

Использование других имен в вашей заметке

Функция может использовать переменные заметки. При каждом вызове она читает их текущие значения:

calc
vat = 20%
with_vat(price) = price * (1 + vat)
with_vat(£50) даёт £60.00
vat = 5%
with_vat(£50) даёт £52.50

Переменная должна уже существовать, когда вы определяете функцию, поэтому поставьте vat = 20% выше with_vat. Если он еще не существует, строка определения показывает ошибку.

Параметры являются локальными для функции. Параметр под названием price не читает и не изменяет переменную под названием price в другом месте примечания:

calc
price = £10
double(price) = price * 2
double(£3) даёт £6.00
price даёт £10.00

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

Функции, которые вызывают другие функции

Небольшие функции могут быть построены друг на друге:

calc
day_rate = £400
fee(days) = days * day_rate
invoice(days) = fee(days) * 1.2
invoice(5) даёт £2,400.00

Функция запоминает ту версию вспомогательной функции, которая существовала при её определении. Если ниже определить вспомогательную функцию заново, ранее созданные функции продолжат использовать старую версию:

calc
shipping(order) = £4.95
total(order) = order + shipping(order)
shipping(order) = £2.95
total(£30) даёт £34.95
shipping(£30) даёт £2.95

Чтобы использовать новую shipping, определите total заново ниже неё. При редактировании исходного определения на месте такой проблемы нет: Varlig пересчитывает заметку сверху, и все последующие строки используют обновлённую версию.

Функция также может вызывать вспомогательную функцию, определённую ниже. В этом случае используется версия, действующая в момент вызова. Поэтому вспомогательная функция должна существовать к моменту вызова внешней:

calc
checkout(order) = order + delivery(order)
delivery(order) = if order >= £40 then £0 else £3.50
checkout(£25) даёт £28.50
checkout(£60) даёт £60.00

Условия

Используйте if … then … else …, чтобы выбрать между результатами. Добавьте еще один if после else, чтобы обработать более двух случаев:

calc
postage(weight) = if weight <= 100 g then £0.85 else if weight <= 750 g then £1.55 else £3.20
postage(90 g) даёт £0.85
postage(500 g) даёт £1.55
postage(1.2 kg) даёт £3.20

Вычисляется только выбранная ветвь. Это позволяет защититься от недопустимых операций, например деления на ноль:

calc
per_person(total, people) = if people > 0 then total / people else £0
per_person(£90, 3) даёт £30.00
per_person(£90, 0) даёт £0.00

Рекурсия

Функция может вызвать себя, если условие в конечном итоге останавливает ее. Этот подсчитывает рукопожатие, когда все в группе пожимают друг другу руки один раз:

calc
handshakes(people) = if people <= 1 then 0 else (people - 1) + handshakes(people - 1)
handshakes(6) даёт 15
handshakes(10) даёт 45

Каждый вызов увеличивает глубину вложенности на один; разрешено не более 12 уровней. handshakes(12) работает, а handshakes(13) выдаёт Error: calculation limit. Функцию без достижимого условия остановки можно определить, но при вызове она достигнет того же ограничения. Две функции могут вызывать друг друга в пределах того же лимита.

Для повседневного подсчета встроенные функции быстрее работают и не имеют такого ограничения. combination(10, 2) также выдает 45, а factorial(n), или n!, охватывает классический рекурсивный пример.

Списки, матрицы и многое другое

Аргументы могут быть списками, матрицами или комплексными числами, а тело может использовать любую встроенную функцию:

calc
spread(scores) = max(scores) - min(scores)
spread([12, 18, 9, 21]) даёт 12

Тело также может содержать суммирование или решение уравнений со своей собственной локальной переменной. См. Списки и статистика и Суммирование, решение уравнений и исчисление.

Подводные камни

  • Записывайте степени через ^. Запись x² внутри функции не поддерживается. Кроме того, короткое имя параметра может совпасть с единицей: в w / h² выражение h² означает часы в квадрате, а не параметр h. Используйте w / h^2.
  • Проверьте количество аргументов. Вызов функции tip($48), когда она ожидает два значения, приводит к ошибке.
  • Цена без явной единицы может трактоваться как цена за единицу. В oats(amount) = amount / 1 kg * £0.95 сумма £0.95 считается ценой за килограмм. Каждый вызов сообщает об этом: наведите указатель, чтобы увидеть пояснение «£0.95 в oats трактуется как цена за кг. Напишите £0.95/kg, чтобы указать это явно». Явная запись ставки в определении убирает подсказку.
  • Одна строка, одна формула. Определение — это одно выражение на одной строке. Для расчета с несколькими шагами определите небольшую функцию для каждого шага и объедините их.
  • Ошибочное переопределение сохраняет прежнюю версию. Если новое определение tip содержит ошибку, строка сообщает о ней, а предыдущая рабочая tip остаётся доступной.
  • Ответы могут измениться, когда заметка пересчитает данные. Вызовы рассчитываются снова каждый раз, поэтому функция, использующая random или сегодняшнюю дату, может дать новый ответ.
  • Ошибки передаются вызывающей строке. Если аргумент приводит к недопустимому вычислению, например делению на ноль, вызов показывает эту ошибку.

Ограничения

Параметр Ограничение
Параметры для каждой функции 32
Вложенные вызовы: функция вызывает себя или другую функцию 12
Число вызовов при вычислении одного вызова верхнего уровня 16,384
Функции, определённые в заметке 1,024

При достижении ограничения появляется Error: calculation limit. Остальная заметка продолжает работать. Полный список — в разделе Ошибки, диагностика и ограничения.

Всё вместе

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

calc
# March invoice
day_rate = £450
vat = 20%
fee(days) = days * day_rate
with_vat(amount) = amount * (1 + vat)
late_fee(amount, days_late) = if days_late > 30 then amount * 2% else £0
design = fee(8) даёт £3,600.00
build = fee(4.5) даёт £2,025.00
subtotal = design + build даёт £5,625.00
with_vat(subtotal) даёт £6,750.00
late_fee(with_vat(subtotal), 45) даёт £135.00

Измените day_rate или vat, и все последующие строки обновятся. Если клиент задержал оплату, один вызов добавит сбор.