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.