Skip to content

The loop and more loops

The looping function that offers the most control in YS is called loop. It's also the most verbose.

There are lots of alternatives that are more specific and require less code, but they don't let you do everything, like decide when to stop.

We'll talk about both today.

The loop function🔗

I implied above that you could control when to stop the loop function.

It's kinda the other way around.

You control when to keep looping!

Loop has a matching recur "function" that you can call to keep looping. Otherwise it exits and returns the value that was evaluated.

And remember, loop is a function, so it always returns something.

The loop function takes a set of paired arguments where the first value is a variable name and the second value is its starting value.

The recur call, calls the loop function (tail) recursively with a new value for each variable.

Here's a simple example that finds the highest power of 2 less than a million:

$ ys -pe '
loop i 1:
  if i < 1000000:
    recur: i * 2
    else: i'
1048576

See how we used the if function to decide when to continue rather than when to stop? It's really the same question but it feels backwards.

More loops🔗

We've seen these before but the main ones are: map, for and reduce.

map is a list comprehension. That's useful for transforming the elements of a list. Let's double the numbers 0 through 9:

ys -pe '(1 .. 9).map(double)'
(1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0)

By "double" we don't mean "multiply by 2". We mean convert integers to floats (longs to doubles).

for is a loop that iterates over a list assigning each element to a variable. It processes the entire list before returning.

Let's use it to double (in the by 2 sense) the numbers 0 through 9:

$ ys -pe 'for i (1 .. 9): 2 * i'
(2 4 6 8 10 12 14 16 18)

OK, so I lied. The for function actually does give you some control. You can use :when to let it know which elements to process.

Let's double the numbers 0 through 9 that are even:

$ ys -pe 'for i (1 .. 100) :when (i < 10): 2 * i'
(2 4 6 8 10 12 14 16 18)

reduce takes each element of a list and uses them to calculate a single value.

It takes a function, a starting value (or accumulator), and a list to process.

Let's total the squares of 1 through 9 and add them to 100:

$ ys -e '
say:
  reduce _ 100 (1 .. 9):
    fn(total, n):
      total + n:sqr
'
385

Remember from before, the first argument to reduce is a function but in YS it's often nicer to put the big thing (the function) last, so we use the _ placeholder.

There are lots more specialized looping functions in YS like filter and remove (for finding or removing elements from a list), but those are the most common ones.

Comments