Functions
Functions are a way to use various functionality of the calculator that goes beyond operators and values. Function names are not case-sensitive.
ABCalc includes over a hundred of built-in functions in several categories:
- General
- Arithmetic
- Trigonometry
- Financial
- Scientific
- Conversion
- Statistical
- String and Char
- Date and Time
You will find the full list of function descriptions on the web page or in the application, on the Functions tab.
Additionally, ABCalc supports custom functions right in the expressions or (in ABCalc Plus) in libraries.
Special Built-in Functions
The following built-in functions have notable behavior worth knowing about.
Error
Error(message) aborts the evaluation of an expression immediately and shows message as an error. This is useful in custom functions to signal invalid input:
fn SafeSqrt(x) => x >= 0 ? Sqrt(x) : Error("Input must be non-negative");
Percent alias
The % symbol is an alias for the PercentOf() function. It calculates what percentage of b the value a represents:
%(50; 200) // 25 (50 is 25% of 200)
%(30; 120) // 25 (30 is 25% of 120)
iff()
iff(condition; value_if_true; value_if_false) is a function-form conditional that returns one of two values based on a boolean condition. It works identically to the ternary operator condition ? value_if_true : value_if_false, just in function notation.
iff(5 > 3; "yes"; "no") // "yes"
iff(x < 0; -x; x) // absolute value of x
iff(n mod 2 == 0; "even"; "odd") // parity check
Unlike the if statement, iff() is an expression — it can appear anywhere a value is expected, including inside other expressions:
Max(iff(a > 0; a; 0); iff(b > 0; b; 0)) // larger of the two non-negative values
ifs()
ifs(cond1; val1; cond2; val2; ...; default) evaluates a sequence of conditions and returns the value paired with the first true condition. If none match, the last argument is returned as the default.
ifs(x < 0; "negative"; x == 0; "zero"; "positive")
// returns "negative", "zero", or "positive" depending on x
ifs(score >= 90; "A"; score >= 80; "B"; score >= 70; "C"; "F")
// letter grade from numeric score
in()
in(element; list_or_value1; list_or_value2; ...) checks whether element is present among the remaining arguments or within a list passed as an argument. It returns true if a match is found.
in(3; 1; 2; 3; 4) // true
in("cat"; "dog"; "cat") // true
in(5; (1; 2; 3)) // false
Note that the in() function differs from the IN operator: the function takes individual values or a list as arguments, while the operator uses the syntax value IN (list).
Function argument separator
Semicolons (;) are the recommended argument separator for all built-in and custom functions. Commas (,) are also accepted but may conflict with decimal separators or number group separators depending on your regional settings. Using semicolons avoids ambiguity:
Round(3.14159; 2) // recommended — semicolon separator → 3.14
Log(100; 10) // log base 10 of 100 → 2
Custom Functions in Expressions
Functions in an expression let you define reusable functionality or just something that you need to execute multiple times within the expression.
A function consists of a header and a body. The body is composed of one or multiple expressions.
A function yields nothing (so you cannot write the function in place of a value), but the function body does return some result (even if it is a null result) when the function is called and its body is evaluated.
A function can be declared in one of two forms:
a) a function with a body:
fn DecodeIOCtl(code)
{
return (
(code >> 16) bit_and 0x0000FFFF;
(code >> 14) bit_and 0x00000003;
(code >> 2) bit_and 0b0111111111111;
code bit_and 0x3
)
};
b) a short notation for small functions:
fn DecodeIOCtlCode(code) => DecodeIOCtl(code);
Documentation Comments
You can attach a description to a custom function using a documentation comment. A documentation comment starts with /// (three forward slashes) and must appear on the line immediately before the fn keyword.
In function libraries (ABCalc Plus), documented functions appear with their description in the ABCalc function list alongside built-in functions. In functions defined inline within an expression, the comment is cosmetic — it is useful for self-documentation, especially when keeping expressions in the history.
/// Returns the hypotenuse length for a right triangle with legs a and b.
fn Hypotenuse(a; b) => Sqrt(a*a + b*b);
/// Decodes a Windows I/O Control Code into its four component fields.
fn DecodeIOCtl(code)
{
return (
(code >> 16) bit_and 0x0000FFFF;
(code >> 14) bit_and 0x00000003;
(code >> 2) bit_and 0b0111111111111;
code bit_and 0x3
)
};
Since version 1.5.0, documentation comments may contain sections similar to C#. The supported sections are "summary", "param" and "returns". The sections provide more convenient representation in the function list. Example:
/// <summary>Decodes a Windows I/O Control Code into its four component fields.</summary>
/// <param name="code">The IOCTL code to decode.</param>
/// <returns>An array of values that compose an IOCTL code.</returns>
fn DecodeIOCtl(code)
{
return (
(code >> 16) bit_and 0x0000FFFF;
(code >> 14) bit_and 0x00000003;
(code >> 2) bit_and 0b0111111111111;
code bit_and 0x3
)
};
Function parameters
A function may include zero, one, or multiple parameters:
fn NoParams() => ...
fn OneParam(param) {...}
fn ManyParams(a; b; c; d; e) {...}
Parameters may be optional. To specify such a parameter and provide a default value to it, put down the name of the parameter followed by "=" and a default value as shown below. The "=" character is used to specify the default value regardless of the option to use ":=" or "=" for an assignment. You may specify zero or more mandatory parameters followed by zero or more optional parameters.
Examples:
fn MyRound(value, up = false) => up ? Round(value) : Trunc(value);
fn MyRound(value, up = false) => iff(up; Round(value); Trunc(value)) // iff is a built-in function that works as a ternary operator.
fn BuildNum(date = null)
{
if (date = null) { date := Today() };
return Trunc(TimespanMSec(date - #2000-01-01#) / 86400000);
};
Returning results
A function may return a value (including a list) or null. The result may be returned implicitly (derived from the last expression in the function body) or explicitly using the return keyword followed by a value or an expression that yields a value during evaluation.
Examples:
fn MeaningOfLife() => 42;
fn MeaningOfLifeExplicit() => return 4*10 + 2;
Functions and Memory Context
The expression and its functions share common memory - they can read and modify the same memory cells (variables). The only exception is function parameters - if there exists a memory cell (variable) X and a function has a parameter named X, then if a function references "X", the value of the parameter will be read and updated, while the memory cell (variable) will not be accessed.
Custom Functions in Libraries
In ABCalc Plus, you can create a library of your own functions. Functions can be stored in one or several files with the ".abcf" extension. Put the file(s) to some directory and specify the location of this directory in the Custom Functions window of ABCalc Plus. The default location is:
- Windows - C:\Users\{username}\AppData\Roaming\ABCalc\Functions
- Linux - typically, /home/{username}/.config/ABCalc/Functions
- macOS - typically, /Users/{username}/Library/Application Support/ABCalc/Functions
The functions in the library are parsed during loading and are executed when an expression references them. When functions are executed, they are isolated and do not have access to main memory cells (variables) but have their own "memory pool" usable for storing intermediate calculation results. This allows you not to worry that variable names in main memory will conflict with the variables in the functions.
Documentation comments (///) work the same way in library files as in inline expressions. Functions with doc comments appear with their descriptions in the ABCalc function list alongside built-in functions.