Skip to content

Methods

A method is written after a value: answers.name.upper(). A method on a missing value gives null, not an error.

A method must fit the value it is called on. A text value has the text methods and a date has the date methods, so today().subDays(90) cannot work: today() gives text. Publishing refuses an expression with a method that cannot apply to its value, and says why. Write mash.date.today().subDays(90) instead.

Every method here is pure. It reads and returns a value, and never changes the form.

A list is a table’s rows, a Choice that allows several options, or a list you write. These methods work on a list directly, or on mash.collect(list), which gives [] when the answer is missing.

MethodGives
sum('key'), avg('key'), average('key'), min('key'), max('key')The total, average, lowest or highest of a column.
count()The number of rows.
pluck('key')A list of one column.
first(), last()The first or last row.
contains('key', value)True when a row has that value.
where('key', value)The rows where the column equals the value.
unique()The list without repeats.
implode('key', separator)One column joined as text.
isEmpty(), isNotEmpty()Whether the list has rows.
{"answers": {"rows": [{"type": "car", "amount": 10}, {"type": "bus", "amount": 20}, {"type": "car", "amount": 30}]}}
mash.collect(answers.rows).sum('amount')
60
answers.rows.count()
3
mash.collect(answers.rows).where('type', 'car').count()
2
mash.collect(answers.rows).pluck('amount')
[10,20,30]
sum(mash.collect(answers.rows).pluck('amount'))
60
mash.collect(answers.rows).contains('type', 'bus')
true
mash.collect(answers.missing).sum('amount')
0

A budget check on a table:

{"answers": {"rows": [{"amount": 10}, {"amount": 20}], "budget": 50}}
mash.collect(answers.rows).sum('amount') <= answers.budget
true

Call these on a text answer, or on mash.str(value), which turns any value into text.

MethodGives
upper(), lower(), trim()The text in capitals, in lower case, without spaces at the ends.
title()The first letter capitalised. title(true) capitalises every word.
length()The number of characters.
slice(start, length)Part of the text. A negative start counts from the end.
replace(from, to)The text with every from replaced.
startsWith(x), endsWith(x), containsAny(x)True or false.
before(x)The text before the first x, or all of it if x is not there.
after(x)The text after the first x, or "" if x is not there.
{"answers": {"name": " ada ", "v": "Hazardous|Asbestos|x"}}
mash.str(answers.name).trim().upper()
"ADA"
mash.str('hello world').title(true)
"Hello World"
mash.str('hello world').slice(0, 5)
"hello"
mash.str('a-b-c').replace('-', '_')
"a_b_c"
answers.v.before('|')
"Hazardous"
answers.v.after('|')
"Asbestos|x"

before and after suit a Lookup whose value packs two things, such as Hazardous|Asbestos.

These are on mash.math.

MethodGives
mash.math.round(x, places)x rounded. Halves round away from 0.
mash.math.floor(x), mash.math.ceil(x)Rounded down or up.
mash.math.abs(x), mash.math.sqrt(x), mash.math.pow(x, y)Absolute value, square root, power.
mash.math.toInt(x)The whole part, towards 0.
mash.math.isNumeric(x), mash.math.isNan(x)True or false.
mash.math.round(13.456, 2)
13.46
mash.math.round(-2.5)
-3
mash.math.toInt(-7.9)
-7
mash.math.isNumeric('abc')
false

Round a table total to pennies:

{"answers": {"r": [{"amount": 10.1}, {"amount": 20.246}]}}
mash.math.round(mash.collect(answers.r).sum('amount'), 2)
30.35

mash.date.parse(value) turns a date answer or text such as 2026-07-10 into a date. A blank or unreadable value gives null. mash.date.today() and mash.date.now() give the clock of the form. A date written back out as text is YYYY-MM-DD HH:MM:SS.

MethodGives
diffInDays(other), diffInWeeks, diffInMonths, diffInYears, diffInHours, diffInMinutesThe signed difference from this date to other.
diffInWeekdays(other), diffInWeekendDays(other)Working days or weekend days from this date, counting it, up to but not counting other.
add(n, unit), sub(n, unit)The date moved by n days, weeks, months, years, hours or minutes.
addDays(n), subDays(n)The date moved by n days.
toDateString(), toDateTimeString(), format(pattern)The date as text.
year, month, day, hour, minute, dayOfWeek, dayOfWeekIsoOne part of the date. dayOfWeek counts Sunday as 0 and dayOfWeekIso counts it as 7.
{"_now": "2026-07-10T12:34:56.000Z", "answers": {"a": "2026-07-01", "b": "2026-07-10", "start": "2026-07-13", "end": "2026-07-17"}}
mash.date.parse(answers.a).diffInDays(mash.date.parse(answers.b))
9
mash.date.parse(answers.b).diffInDays(mash.date.parse(answers.a))
-9
mash.date.parse('2026-07-10').addDays(5).toDateString()
"2026-07-15"
mash.date.parse('2026-07-10').add(2, 'weeks').toDateString()
"2026-07-24"
mash.date.parse('2026-07-10').format('dd/MM/yyyy')
"10/07/2026"
mash.date.today().toDateString()
"2026-07-10"
mash.date.parse('2026-07-12').dayOfWeekIso
7

Counting days of leave, both ends included, is the difference plus one. A blank end date still gives an answer:

mash.date.parse(answers.start).diffInDays(mash.date.parse(answers.end)) + 1
5

Working days, with both ends included:

mash.date.parse(answers.start).diffInWeekdays(mash.date.parse(answers.end).addDays(1))
5

Adding a month to the 31st goes into the next month, as it does in a calendar library:

mash.date.parse('2026-01-31').add(1, 'month').toDateString()
"2026-03-03"

Dates compare with <, > and ==:

mash.date.parse(answers.a) < mash.date.parse(answers.b)
true

A date that cannot be read gives null, and so do the methods on it:

mash.date.parse('nonsense')
null