code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(99 lines)

Reductions

In Tomo, reductions are a way to express the idea of folding or reducing a collection of values down to a single value. Reductions use a parenthesized infix operator followed by a colon, followed by a collection:

nums := [10, 20, 30]
sum := (+: nums)
assert sum == 60

Reductions return an optional value which will be a null value if the thing being iterated over has no values. In such cases, the reduction is undefined. As with all optionals, you can use either the postfix ! operator to perform a runtime check and error if there's a null value, or you can use or to provide a fallback value:

nums : [Int] = []
sum := (+: nums)

assert sum == none

assert sum or 0 == 0

nums = [10, 20]
assert (+: nums)! == 30

Reductions can be used as an alternative to generic functions like sum(), product(), any(), and all() in Python, or higher-order functions like foldl and foldr in functional programming:

# Sum:
assert (+: [10, 20, 30])! == 60

# Product:
assert (*: [2, 3, 4])! == 24

# Any:
assert (or: [no, yes, no])! == yes

# All:
assert (and: [no, yes, no])! == no

Minimum and Maximum

Reductions are especially useful for finding the minimum or maximum values in a collection using the _min_ and _max_ infix operators.

# Get the maximum value:
assert (_max_: [10, 30, 20])! == 30

# Get the minimum value:
assert (_min_: [10, 30, 20])! == 10

Reducers also support field and method call suffixes, which makes it very easy to compute the argmin/argmax (or keyed minimum/maximum) of a collection. This is when you want to get the minimum or maximum value according to some feature.

# Get the longest text:
assert (_max_.length: ["z", "aaaaa", "mmm"])! == "aaaaa"

# Get the number with the biggest absolute value:
assert (_max_.abs(): [1, -2, 3, -4])! == -4

You can also use suffixes on other operators:

texts := ["x", "y", "z"]
assert (==: texts) == no
assert (==.length: texts) == yes
assert (+.length: texts) == 3

nums := [1, 2, -3]
assert (+.abs(): nums) == 6

Comprehensions

Reductions work not only with iterable values (lists, sets, integers, etc.), but also with comprehensions. You can use comprehensions to perform reductions while filtering out values or while applying a transformation:

# Sum the lengths of these texts:
assert (+: t.length for t in ["a", "bc", "def"])! == 6

# Sum the primes between 1-100:
assert (+: i for i in 100 if i.is_prime())! == 1060
1 # Reductions
3 In Tomo, reductions are a way to express the idea of folding or reducing a
4 collection of values down to a single value. Reductions use a parenthesized
5 infix operator followed by a colon, followed by a collection:
7 ```tomo
8 nums := [10, 20, 30]
9 sum := (+: nums)
10 assert sum == 60
11 ```
13 Reductions return an optional value which will be a null value if the thing
14 being iterated over has no values. In such cases, the reduction is undefined.
15 As with all optionals, you can use either the postfix `!` operator to perform
16 a runtime check and error if there's a null value, or you can use `or` to
17 provide a fallback value:
19 ```tomo
20 nums : [Int] = []
21 sum := (+: nums)
23 assert sum == none
25 assert sum or 0 == 0
27 nums = [10, 20]
28 assert (+: nums)! == 30
29 ```
31 Reductions can be used as an alternative to generic functions like `sum()`,
32 `product()`, `any()`, and `all()` in Python, or higher-order functions like
33 `foldl` and `foldr` in functional programming:
35 ```tomo
36 # Sum:
37 assert (+: [10, 20, 30])! == 60
39 # Product:
40 assert (*: [2, 3, 4])! == 24
42 # Any:
43 assert (or: [no, yes, no])! == yes
45 # All:
46 assert (and: [no, yes, no])! == no
47 ```
49 ## Minimum and Maximum
51 Reductions are _especially_ useful for finding the minimum or maximum values in
52 a collection using the `_min_` and `_max_` infix operators.
54 ```tomo
55 # Get the maximum value:
56 assert (_max_: [10, 30, 20])! == 30
58 # Get the minimum value:
59 assert (_min_: [10, 30, 20])! == 10
60 ```
62 Reducers also support field and method call suffixes, which makes it very easy
63 to compute the argmin/argmax (or keyed minimum/maximum) of a collection. This
64 is when you want to get the minimum or maximum value _according to some
65 feature_.
67 ```tomo
68 # Get the longest text:
69 assert (_max_.length: ["z", "aaaaa", "mmm"])! == "aaaaa"
71 # Get the number with the biggest absolute value:
72 assert (_max_.abs(): [1, -2, 3, -4])! == -4
73 ```
75 You can also use suffixes on other operators:
77 ```tomo
78 texts := ["x", "y", "z"]
79 assert (==: texts) == no
80 assert (==.length: texts) == yes
81 assert (+.length: texts) == 3
83 nums := [1, 2, -3]
84 assert (+.abs(): nums) == 6
85 ```
87 ## Comprehensions
89 Reductions work not only with iterable values (lists, sets, integers, etc.),
90 but also with comprehensions. You can use comprehensions to perform reductions
91 while filtering out values or while applying a transformation:
93 ```tomo
94 # Sum the lengths of these texts:
95 assert (+: t.length for t in ["a", "bc", "def"])! == 6
97 # Sum the primes between 1-100:
98 assert (+: i for i in 100 if i.is_prime())! == 1060
99 ```