|
| 1 | +--- |
| 2 | +title: The loop and more loops |
| 3 | +date: 2025-07-31 |
| 4 | +draft: false |
| 5 | +authors: [ingydotnet] |
| 6 | +categories: [Summer-of-YS] |
| 7 | +edit: blog/2025-07-31.md |
| 8 | +comments: true |
| 9 | +--- |
| 10 | + |
| 11 | + |
| 12 | +The looping function that offers the most control in YS is called `loop`. |
| 13 | +It's also the most verbose. |
| 14 | + |
| 15 | +There are lots of alternatives that are more specific and require less code, but |
| 16 | +they don't let you do everything, like decide when to stop. |
| 17 | + |
| 18 | +We'll talk about both today. |
| 19 | + |
| 20 | +<!-- more --> |
| 21 | + |
| 22 | + |
| 23 | +## The `loop` function |
| 24 | + |
| 25 | +I implied above that you could control when to stop the `loop` function. |
| 26 | + |
| 27 | +It's kinda the other way around. |
| 28 | + |
| 29 | +You control when to keep looping! |
| 30 | + |
| 31 | +Loop has a matching `recur` "function" that you can call to keep looping. |
| 32 | +Otherwise it exits and returns the value that was evaluated. |
| 33 | + |
| 34 | +And remember, `loop` is a function, so it always returns something. |
| 35 | + |
| 36 | +The `loop` function takes a set of paired arguments where the first value is a |
| 37 | +variable name and the second value is its starting value. |
| 38 | + |
| 39 | +The `recur` call, calls the `loop` function (tail) recursively with a new value |
| 40 | +for each variable. |
| 41 | + |
| 42 | +Here's a simple example that finds the highest power of 2 less than a million: |
| 43 | + |
| 44 | +```bash |
| 45 | +$ ys -pe ' |
| 46 | +loop i 1: |
| 47 | + if i < 1000000: |
| 48 | + recur: i * 2 |
| 49 | + else: i' |
| 50 | +1048576 |
| 51 | +``` |
| 52 | + |
| 53 | +See how we used the `if` function to decide when to continue rather than when to |
| 54 | +stop? |
| 55 | +It's really the same question but it feels backwards. |
| 56 | + |
| 57 | + |
| 58 | +## More loops |
| 59 | + |
| 60 | +We've seen these before but the main ones are: `map`, `for` and `reduce`. |
| 61 | + |
| 62 | +`map` is a list comprehension. |
| 63 | +That's useful for transforming the elements of a list. |
| 64 | +Let's double the numbers 0 through 9: |
| 65 | + |
| 66 | +```bash |
| 67 | +ys -pe '(1 .. 9).map(double)' |
| 68 | +(1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0) |
| 69 | +``` |
| 70 | + |
| 71 | +By "double" we don't mean "multiply by 2". |
| 72 | +We mean convert integers to floats (longs to doubles). |
| 73 | + |
| 74 | +`for` is a loop that iterates over a list assigning each element to a variable. |
| 75 | +It processes the entire list before returning. |
| 76 | + |
| 77 | +Let's use it to double (in the by 2 sense) the numbers 0 through 9: |
| 78 | + |
| 79 | +```bash |
| 80 | +$ ys -pe 'for i (1 .. 9): 2 * i' |
| 81 | +(2 4 6 8 10 12 14 16 18) |
| 82 | +``` |
| 83 | + |
| 84 | +OK, so I lied. |
| 85 | +The `for` function actually does give you some control. |
| 86 | +You can use `:when` to let it know which elements to process. |
| 87 | + |
| 88 | +Let's double the numbers 0 through 9 that are even: |
| 89 | + |
| 90 | +```bash |
| 91 | +$ ys -pe 'for i (1 .. 100) :when (i < 10): 2 * i' |
| 92 | +(2 4 6 8 10 12 14 16 18) |
| 93 | +``` |
| 94 | + |
| 95 | + |
| 96 | +`reduce` takes each element of a list and uses them to calculate a single value. |
| 97 | + |
| 98 | +It takes a function, a starting value (or accumulator), and a list to process. |
| 99 | + |
| 100 | +Let's total the squares of 1 through 9 and add them to 100: |
| 101 | + |
| 102 | +```bash |
| 103 | +$ ys -e ' |
| 104 | +say: |
| 105 | + reduce _ 100 (1 .. 9): |
| 106 | + fn(total, n): |
| 107 | + total + n:sqr |
| 108 | +' |
| 109 | +385 |
| 110 | +``` |
| 111 | + |
| 112 | +Remember from before, the first argument to `reduce` is a function but in YS |
| 113 | +it's often nicer to put the big thing (the function) last, so we use the `_` |
| 114 | +placeholder. |
| 115 | + |
| 116 | +There are lots more specialized looping functions in YS like `filter` and |
| 117 | +`remove` (for finding or removing elements from a list), but those are the most |
| 118 | +common ones. |
0 commit comments