Skip to content

Collections

A collection holds many values under one name. MaSH has two basic kinds, arrays and dictionaries, and a toolkit called mash.collect for working on them.

An array is an ordered list in square brackets:

set colours to ["red", "green", "blue"]
printline colours[0]
printline colours[2]
printline count(colours)
red
blue
3

Positions start at 0, so the first item is colours[0]. count() tells you how many items there are. (Arrays have no .length.)

Change an item by its position, and add one to the end with []:

set colours to ["red", "green"]
set colours[0] to "pink"
colours[] = "blue"
printline colours
Array [
"pink",
"green",
"blue"
]

Arrays can hold anything, including other arrays:

set grid to [[1, 2], [3, 4]]
printline grid[1][0]
3

A dictionary stores values under names, called keys. Use curly braces:

set person to {name: "Ada", age: 36}
printline person["name"]
printline person.age
Ada
36

Read a value with ["key"] or with a dot. Add or change one the same way:

set person to {name: "Ada"}
set person["age"] to 36
set person.city to "London"
printline person
Dictionary {
"name": "Ada",
"age": 36,
"city": "London"
}

Reading a key that isn’t there gives null, not an error. That makes ?? a good fit:

set person to {name: "Ada"}
printline person["phone"] ?? "no phone on file"
no phone on file

Dictionaries can nest, and an array can hold dictionaries. This is the shape of most data you’ll get from files and web services:

set orders to [
{ref: "A-1", total: 40},
{ref: "A-2", total: 15}
]
each orders as order
printline "{{order.ref}}: {{order.total}}"
end
A-1: 40
A-2: 15

Wrap an array or dictionary in mash.collect() and you get a Collection with lots of helper methods. Many of them take a block of script, which is a small piece of code run once per item. You’ll write blocks properly in Blocks. For now, copy the shape.

set prices to mash.collect([12, 30, 8])
printline prices.sum()
printline prices.max()
printline prices.min()
printline prices.avg()
printline prices.count()
printline prices.join(", ")
50
30
8
16.666666666667
3
12, 30, 8

filter keeps the items for which the block returns true:

set people to mash.collect([
{name: "Ada", age: 36},
{name: "Bo", age: 17},
{name: "Cy", age: 52}
])
set adults to people.filter(block person
return person["age"] is more than or equal to 18
end)
printline adults.count()
printline adults.pluck("name").join(" and ")
2
Ada and Cy

pluck pulls one key out of every item. sum("age") adds up one key. where is a shortcut for simple matches:

set people to mash.collect([
{name: "Ada", team: "x", age: 36},
{name: "Bo", team: "y", age: 17},
{name: "Cy", team: "x", age: 52}
])
printline people.sum("age")
printline people.where("team", "x").count()
printline people.sortBy("age").first()["name"]
printline people.sortByDesc("age").first()["name"]
105
2
Bo
Cy

map builds a new collection from the results of a block:

set names to mash.collect(["ada", "bo"])
set shouted to names.map(block n
return mash.str(n).upper().toString()
end)
printline shouted.join(", ")
ADA, BO
set n to mash.collect([5, 2, 8])
printline n.sort().values().join(", ")
printline n.sortDesc().values().join(", ")
2, 5, 8
8, 5, 2

A sorted collection remembers where each item used to sit. Add .values() before you print or join so the order is tidy.

A collection works in each just like an array:

set people to mash.collect([{name: "Ada"}, {name: "Bo"}])
each people as person
printline person["name"]
end
Ada
Bo

Many of the things MaSH gives back, such as a list of files, are collections. You can filter, sort and total them with the methods above.

A plain dictionary takes the same methods. person.has("name") and person.keys() work, and person.remove("name") changes person itself.

set person to {name: "Ada", role: "admin"}
printline person.has("name")
person.remove("role")
printline person.keys()
true
Array [
"name"
]

Make an array of five numbers. Print the total, the biggest, and a list of only the ones above 10.

Next, you’ll learn to write your own reusable pieces.