# Looping

A very common and essential operation in all programming is looping. Most languages support looping of some kind, either with explicit loops or recursion. Janet supports both recursion and a primitive `while` loop. While recursion is useful in many cases, sometimes it is more convenient to use an explicit loop to iterate over a collection like an array.

## Example 1: Iterating a range

Suppose you want to calculate the sum of the first 10 natural numbers 0 through 9. There are many ways to carry out this explicit calculation. A succinct way in Janet is:

``(+ ;(range 10))``

We will limit ourselves however to using explicit looping and no functions like `(range n)` which generate a list of natural numbers for us.

For our first version, we will use only the `while` form to iterate, similar to how one might sum natural numbers in a language such as C.

``````(var sum 0)
(var i 0)
(while (< i 10)
(+= sum i)
(++ i))
(print sum) # prints 45``````

This is a very imperative program, and it is not the best way to write this in Janet. We are manually updating a counter `i` in a loop. Using the macros `+=` and `++`, this style code is similar in density to C code. It is recommended to instead use either macros (such as the `loop` or `for` macros) or a functional style in Janet.

Since this is such a common pattern, Janet has a macro for this exact purpose. The `(for x start end body)` form captures this behavior of incrementing a counter in a loop.

``````(var sum 0)
(for i 0 10 (+= sum i))
(print sum) # prints 45``````

We have completely wrapped the imperative counter in a macro. The `for` macro, while not very flexible, is very terse and covers a common case of iteration: iterating over an integer range. The `for` macro will be expanded to something very similar to our original version with a `while` loop.

We can do something similar with the more flexible `loop` macro.

``````(var sum 0)
(loop [i :range [0 10]] (+= sum i))
(print sum) # prints 45``````

This is slightly more verbose than the `for` macro, but can be more easily extended. Let's say that we wanted to only count even numbers towards the sum. We can do this easily with the `loop` macro.

``````(var sum 0)
(loop [i :range [0 10] :when (even? i)] (+= sum i))
(print sum) # prints 20``````

The `loop` macro has several verbs (`:range`) and modifiers (`:when`) that let the programmer more easily generate common looping idioms. The `loop` macro is similar to the Common Lips `loop` macro, but smaller in scope and with a much simpler syntax. As with the `for` macro, the `loop` macro expands to similar code as our original `while` expression.

## Example 2: Iterating over an indexed data structure

Another common usage for iteration in any language is iterating over the items in a data structure, like items in an array, characters in a string, or key-value pairs in a table.

Say we have an array of names that we want to print out. We will again start with a simple `while` loop which we will refine into more idiomatic expressions.

First, we will define our array of names:

``````(def names
@["Jean-Paul Sartre"
"Bob Dylan"
"Frida Kahlo"
"Harriet Tubman"])``````

With our array of names, we can use a `while` loop to iterate through the indices of names, get the values, and then print them.

``````(var i 0)
(def len (length names))
(while (< i len)
(print (get names i))
(++ i))``````

This is rather verbose. Janet provides the `each` macro for iterating through the items in a tuple or array, or the bytes in a buffer, symbol, or string.

``(each name names (print name))``

We can also use the `loop` macro for this case as well using the `:in` verb.

``(loop [name :in names] (print name))``

Lastly, we can use the `map` function to apply a function over each value in the array.

``(map print names)``

The `each` macro is actually more flexible than the normal loop, as it is able to iterate over data structures that are not like arrays. For example, `each` will iterate over the values in a table.

## Example 3: Iterating a dictionary

In the previous example, we iterated over the values in an array. Another common use of looping in a Janet program is iterating over the keys or values in a table. We cannot use the same method as iterating over an array because a table or struct does not contain a known integer range of keys. Instead we rely on a function `next`, which allows us to visit each of the keys in a struct or table. Note that iterating over a table will not visit the prototype table.

As an example, let's iterate over a table of letters to a word that starts with that letter. We will print out the words to our simple children's book.

``````(def alphabook
@{"A" "Apple"
"B" "Banana"
"C" "Cat"
"D" "Dog"
"E" "Elephant"})``````

As before, we can evaluate this loop using only a `while` loop and the `next` function. The `next` function is the primary way to iterate in Janet, and is overloaded to support all iterable types. Given a data structure and a key, it returns the next key in the data structure. If there are no more keys left, it returns `nil`.

``````(var key (next alphabook nil))
(while (not= nil key)
(print key " is for " (get alphabook key))
(set key (next alphabook key)))``````

However, we can do better than this with the `loop` macro using the `:pairs` or `:keys` verbs.

``````(loop [[letter word] :pairs alphabook]
(print letter " is for " word))``````

Using the `:keys` verb and shorthand notation for indexing a data structure:

``````(loop [letter :keys alphabook]
(print letter " is for " (alphabook letter)))``````

As an alternative to the `loop` macro here, we can also use the macros `eachk` and `eachp`, which behave like `each` but `loop` over the keys of a data structure and the key-value pairs in a data structure respectively.

Data structures like tables and structs can be called like functions that look up their arguments. This allows for writing shorter code than what is possible with `(get alphabook letter)`.

We can also use the core library functions `keys` and `pairs` to get arrays of the keys and pairs respectively of the alphabook.

``````(loop [[letter word] :in (pairs alphabook)]
(print letter " is for " word))

(loop [letter :in (keys alphabook)]
(print letter " is for " (alphabook letter)))``````

Notice that iteration through the table is in no particular order. Iterating the keys of a table or struct guarantees no order. If you want to iterate in a specific order, use a different data structure or the `(sort indexed)` function.