A tour of Vex
Each lesson adds one call to the chain of the lesson before it. Each example runs the real @mark1russell7/vex in your browser.
The examples read four boxes: A, B, C and D. Each box has a position, a size, a weight, a color and a name. Drag a box in any example: each example on the page evaluates again with the new position.
The root of each chain comes from these lines:
import { space, vex } from "@mark1russell7/vex";import { BoolDomain, ColorDomain, NumDomain, Vec2Domain } from "@mark1russell7/vex-domains";
const root = vex(Vec2Domain, NumDomain, BoolDomain, ColorDomain).over(space.record(boxes));1. Read a field
Section titled “1. Read a field”from("position") reads the field position of the record at the focus. At the start, the focus is the origin: the key where the evaluation starts. Select another origin to read the position of another box.
root.from("position")Result at A: (2, 2)
| origin | A | B | C | D |
|---|---|---|---|---|
| result | (2, 2) | (6, 5) | (13, 3) | (4, 11) |
2. Apply an op
Section titled “2. Apply an op”._ lists the ops of the domain of the current value. A bare string is a field at the focus, so add("size") adds the size of the same box. The result is the far corner of the box.
root.from("position")._.add("size")Result at A: (7, 6)
| origin | A | B | C | D |
|---|---|---|---|---|
| result | (7, 6) | (10, 9) | (16, 9) | (11, 13) |
3. Read at another key
Section titled “3. Read at another key”root.of("B", "position") reads a field at the key B, from each origin. It is like an absolute reference in a spreadsheet. At the origin B, the result is the size of B.
root.from("position")._.add("size")
._.subtract(root.of("B", "position"))Result at A: (1, 1)
| origin | A | B | C | D |
|---|---|---|---|---|
| result | (1, 1) | (4, 4) | (10, 4) | (5, 8) |
4. Change the value kind
Section titled “4. Change the value kind”length() gives a number. After it, the chain has no Vec2 ops: the type of the chain follows the value. The Num domain gives the ops of numbers.
root.from("position")._.add("size")
._.subtract(root.of("B", "position"))
._.length()Result at A: 1.41
| origin | A | B | C | D |
|---|---|---|---|---|
| result | 1.41 | 5.66 | 10.77 | 9.43 |
5. Move the focus
Section titled “5. Move the focus”to("C") moves the focus for the field names after it. The first position reads at the origin, and the second position reads at C. The result is the distance from each box to C.
root.from("position").to("C")._.subtract("position")._.length()Result at A: 11.05
| origin | A | B | C | D |
|---|---|---|---|---|
| result | 11.05 | 7.28 | 0 | 12.04 |
6. An axis
Section titled “6. An axis”others(body) evaluates the body at each key except the focus. The body starts with the current value from the origin, and its field names read at each target. The result is a list with one item for each other box.
root.from("position")
.others((e) => e._.subtract("position")._.length())
.values()Result at A: [5, 11.05, 9.22]
| origin | A | B | C | D |
|---|---|---|---|---|
| result | [5, 11.05, 9.22] | [5, 7.28, 6.32] | [11.05, 7.28, 12.04] | [9.22, 6.32, 12.04] |
7. Reduce the list
Section titled “7. Reduce the list”min() gives the smallest value of the list. The other reductions are max, sum, mean, count, any, all, none, first, values and reduce(op). By default, a reduction skips error items. With { strict: true }, the first error item is the result.
root.from("position")
.others((e) => e._.subtract("position")._.length())
.min()Result at A: 5
| origin | A | B | C | D |
|---|---|---|---|---|
| result | 5 | 5 | 7.28 | 6.32 |
8. Catch an error value
Section titled “8. Catch an error value”Vex does not throw. A division by the vector (0, 0) gives the error #NUM!. ifError gives a fallback when the chain gives an error, like IFERROR in a spreadsheet. Move the slider to see the error, and then the fallback.
root.from("position")._.divide(0).ifError(root.from("position"))Result at A: (2, 2)
| origin | A | B | C | D |
|---|---|---|---|---|
| result | (2, 2) | (6, 5) | (13, 3) | (4, 11) |
- The concepts explain spaces, addresses, axes and domains.
- The Lab lets you build a chain from chips and change its JSON.
- Why none? explains each error code.