Your own functions
When you type the same formula again and again with different numbers, turn it into a function. You name the formula and its inputs once, then call it wherever you need an answer: a tip calculator, a BMI check, a savings projection or an invoice.
This page covers defining and calling functions, how they use the other names in your note,
conditions and recursion, and the limits that apply. For the functions that come with Varlig,
such as sqrt and round, see the built-in function reference.
Defining and calling a function
Write the function’s name, its parameters in parentheses, an equals sign and the formula. Then call it with values in the same order:
tip(bill, pct) = bill * pcttip($48, 15%) gives $7.20tip($120, 12.5%) gives $15.00tip($36 + $12, 15%) gives $7.20The definition line shows no answer. Each call puts your values in place of bill and pct
and works out the formula. An argument can be a whole calculation, like $36 + $12 above.
Arguments are full values, not only numbers, so units and currencies carry through the formula:
bmi(weight, height) = weight / height^2bmi(81 kg, 1.8 m) gives 25 kg/m²Units are kept as you give them, so bmi(81 kg, 180 cm) answers in kg/cm². To get the same
unit whatever you pass in, convert inside the function:
bmi(weight, height) = (weight / height^2) in kg/m^2bmi(81 kg, 180 cm) gives 25 kg/m²bmi(80 kg, 5.9 ft) gives 24.7375131668 kg/m²A function can also have no parameters. Write empty parentheses both when you define it and when you call it:
standard_vat() = 20%£120 * standard_vat() gives £24.00A plain variable, such as standard_vat = 20%, usually does the same job with less typing.
Names and parameters
- Function and parameter names are single words. Use letters, digits and underscores, such
as
net_payorbmi2, with no spaces. If you writearea of circle(r) = pi * r^2, the line suggests the name to use instead:area_of_circle. - Function names ignore case: after defining
Tip(bill, pct), you can calltip($48, 15%). - Each parameter needs its own name.
f(a, a) = ais an error. - A function can have up to 32 parameters.
- You can’t reuse the name of a built-in function.
round(x) = …orsqrt(x) = …shows an error instead of replacing it. A plain variable can still use one of those names, such asfloor = 12 m²; see Names. - The spreadsheet spellings
avg,totalandstdevare free to use. Define your owntotal(order)and your version is the one that runs. - A function and a variable can share a name.
ratereads the variable andrate(5)calls the function. - Always call a function with parentheses. A function name on its own, with no variable of the same name, shows an error.
Commas in arguments
A comma followed by a space separates the arguments, and a comma followed by exactly three digits groups thousands, so you can write amounts the way you normally would:
tip(bill, pct) = bill * pcttip($1,200, 15%) gives $180.00tip($1200,15%) gives $180.00When a function needs more values than the spaces give it, every comma separates, as in the
second call. Use a decimal point for fractions, as in tip($48, 12.5%).
Using other names in your note
A function can use variables from your note. It reads their current value each time you call it:
vat = 20%with_vat(price) = price * (1 + vat)with_vat(£50) gives £60.00vat = 5%with_vat(£50) gives £52.50The variable must already exist when you define the function, so put vat = 20% above
with_vat. If it doesn’t exist yet, the definition line shows an error.
Parameters are local to the function. A parameter called price doesn’t read or change a
variable called price elsewhere in the note:
price = £10double(price) = price * 2double(£3) gives £6.00price gives £10.00Like variables, a function defined in one calc block can be used in later calc blocks in the same note. Varlig works through the note from top to bottom, so define a function above the first line that calls it. A call above the definition shows no answer.
Functions that call other functions
Small functions can build on each other:
day_rate = £400fee(days) = days * day_rateinvoice(days) = fee(days) * 1.2invoice(5) gives £2,400.00A function remembers the version of a helper that existed when you defined it. If you define the same helper again further down, functions defined earlier keep using the old version:
shipping(order) = £4.95total(order) = order + shipping(order)shipping(order) = £2.95total(£30) gives £34.95shipping(£30) gives £2.95To pick up the new shipping, define total again below it. Editing a definition in place
doesn’t cause this. Varlig recalculates the note from the top, so everything below uses your
edited version.
A function can also call a helper you define further down. It then uses whatever that helper is when you make the call, so the helper must exist by the time you call the outer function:
checkout(order) = order + delivery(order)delivery(order) = if order >= £40 then £0 else £3.50checkout(£25) gives £28.50checkout(£60) gives £60.00Conditions
Use if … then … else … to choose between results. Chain another if after else for more
than two cases:
postage(weight) = if weight <= 100 g then £0.85 else if weight <= 750 g then £1.55 else £3.20postage(90 g) gives £0.85postage(500 g) gives £1.55postage(1.2 kg) gives £3.20Only the branch that applies is worked out. That lets you guard against a calculation that would otherwise fail, such as dividing by zero:
per_person(total, people) = if people > 0 then total / people else £0per_person(£90, 3) gives £30.00per_person(£90, 0) gives £0.00Recursion
A function can call itself, as long as a condition eventually stops it. This one counts the handshakes when everyone in a group shakes hands once:
handshakes(people) = if people <= 1 then 0 else (people - 1) + handshakes(people - 1)handshakes(6) gives 15handshakes(10) gives 45Each call nests one level deeper, and at most 16 nested calls are allowed. handshakes(16)
still works, but handshakes(17) shows Error: calculation limit. A function that never
reaches its stopping case is accepted when you define it, and hits the same limit when you
call it. Two functions can also call each other, within the same limit.
For everyday counting, the built-in functions are quicker and have no such limit.
combination(10, 2) also gives 45, and factorial(n), or n!, covers the classic recursive
example.
Lists, matrices and more
Arguments can be lists, matrices or complex numbers, and a body can use any built-in function:
spread(scores) = max(scores) - min(scores)spread([12, 18, 9, 21]) gives 12A body can also contain a summation or an equation solver with its own local variable. See Lists and statistics and Summation, equation solving and calculus.
Pitfalls
- Write powers with
^.x²isn’t accepted inside a function. Worse, a short parameter name can match a unit: inw / h², theh²means square hours, not the parameterh. Writew / h^2. - Check the number of arguments. Calling
tip($48)when the function expects two values shows an error. - One line, one formula. A definition is a single expression on one line. For a calculation with several steps, define a small function for each step and combine them.
- A broken redefinition keeps the old version. If a new definition of
tiphas a mistake, the line shows an error and the previous workingtipstays available. - Answers can change when the note recalculates. Calls are worked out again each time,
so a function that uses
randomor today’s date can give a new answer. - Errors come through. If an argument makes the formula fail, such as dividing by zero, the call shows that error.
Limits
| What | Limit |
|---|---|
| Parameters per function | 32 |
| Nested calls (a function calling itself or another) | 16 |
| Calls made while working out one top-level call | 16,384 |
| Functions defined in a note | 1,024 |
Hitting a limit shows Error: calculation limit. The rest of the note keeps working. See
Errors, diagnostics and limits for every limit.
Putting it together
Here is a freelance invoice. The rate and VAT sit at the top as named values, and three small functions do the work:
# March invoiceday_rate = £450vat = 20%fee(days) = days * day_ratewith_vat(amount) = amount * (1 + vat)late_fee(amount, days_late) = if days_late > 30 then amount * 2% else £0design = fee(8) gives £3,600.00build = fee(4.5) gives £2,025.00subtotal = design + build gives £5,625.00with_vat(subtotal) gives £6,750.00late_fee(with_vat(subtotal), 45) gives £135.00Change day_rate or vat and every line below updates. When the client pays late, one call
adds the fee.