No matches — try another term.
A complete overview of every built-in function, operator and constant.
Free vs. Pro
Free
| Category | Functions / features |
|---|---|
| Constants | pi, e, inf, today, now |
| Operators | + - * / ^ %, < > <= >= == !=, and or not, .. |
| Trigonometry | sin, cos, tan, asin, acos, atan, atan2 |
| Math | sqrt, abs, exp, log, log10, log2, floor, ceil, round, min, max, pow, sign, clamp, lerp, mod |
| Number systems | 0x/0b/0o literals, hex, bin, oct, dec, band, bor, bxor, bnot, shl, shr |
| Strings | str, len, print |
| Date & time | date, datetime, day, month, year, hour, minute, weekday, days, addmonths, addyears, monthstart, monthend, dformat |
| Proportion | proportion |
| CSV | csv, csvwrite (manual load/save) |
| Language | Variables, labels, line references (@n), comments, units |
| Files & sharing | .dply / .dplylib / .dplybundle, share, open-with |
| Shortcuts | Desktop keyboard shortcuts |
Pro
| Category | Functions / features |
|---|---|
| Matrices | det, inv, transpose, trace, norm, eye, zeros, ones, size |
| Lists | len, range, push, pop, first, last, sort, reverse, contains, list, append |
| Statistics | sum, mean, median, std, variance, mode, percentile, quantile, corr, cov |
| Finance | pv, fv, pmt, nper, rate, npv, irr |
| Control flow | for / while loops with break / continue, if / elif / else |
| Charts | plot, scatter, bar, hist |
| Symbolic algebra | solve, simplify, factor |
| Differentiation | diff (symbolic and numeric) |
| Integration | integrate (symbolic and numeric) |
| User-defined functions | f(x) = …, def name(…): (including recursion) |
| Classes & objects | class Name(…):, methods, instances |
| Form view | Turn a sheet into a fillable form (inputs, outputs, charts, CSV) |
Constants
| Name | Value / meaning |
|---|---|
pi | π ≈ 3.14159265358979… |
e | Euler's number ≈ 2.71828182845904… |
inf | Infinity (∞) |
today | Today's date (no time component) |
now | Current date and time |
Operators
Arithmetic
| Operator | Meaning | Example |
|---|---|---|
+ | Addition | 3 + 4 → 7 |
- | Subtraction | 10 - 3 → 7 |
* | Multiplication | 2 * 5 → 10 |
/ | Division | 7 / 2 → 3.5 |
^ | Power | 2^8 → 256 |
% | Modulo | 10 % 3 → 1 |
A number or parenthesised expression directly in front of a parenthesis is an implicit multiplication: 3(x + 5) = 3 * (x + 5), (1 + 2)(3 + 4) → 21.
Percentages
A % written after a value is a percentage: 19% is 0.19. It binds tighter than * and /, so the percentage stays in one piece — 238 / 119% is 238 / 1.19 → 200, not (238 / 119) / 100.
With + and - a percentage is taken of the left-hand value — that is how you add or remove a markup:
| Expression | Result | Reads as |
|---|---|---|
100 + 10% | 110 | 100 plus 10 % of 100 |
4 + 20% | 4.8 | 4 plus 20 % of 4 |
250 - 15% | 212.5 | 250 minus 15 % of 250 |
100 + 10% + 10% | 121 | two markups in a row |
This applies only to a percentage written directly to the right of + or -. Everywhere else % keeps its plain meaning of "divide by 100":
1200 * 19% → 228 // * and / are unaffected
4 + 20% * 2 → 4.4 // the right side is a product, not a percentage
p = 20%
4 + p → 4.2 // p is 0.2; there is no % in the expression
4 + 5/100 → 4.05 // a real division, not a percentage
A % between two values is the modulo operator (10 % 3 → 1).
Comparison
| Operator | Meaning |
|---|---|
< | Less than |
> | Greater than |
<= | Less than or equal |
>= | Greater than or equal |
== | Equal |
!= | Not equal |
Result: 1 (true) or 0 (false).
Logic
| Operator | Meaning | Example |
|---|---|---|
and | Logical and | x > 0 and x < 10 |
or | Logical or | x < 0 or x > 10 |
not | Negation | not (x == 0) |
Conditional expression
value_if_true if condition else value_if_false — an inline conditional (Python-style). It makes one-liner functions and recursive definitions practical:
discount(n) = 0.1 if n > 100 else 0
fact(n) = 1 if n <= 1 else n * fact(n - 1)
grade(p) = "A" if p >= 90 else "B" if p >= 80 else "C"
It chains right-associatively, so a if c1 else b if c2 else c reads as a if c1 else (b if c2 else c).
Range
| Syntax | Meaning |
|---|---|
a..b | Integer range from a to b (inclusive) |
Used in for loops and plot.
Trigonometry
All angles are in radians.
| Function | Syntax | Result |
|---|---|---|
sin | sin(x) | Sine of x |
cos | cos(x) | Cosine of x |
tan | tan(x) | Tangent of x |
asin | asin(x) | Arcsine, result in [−π/2, π/2] |
acos | acos(x) | Arccosine, result in [0, π] |
atan | atan(x) | Arctangent, result in (−π/2, π/2) |
atan2 | atan2(y, x) | Arctangent of y/x (preserves the quadrant) |
sin(pi / 2) → 1
cos(0) → 1
atan2(1, 1) → 0.7853… (= π/4)
Basic math functions
| Function | Syntax | Result |
|---|---|---|
sqrt | sqrt(x) | Square root of x |
abs | abs(x) | Absolute value |
exp | exp(x) | eˣ |
log | log(x) | Natural logarithm (base e) |
log10 | log10(x) | Logarithm base 10 |
log2 | log2(x) | Logarithm base 2 |
floor | floor(x) / floor(x, digits) | Round down; to digits decimals if given |
ceil | ceil(x) / ceil(x, digits) | Round up; to digits decimals if given |
round | round(x) / round(x, digits) | Round half away from zero; to digits decimals if given |
convert | convert(x, "from", "to") | Convert between units, incl. temperatures (see below) |
defunit | defunit("name") / defunit("name", "base") / defunit("name", factor, "base") | Define a custom unit (see below) |
min | min(a, b) / min(list) | The smaller of two values, or the smallest element of a list |
max | max(a, b) / max(list) | The larger of two values, or the largest element of a list |
pow | pow(x, n) | x to the power of n (same as x^n) |
sign | sign(x) | Sign: −1, 0 or 1 |
clamp | clamp(x, min, max) | Clamp x to the range [min, max] |
lerp | lerp(a, b, t) | Linear interpolation: a + t*(b−a); t=0 → a, t=1 → b |
mod | mod(a, b) | Remainder of a÷b (same as a % b, but as a function) |
sqrt(144) → 12
log(e) → 1
log10(1000) → 3
floor(3.7) → 3
ceil(3.2) → 4
round(3.14159, 2) → 3.14
round(3.14159 m, 2)→ 3.14 m (keeps the unit)
sign(-5) → -1
min(3, 5) → 3
max([3, 1, 2]) → 3
clamp(15, 0, 10) → 10
clamp(-3, 0, 10) → 0
lerp(0, 100, 0.25) → 25
mod(17, 5) → 2
Unit conversion — convert
convert(value, "from", "to") converts a value between units. The units are given as text. Temperatures (C/°C, F/°F, K) are converted with their offset; all other units multiplicatively. Only units of the same physical kind convert into each other (length↔length, not length↔mass), and currencies are rejected (no fixed rate).
convert(20, "C", "F") → 68
convert(0, "C", "K") → 273.15
convert(5, "km", "m") → 5000 m
convert(1000, "nm", "µm") → 1 µm
convert(5, "mm", "µm") → 5000 µm
convert(2, "h", "min") → 120 min
convert(36, "km/h", "m/s") → 10 m/s
convert(5, "km", "cm") → 500000 cm (exact — no rounding artifacts)
Length supports the full metric range: nm, µm (or um), mm, cm, dm, m, km. The µ sign only works inside the convert text arguments; for an inline unit (5um + 3um) use the ASCII alias um.
Conversions across many powers of ten are computed exactly: the decimal shift is applied to numerator/denominator instead of multiplying by an inexact factor, so integer results such as convert(5, "km", "cm") → 500000 stay clean.
Imperial units. Common imperial units are built in and mix freely with metric ones via convert:
Length: in, ft, yd, mi Mass: lb, oz * Volume (US measures): gal, qt, pt, floz
convert(1, "mi", "km") → 1.609344 km
convert(1, "mi", "ft") → 5280 ft
convert(1, "lb", "oz") → 16 oz
convert(1, "gal", "L") → 3.785411784 L
3ft + 2ft → 5 ft
The result carries the target unit (except temperatures, which are plain numbers), so it keeps calculating: convert(5, "km", "m") + 100 m → 5100 m.
More physical quantities. Beyond length, mass and time these units are built in and convert within their own kind:
Volume (metric): ml, dl, L (or l) Energy: J, kJ, Wh, kWh Power: W, kW, MW Force: N, kN Pressure: Pa, bar Frequency: Hz, kHz, MHz
convert(1, "kWh", "J") → 3600000 J
2kWh + 500Wh → 2.5 kWh
convert(1, "bar", "Pa") → 100000 Pa
1.5L + 3dl → 1.8 L
Custom units — defunit
Define your own units, e.g. for an electrical-engineering library. Once defined, a unit works both inline (12 V) and in convert.
| Form | Meaning |
|---|---|
defunit("V") | New base unit with its own dimension |
defunit("Ohm", "V/A") | Derived unit (factor 1) from existing units |
defunit("kOhm", 1000, "Ohm") | Scaled unit: 1 kOhm = 1000 Ohm |
defunit("V")
defunit("A")
defunit("Ohm", "V/A")
defunit("kOhm", 1000, "Ohm")
convert(1, "kOhm", "Ohm") → 1000 Ohm
U = 12 V → 12 V
Custom units are document-local (they reset per document). Put defunit(...) calls at the top of a .dplylib library and import it to share a unit set across documents. Only units of the same dimension convert into each other.
Multiplying and dividing units reduces the result to its base unit whenever one has the same dimension, converting the value accordingly. Because Ohm is defined as V/A, the compound units cancel to the expected named result:
470 Ohm * 10 mA → 4.7 V (Ohm·A cancels to voltage)
5 V / 25 mA → 200 Ohm (reduced to base Ohm, not 0.2 kOhm)
12 V / 4 A → 3 Ohm
1 / Ohm → 1 S (reciprocal → conductance)
H / Ohm → 1 s (time constant)
Two units of the same dimension combine into a power (the value is converted): 5 mm 10 m → 0.05 m², 2 Ohm 3 kOhm → 6000 Ohm². If no named unit matches (e.g. 100 W * 2 h → 200 W·h), the compound form is kept.
A power belongs to the unit, not to the quantity: 54 m^2 and 54 m² are both 54 square metres. Put the quantity in brackets to square it as a whole ((54 m)^2 → 2916 m²).
Automatic prefix for display. When a result falls outside the range [0.1, 1000), it is shown in the unit that brings it into a nice range — chosen among your own units and the metric 1000-step prefixes:
1 V / 1 mA → 1 kOhm (not 1000 Ohm)
0.001 V → 1 mV
1500 m → 1.5 km
0.008 m → 8 mm
This is display-only: the stored value is unchanged, so @n references and further math keep full precision. Values already in range (200 Ohm, 0.5 m), compounds (50 km/h), powers (20 m²) and currencies are left as-is, and it never switches between metric and imperial.
Number systems (binary, octal, hex)
Numbers can be entered in binary, octal or hexadecimal using the prefixes 0b, 0o and 0x. They are ordinary numbers and mix freely with decimal values and all other functions. Conversion functions turn a value back into a string in a given base, and dec parses such a string into a number.
| Function | Syntax | Result |
|---|---|---|
0x… | 0xFF | Hexadecimal literal (0xFF → 255) |
0b… | 0b1010 | Binary literal (0b1010 → 10) |
0o… | 0o100 | Octal literal (0o100 → 64) |
hex | hex(x) | x as a hexadecimal string (0x…) |
bin | bin(x) | x as a binary string (0b…) |
oct | oct(x) | x as an octal string (0o…) |
dec | dec("0xFF") | Parse a 0x/0b/0o/decimal string to a number |
0xFF → 255
0b1010 → 10
0o100 → 64
0xFF + 1 → 256
hex(255) → 0xFF
bin(10) → 0b1010
oct(64) → 0o100
hex(-255) → -0xFF
dec("0xFF") → 255
dec(hex(1234)) → 1234
Bitwise operations
Bitwise functions operate on integers (fractional parts are truncated). ^ is reserved for exponentiation, so XOR is the bxor function rather than an operator.
| Function | Syntax | Result |
|---|---|---|
band | band(a, b) | Bitwise AND |
bor | bor(a, b) | Bitwise OR |
bxor | bxor(a, b) | Bitwise XOR |
bnot | bnot(a) | Bitwise NOT (complement) |
shl | shl(a, n) | Shift a left by n bits |
shr | shr(a, n) | Shift a right by n bits |
band(12, 10) → 8
bor(12, 10) → 14
bxor(12, 10) → 6
bnot(0) → -1
shl(1, 4) → 16
shr(256, 2) → 64
hex(band(0xF0, 0x3C)) → 0x30
Calculus Pro
Symbolic (2 arguments)
| Function | Syntax | Result |
|---|---|---|
diff | diff(expr, var) | Symbolic derivative with respect to var |
integrate | integrate(expr, var) | Symbolic indefinite integral |
diff(x^3, x) → 3x²
diff(sin(x), x) → cos(x)
integrate(x^2, x) → x³/3
integrate(sin(x), x) → −cos(x)
Numeric (3 or 4 arguments)
| Function | Syntax | Result |
|---|---|---|
diff | diff(expr, var, point) | Numeric derivative at a point (central difference) |
integrate | integrate(expr, var, a, b) | Numeric integral from a to b (Simpson's rule) |
diff(x^2, x, 3) → 6
integrate(x^2, x, 0, 3) → 9
Symbolic algebra (CAS) Pro
| Function | Syntax | Result |
|---|---|---|
solve | solve(expr, var) | Roots / solutions |
solve | solve(eq1, eq2, …, var1, var2, …) | Solve a system of equations |
simplify | simplify(expr) | Expand & combine a polynomial |
factor | factor(expr) | Factor an expression |
solve(x^2 - 4, x) → x = -2, x = 2
solve(x^2 + 2*x + 1 == 0, x) → x = -1
solve(x + y == 3, x - y == 1, x, y) → x = 2, y = 1
simplify(2*x + 3*x) → 5x
simplify((x + 1)^2) → x² + 2x + 1
factor(x^2 - 4) → (x − 2)(x + 2)
factor(x^2 + 2*x + 1) → (x + 1)²
simplify expands and combines polynomials (powers with non-negative integer exponents). It does not cancel divisions by a variable (x^2 / x) or apply trigonometric identities (sin(x)^2 + cos(x)^2) — those report an error.
Matrices Pro
Inside […], , and ; separate elements and ;; separates rows:
v = [1, 2, 3] // row vector
v = [1; 2; 3] // row vector (semicolon also separates elements)
A = [1, 2 ;; 3, 4] // 2×2 matrix (;; = new row)
c = [1 ;; 2 ;; 3] // column vector (3×1)
Comma-decimal mode: when the number format uses a comma as the decimal point, , is the decimal sign, so use ; to separate values unambiguously — [1,5; 2,5] is the vector [1.5, 2.5], and ;; still starts a new row. The same applies to function arguments: sum(1,5; 2,5).
| Function | Syntax | Result |
|---|---|---|
det | det(A) | Determinant (square matrix) |
inv | inv(A) | Inverse (square matrix) |
transpose | transpose(A) | Transpose |
trace | trace(A) | Trace (sum of diagonal elements) |
norm | norm(A) | Frobenius norm; for a scalar: abs(x) |
eye | eye(n) | n×n identity matrix (up to 1000×1000) |
zeros | zeros(n) / zeros(r, c) | Matrix of zeros |
ones | ones(n) / ones(r, c) | Matrix of ones |
size | size(A) / size(A, dim) | [rows, cols]; dim=1 → rows, dim=2 → cols |
det([1, 2 ;; 3, 4]) → -2
inv([1, 2 ;; 3, 4]) → [[-2, 1], [1.5, -0.5]]
transpose([1, 2 ;; 3, 4]) → [[1, 3], [2, 4]]
trace([1, 2 ;; 3, 4]) → 5
eye(3) → [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
zeros(2, 3) → [[0, 0, 0], [0, 0, 0]]
size([1, 2 ;; 3, 4]) → [2, 2]
size([1, 2 ;; 3, 4], 1) → 2
Collapsing tall outputs
Multi-row matrix results can be collapsed to a one-line summary ([42×1] 1…) — click the chevron next to the line number, or tap the summary to expand again. On small screens (phones in portrait) tall matrix outputs start collapsed, like plots.
Lists & arrays Pro
Lists are internally 1×n matrices: [1, 2, 3].
| Function | Syntax | Result |
|---|---|---|
len | len(list) | Number of elements |
range | range(end) | Integers 0 to end−1 |
range | range(start, end) | Integers start to end−1 (up to 100,000) |
range | range(start, end, step) | With a custom step |
push | push(list, value) | Append an element (returns a new list) |
pop | pop(list) | Remove the last element (returns a new list) |
first | first(list) | First element |
last | last(list) | Last element |
sort | sort(list) | Sorted ascending (returns a new list) |
reverse | reverse(list) | Reversed order (returns a new list) |
contains | contains(list, value) | 1 if present, otherwise 0 |
list | list(a, b, …) | Generic list of arbitrary values (see below) |
append | append(list, value) | Append to a generic list (returns a new list) |
map | map(f, list) | Apply function f to each element |
filter | filter(f, list) | Keep elements where f(element) is true (≠ 0) |
len([10, 20, 30]) → 3
range(5) → [0, 1, 2, 3, 4]
range(2, 6) → [2, 3, 4, 5]
range(0, 10, 2) → [0, 2, 4, 6, 8]
push([1, 2], 3) → [1, 2, 3]
pop([1, 2, 3]) → [1, 2]
first([5, 6, 7]) → 5
last([5, 6, 7]) → 7
sort([3, 1, 2]) → [1, 2, 3]
reverse([1, 2, 3]) → [3, 2, 1]
contains([1, 2, 3], 2) → 1
Generic lists
A generic list holds arbitrary values — whole vectors, named lists, strings or numbers — without flattening them. It is the tool for collecting results in a loop and reading them back one by one.
Create one with list(...) (or list() for an empty list) and grow it with append. A bracket literal whose elements are not plain numbers — such as [v1, v2] with vectors — also forms a generic list.
Results = list()
for i in 1..3:
Results = append(Results, [i, i*2, i*3])
Results → [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
Results[1] → [2, 4, 6] (the whole second vector)
sum(Results[1]) → 12
len(Results) → 3
Access is 0-based; negative indices count from the end (Results[-1] is the last element). Results[0] = [9, 9, 9] replaces an element, for v in Results: iterates over the elements, and first/last/reverse/push/pop work element-wise. Aggregations such as sum and mean flatten all numeric values inside the list, including the elements of contained vectors.
map & filter
map(f, list) applies a function to each element; filter(f, list) keeps the elements for which the function is true. The first argument is a function name — a reference, not a call — and may be a builtin or one of your own functions. They replace many explicit for loops.
square(x) = x^2
map(square, [1, 2, 3]) → [1, 4, 9]
map(sqrt, [1, 4, 9]) → [1, 2, 3]
even(n) = n % 2 == 0
filter(even, [1, 2, 3, 4, 5, 6]) → [2, 4, 6]
sum(map(square, [1, 2, 3])) → 14
Named lists
A named list labels each value with a key, so you can read it back by name instead of by position. Write the entries as key: value inside the brackets. Keys may be quoted ("Strom") or, if they are a single word, bare (Strom). The list can span several lines.
Expenses = [
"Electricity": 120,
"Water": 80,
"Rent": 900
]
Expenses["Electricity"] → 120
sum(Expenses) → 1100
len(Expenses) → 3
mean(Expenses) → 366.67
Access and update entries by key; assigning a new key adds it:
Expenses["Internet"] = 40 // adds a new entry
sum(Expenses) → 1140
Entries can also be read by position (0-based, like a list), which keeps the unit too:
Expenses[0] → 120 (first entry)
Expenses[-1] → 40 (last entry)
List and statistics functions (sum, mean, median, std, min, max, sort, len, …) operate on the values, in the order the entries were written.
Entries may carry units, and they are kept — both when reading a single entry and when aggregating, as long as all entries share the same unit:
Costs = ["Electricity": 120 €, "Water": 80 €]
Costs["Electricity"] → 120 €
sum(Costs) → 200 €
max(Costs) → 120 €
Values may also be anything — vectors, lists, strings — not just numbers:
Series = ["Jan": [10, 12, 9], "Feb": [11, 8, 14]]
Series["Feb"] → [11, 8, 14] (the whole vector)
keys(Series) → [Jan, Feb]
values(Series) → [[10, 12, 9], [11, 8, 14]]
keys(d) and values(d) return the keys and values as a list. Aggregations still work over the numeric entries and skip non-numeric ones.
Statistics Pro
All statistics functions accept either a list or comma-separated values.
| Function | Syntax | Result |
|---|---|---|
sum | sum(list) / sum(a, b, …) | Sum of all values |
mean | mean(list) / mean(a, b, …) | Arithmetic mean |
median | median(list) / median(a, b, …) | Median (middle value) |
std | std(list) / std(a, b, …) | Sample standard deviation (÷ n−1) |
variance | variance(list) / variance(a, b, …) | Sample variance (÷ n−1) |
mode | mode(list) / mode(a, b, …) | Most frequent value |
percentile | percentile(list, p) | p-th percentile (p: 0–100), linear interpolation |
quantile | quantile(list, q) | q-th quantile (q: 0–1), linear interpolation |
corr | corr(xs, ys) | Pearson correlation coefficient |
cov | cov(xs, ys) | Sample covariance (÷ n−1) |
linreg | linreg(xs, ys) | Linear regression → [slope, intercept, r2] |
sum([1, 2, 3, 4]) → 10
mean(2, 4, 6) → 4
median([1, 3, 5, 7]) → 4
std(2, 4, 4, 4, 5, 5, 7, 9) → 2
variance([2, 4, 4, 4, 5, 5, 7, 9]) → 4
mode([1, 2, 2, 3]) → 2
percentile([1, 2, 3, 4, 5], 75) → 4
quantile([1, 2, 3, 4, 5], 0.5) → 3
xs = [1, 2, 3, 4, 5]
ys = [2, 4, 5, 4, 5]
corr(xs, ys) → 0.9079
cov(xs, ys) → 1.75
linreg fits a straight line y = slope·x + intercept and returns a named list with slope, intercept and the coefficient of determination r2:
r = linreg([1, 2, 3, 4], [2.1, 3.9, 6.2, 7.8])
r["slope"] → 1.9…
r["intercept"] → 0.1…
r["r2"] → 0.99…
Finance Pro
All finance functions use standard Excel-compatible sign conventions: inflows positive, outflows negative. rate as a decimal (5 % = 0.05).
| Function | Syntax | Result |
|---|---|---|
pv | pv(rate, nper, pmt [, fv]) | Present value of an annuity; fv defaults to 0 |
fv | fv(rate, nper, pmt [, pv]) | Future value of an annuity; pv defaults to 0 |
pmt | pmt(rate, nper, pv [, fv]) | Periodic payment; fv defaults to 0 |
nper | nper(rate, pmt, pv [, fv]) | Number of periods; fv defaults to 0 |
rate | rate(nper, pmt, pv [, fv]) | Interest rate per period (Newton–Raphson, 300 iter.) |
npv | npv(rate, cashflows) | Net present value of future cashflows (list) |
irr | irr(cashflows) | Internal rate of return (Newton–Raphson, 300 iter.) |
// Monthly payment on a 200 000 € loan, 5 % p.a. over 20 years
rate_m = 0.05 / 12
pmt(rate_m, 240, 200000) → -1319.91
// Future value of 200 €/month over 10 years at 4 % p.a.
fv(0.04 / 12, 120, -200) → 29 411.03
// Present value of receiving 1 000 €/year for 5 years at 6 %
pv(0.06, 5, 1000) → 4212.36
// IRR of a project: invest 1 000 €, receive 400 € each of 3 years
irr([-1000, 400, 400, 400]) → 0.0974 // ≈ 9.74 %
Strings
| Function | Syntax | Result |
|---|---|---|
str | str(value) | Convert a number, matrix or date to text |
len | len(text) | Length of the string (number of characters) |
ord | ord(text) | Unicode code point(s): a single character → a number, a longer string → the list of its code points |
char | char(code) | The character(s) for a code point or a list of code points — the inverse of ord |
print | print(value) | Print value or string in the result column |
str(42) → "42"
str([1, 2, 3]) → "[[1, 2, 3]]"
len("Hello") → 5
ord("A") → 65
ord("Hi") → [72, 105]
char(65) → "A"
char([72, 105]) → "Hi"
char(ord("draft")) → "draft" (round-trips)
ord/char bridge text and numbers, so a string can be processed byte-wise (hashing, XOR/Caesar ciphers, checksums) and turned back into text.
Date & time
Constructors
| Function | Syntax | Result |
|---|---|---|
date | date(year, month, day) | Date value |
datetime | datetime(year, month, day, hour, minute) | Date with time |
datetime | datetime(year, month, day, hour, minute, second) | Date with seconds |
Extractors
| Function | Syntax | Result |
|---|---|---|
day | day(d) | Day (1–31) |
month | month(d) | Month (1–12) |
year | year(d) | Year (e.g. 2025) |
hour | hour(d) | Hour (0–23) |
minute | minute(d) | Minute (0–59) |
weekday | weekday(d) | Weekday: 1 = Monday … 7 = Sunday (ISO 8601) |
Arithmetic & formatting
| Function | Syntax | Result |
|---|---|---|
days | days(d1, d2) | Difference in days (d1 − d2) |
addmonths | addmonths(d, n) | Add n months (day clamped to month end if needed) |
addyears | addyears(d, n) | Add n years (Feb 29 → Feb 28 in non-leap years) |
monthstart | monthstart(d) | First day of the month |
monthend | monthend(d) | Last day of the month |
dformat | dformat(d) | Default format (e.g. "13.06.2026") |
dformat | dformat(d, "pattern") | Custom format (see placeholders below) |
- | d1 - d2 | Difference in days (shorthand) |
Placeholders for dformat:
| Placeholder | Meaning |
|---|---|
yyyy | Four-digit year |
MM | Two-digit month (01–12) |
dd | Two-digit day (01–31) |
HH | Two-digit hour (00–23) |
mm | Two-digit minute (00–59) |
ss | Two-digit second (00–59) |
d = date(2026, 6, 13)
day(d) → 13
weekday(d) → 6 // Saturday
days(date(2026, 12, 31), d) → 201
dformat(d, "dd.MM.yyyy") → "13.06.2026"
addmonths(d, 3) → 2026-09-13
addmonths(date(2026, 1, 31), 1) → 2026-02-28 // clamped to Feb end
addyears(d, 1) → 2027-06-13
monthstart(d) → 2026-06-01
monthend(d) → 2026-06-30
datetime(2026, 6, 13, 14, 30)
today → current date
now → current date and time
Charts Pro
plot — line chart
plot(expr)
plot(expr, from..to)
plot(expr, from, to)
plot(expr, from..to, yFrom..yTo)
plot(expr, from..to, yFrom..yTo, steps)
plot(expr1, expr2, …, from..to)
plot(expr, ..., "title", "x axis", "y axis")
plot(expr, ..., "logy")
| Parameter | Meaning | Default |
|---|---|---|
expr | Expression in x | — |
from..to | x range (range syntax) | −2π .. 2π |
from, to | x range (legacy syntax, 3 arguments) | −2π, 2π |
yFrom..yTo | Fix the y axis | automatic |
steps | Number of sample points (2 – 10,000) | 300 |
"…" strings | Chart title, x-axis and y-axis label (in order) | none |
"logx", "logy", "loglog" | Logarithmic scaling of the x, y, or both axes | linear |
String arguments may appear in any position; the scaling keywords "logx", "logy" and "loglog" are recognized as options, all other strings are assigned in order as title, x-axis label and y-axis label.
On a logarithmic axis only positive values are shown (non-positive points are skipped) and the gridlines snap to full decades. Tooltips and CSV/SVG export keep the real (un-transformed) values.
Several curves in one plot: pass more than one expression before the range. Each gets its own colour and an automatic legend (labelled with the expression), and the CSV export gets one column per curve:
plot(sin(x), cos(x), 0..2*pi)
plot(x, 2*x, 3*x, 0..5, "Comparison")
plot(sin(x))
plot(x^2, -5..5)
plot(x^3, -10, 10)
plot(sin(x), -pi..pi, -1..1, 500)
plot(sin(x), "Oscillation", "time t", "amplitude")
plot(exp(x), 1..20, "logy")
plot(x^3, 1..1000, "loglog")
scatter — point cloud
scatter(xs, ys)
scatter(xs, ys, "title", "x axis", "y axis")
Both data arguments must be lists or vectors of equal length. String arguments are assigned in order as title, x-axis and y-axis label.
scatter([1, 2, 3, 4], [1, 4, 9, 16])
scatter(xs, ys, "Measurements", "time", "value")
bar — bar chart
bar(values)
bar(values, xs)
bar(values, ..., "title", "x axis", "y axis")
Draws a bar chart. values is a list of bar heights. The optional xs argument provides explicit x positions (must have the same length as values); without it the bars are numbered 0, 1, 2, …
| Parameter | Meaning | Default |
|---|---|---|
values | List of bar heights | — |
xs | Explicit x positions for the bars | 0, 1, 2, … |
"…" strings | Chart title, x-axis and y-axis label (in order) | none |
bar([12, 7, 19, 5])
sales = [4200, 5100, 3800, 6300]
bar(sales)
bar([10, 20, 30], [2020, 2021, 2022])
bar([12, 19, 7], "Revenue", "month", "kEUR")
hist — histogram
hist(data)
hist(data, bins)
hist(data, ..., "title", "x axis", "y axis")
Bins the data into a frequency histogram and draws it. Bars touch to emphasise the continuous distribution.
| Parameter | Meaning | Default |
|---|---|---|
data | List of values to bin | — |
bins | Number of bins (2 – 200) | 10 |
"…" strings | Chart title, x-axis and y-axis label (in order) | none |
data = [2, 5, 3, 8, 5, 7, 5, 3, 4, 6, 7, 5]
hist(data)
hist(data, 5)
hist(data, 5, "Distribution", "value", "count")
Labeled chart lines: a label in front of any chart call becomes the chart title if no explicit title string is given — Revenue: bar([12, 19, 7]) draws the chart with the title "Revenue".
Export: every chart has overlay buttons for SVG, PNG and CSV. Title and axis labels are included in the SVG export.
CSV import / export
CSV files are read and written manually — never automatically on every keystroke. A load/save button appears in the result row of any line that uses csv(…) or csvwrite(…).
total = csv("sales") // column 1 of the picked file
q2 = csv("sales", 2) // column 2 (1-based)
rev = csv("sales", "revenue") // column by header name
csvwrite([1, 2, 3], "out") // shows a save button
| Function | Meaning |
|---|---|
csv("name") | First column as a list |
csv("name", n) | Column n (1-based) |
csv("name", "header") | Column by header name |
csvwrite(data, "name") | Export a list/matrix as CSV (manual save button) |
What the name is for
The string in csv("name") is a display name / key, not a file path. Clicking the load button opens a native file dialog; the name only labels the import. It does three things:
1. Tells imports apart. Several independent sources can live in one document, each with its own load button and its own file: `` revenue = csv("revenue") costs = csv("costs") ` 2. Load once, use many columns. Every call with the same name shares the one loaded table, so you pick the file only once: ` month = csv("sales", 1) units = csv("sales", 2) price = csv("sales", "price") `` 3. Drives the load indicator. The button shows, per name, whether data is already in memory (a check mark) or still needs loading.
Loaded data lives in memory only — after restarting the app you load it again, and the name is the stable label that reconnects a formula to its source. The delimiter (;, tab or ,) and a header row are detected automatically; with ;/tab a decimal comma is accepted.
Proportion
| Function | Syntax | Result |
|---|---|---|
proportion | proportion(a, b, c) | a · c / b |
Solves: a : b = ? : c
proportion(3, 4, 8) → 6 // 3:4 = 6:8
Control flow (user functions) Pro
For loop
for i in 1..n:
…
for i in list:
…
Maximum 10,000 iterations. Integer range: at most 10,000 steps.
Use break to exit the loop immediately, continue to skip ahead to the next iteration:
for i in 1..10:
if i == 5:
break
if i % 2 == 0:
continue
…
While loop
while condition:
…
break and continue work the same way as in for.
If / elif / else
if condition:
…
elif another_condition:
…
elif yet_another:
…
else:
…
Any number of elif branches are allowed; else is optional.
Return
return value
Recursion
Maximum 100 levels of call depth.
User-defined functions Pro
Short form (single line)
f(x) = x^2 + 2*x
Long form with def
def name(param1, param2, optParam = defaultValue):
…
return result
def factorial(n):
s = 1
for i in 1..n:
s = s * i
return s
factorial(6) → 720
Parameters may be numbers, lists/vectors or strings — a function can take a whole vector and index into it:
def dot(a, b):
s = 0
for i in 0..len(a) - 1:
s = s + a[i] * b[i]
return s
dot([1, 2, 3], [4, 5, 6]) → 32
Classes Pro
class Name(param1, param2, …):
def method():
return …
The parameters in the class header become fields of the instance; inside a method you read them as self.param1.
class Circle(r):
def area():
return pi * self.r^2
def circumference():
return 2 * pi * self.r
c = Circle(5)
c.area() → 78.5398…
c.circumference() → 31.4159…
Form view Pro
The form view turns a sheet into a clean, fillable form: labelled input fields at the top, computed results below, plus any charts and CSV load/save buttons. The underlying document is unchanged — the form only reads and writes the variables you point it at, so switching back to the editor shows the same sheet.
Open the Form menu:
- Edit form… opens the form editor.
- Form view (appears once a form is defined) toggles between the code editor
and the filled-in form.
Inputs
Each input links a label to a variable in the sheet. In the form, an input is one of two kinds:
- A number field. Typing a value writes it back to that variable's
- A choice of chips. Give the input a set of
label : valueoptions and it
assignment (kapital = 1000). An optional unit is shown as a suffix and appended automatically, so kapital = 1000 € stays intact while you only edit the number.
becomes a row of tap-to-select chips — handy for switching an assignment between a few fixed values (e.g. Reinvest? → Yes = 1 / No = 0).
Outputs
An output links a label to a variable whose computed result is shown read-only, formatted with the sheet's precision and its unit. Outputs update as soon as an input changes.
Charts and CSV
- Charts — pick which chart lines (
plot,scatter,bar, - CSV — each
csv(…)load andcsvwrite(…)save in
hist) appear in the form.
the sheet gets a row in the form; you can give it a friendlier label or hide it.
Automatic mode
The editor can read the sheet and propose a starting point instead of adding every field by hand. When it finds candidates, a banner offers Apply:
- Inputs — every variable set to a plain value without a formula
- Outputs — every variable that (directly or indirectly) depends on one of
(kapital = 1000, weg = 12 km); its unit is filled in automatically.
those inputs (zinsen = kapital * satz / 100).
It only fills fields that aren't already present, and it never runs on its own — apply it, then remove what you don't need and add the labels. Variables defined inside for/while/if/def blocks and function definitions are ignored.
How it is stored
A form lives in the sheet's frontmatter as form_* fields, so it travels with the .dply file:
---
form_title: Compound interest
form_description: Quick estimate
form_inputs: Capital|kapital{€}, Reinvest?|reinvest[Yes:1,No:0]
form_outputs: Net gain (€)|net_gain
form_plots: 1
---
| separates the label from the variable, {unit} adds a unit, and [label:value,…] defines chip options.
Miscellaneous
Line references
@1, @2, … — refer to the result of that line.
5 * 3 → 15
@1 + 10 → 25
Comments
// single-line comment
# also a comment
Labels
VAT: 0.19 * 100 → VAT: 19
The label is the text before the :. It may contain letters, digits, spaces and hyphens. If it needs other characters — parentheses, /, a currency sign — wrap it in quotes; the quotes are dropped from the output:
"Area (m²)": 4.5 * 12 → Area (m²): 54
Running total
A line containing just total sums the results of the lines above it, back to the last blank line, heading/comment or a previous total. Ideal for shopping lists and budgets:
# Groceries
12.50
8.00
3.20
total → 23.70
It keeps a shared unit (10 kg + 20 kg = 30 kg) and takes an optional label (Total: total).
Library import
import "file.dplylib"
Debug / print
print(x) // prints x in the result column
Bracket matching
The editor helps you keep parentheses () and brackets [] balanced:
- Unbalanced brackets are marked red. If a bracket has no partner — an
- Matching pair highlight. Place the cursor next to a bracket and its
- Clear error message. A line with a missing closing bracket now reports
opening ( that is never closed, or a stray closing ) — it is highlighted in red so you can see exactly where the problem is.
matching partner is highlighted (like a spreadsheet), so nested expressions are easy to follow.
e.g. "Unclosed bracket: 1× ) missing" instead of a generic "Unknown input".
cos((1+2)*3 → Unclosed bracket: 1× ) missing (first ( shown red)
Number format
Settings → Number format controls how results and numbers in the editor are displayed:
- Decimal separator — Automatic (follows your system language), Period
- Thousands separator — a toggle to turn digit grouping on or off. With it
(1,234.56) or Comma (1.234,56). In comma mode use ; to separate list and function-argument values (see Lists & arrays).
off, numbers are shown without grouping (1234567 instead of 1,234,567); the decimal separator is unaffected. Applies to both results and the editor.
Files, sharing & open-with
draftply files are plain text with a small header, so they travel well.
| Extension | Contents |
|---|---|
.dply | A notebook (document). |
.dplylib | A function/unit library you import into a document. |
.dplybundle | A notebook packaged together with its libraries in one file. |
Sharing. File → Share sends the current draft through your operating system's share sheet. If the document uses imported libraries, it is shared as a self-contained .dplybundle (so it still works for the recipient); otherwise as a plain .dply. Library → Share exports the document's functions as a .dplylib. Sharing appears where the OS provides a share sheet (iOS, Android, macOS, Windows).
Open with draftply. Opening a .dply, .dplylib or .dplybundle from another app or your file manager opens it in draftply as a new draft (the content is copied in — the original file is not linked). For safety, a document that arrives from another app is not evaluated automatically: a banner lets you review the content first and press Evaluate to run it.
Keyboard shortcuts
Desktop shortcuts. On macOS use ⌘ (Cmd) instead of Ctrl.
| Shortcut | Action |
|---|---|
Ctrl + N | New draft |
Ctrl + O | Open file |
Ctrl + S | Save |
Ctrl + Shift + S | Save as… |
Ctrl + P | Print / Save as PDF |
Ctrl + , | Settings |
Ctrl + F | Search in the document |
Ctrl + Z · Ctrl + Shift + Z / Ctrl + Y | Undo · Redo |
Ctrl + C · Ctrl + X · Ctrl + V · Ctrl + A | Copy · Cut · Paste · Select all |
Tab or Enter | Accept autocomplete |
↑ · ↓ | Navigate the autocomplete list |