aboutsummaryrefslogtreecommitdiff
path: root/docs/reductions.md
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-02 20:22:19 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-11-02 20:22:19 -0400
commit0b7a0dd043a4c7ccfc924d618508d1edc0115e2f (patch)
tree6e1942840ab7e1e10bed111d8d5a012eacdf8b9b /docs/reductions.md
parent985011aed89706e9a4b06e6c6f3239d53ac8e6e8 (diff)
Change reducers to use (OP: ...) syntax and return an optional value
Diffstat (limited to 'docs/reductions.md')
-rw-r--r--docs/reductions.md81
1 files changed, 35 insertions, 46 deletions
diff --git a/docs/reductions.md b/docs/reductions.md
index 143a59ad..b4e78624 100644
--- a/docs/reductions.md
+++ b/docs/reductions.md
@@ -1,14 +1,35 @@
# 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 an infix operator
-surrounded by parentheses, followed by a collection:
+collection of values down to a single value. Reductions use a parenthesized
+infix operator followed by a colon, followed by a collection:
```tomo
nums := [10, 20, 30]
-sum := (+) nums
+sum := (+: nums)
>> sum
-= 60
+= 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:
+
+```tomo
+nums := [:Int]
+sum := (+: nums)
+
+>> sum
+= !Int
+
+>> sum or 0
+= 0
+
+>> nums = [10, 20]
+>> (+: nums)!
+= 30
```
Reductions can be used as an alternative to generic functions like `sum()`,
@@ -17,19 +38,19 @@ Reductions can be used as an alternative to generic functions like `sum()`,
```tomo
# Sum:
->> (+) [10, 20, 30]
+>> (+: [10, 20, 30])!
= 60
# Product:
->> (*) [2, 3, 4]
+>> (*: [2, 3, 4])!
= 24
# Any:
->> (or) [no, yes, no]
+>> (or: [no, yes, no])!
= yes
# All:
->> (and) [no, yes, no]
+>> (and: [no, yes, no])!
= no
```
@@ -40,11 +61,11 @@ a collection using the `_min_` and `_max_` infix operators.
```tomo
# Get the maximum value:
->> (_max_) [10, 30, 20]
+>> (_max_: [10, 30, 20])!
= 30
# Get the minimum value:
->> (_min_) [10, 30, 20]
+>> (_min_: [10, 30, 20])!
= 10
```
@@ -55,11 +76,11 @@ maximum value _according to some feature_.
```tomo
# Get the longest text:
->> (_max_.length) ["z", "aaaaa", "mmm"]
+>> (_max_.length: ["z", "aaaaa", "mmm"])!
= "aaaaa"
# Get the number with the biggest absolute value:
->> (_max_:abs()) [1, -2, 3, -4]
+>> (_max_:abs(): [1, -2, 3, -4])!
= -4
```
@@ -71,42 +92,10 @@ while filtering out values or while applying a transformation:
```tomo
# Sum the lengths of these texts:
->> (+) t.length for t in ["a", "bc", "def"]
+>> (+: t.length for t in ["a", "bc", "def"])!
= 6
# Sum the primes between 1-100:
->> (+) i for i in 100 if i:is_prime()
+>> (+: i for i in 100 if i:is_prime())!
= 1060
```
-
-## Empty Collection Behavior
-
-If a collection has no members, the default behavior for a reduction is to
-create a runtime error and halt the program with an informative error message.
-If you instead want to provide a default fallback value, you can use `else:` to
-give one:
-
-```tomo
-empty := [:Int]
->> (+) empty else: -1
-= -1
-
->> (+) empty
-# Error: empty iterable!
-```
-
-You can also provide your own call to `fail()` or `exit()` with a custom error
-message, or a short-circuiting control flow statement (`return`, `stop`,
-`skip`) like this:
-
-```tomo
->> (_max_) things else: exit("No things!")
-
-for nums in num_arrays:
- product := (*) nums else: skip
- do_thing(product)
-
-func remove_best(things:[Thing]):
- best := (_max_.score) things else: return
- best:remove()
-```