Chapter 10. Looping with the loop Command

The loop and format commands are powerful and hacker-friendly. Though most of the functionality they offer is available elsewhere in the Lisp language, these highly specialized commands are worth learning if you like terse code. We’ll look at loop in this chapter. The next chapter covers format.

The loop Macro

Any type of looping you would ever want to do inside a computer program can be accomplished with the loop macro. Here’s a simple example:

> (loop for i
        below 5
        sum i)
10

This code adds together the natural numbers below 5, like this:

0 + 1 + 2 + 3 + 4 = 10

You can see that this loop command doesn’t work in the way a proper Lisp command should. First of all, it’s parenthetically challenged. Never before have we had seven tokens in a row without parentheses!

image with no caption

What makes it even less Lispy is that some of these extra tokens (for, below, and sum) appear to have special meanings. Recall from Chapter 3 that the first token in a form (the one immediately after the opening parenthesis) is typically what decides the basic behavior of the code, while the rest of the form contains parameters. Within the loop macro, several of these “magic tokens” fundamentally affect the loop’s behavior. Here’s what they mean:

  • for allows you to declare a variable (in this case, named i) that iterates through a range of values. By default, it will count through the integers starting at zero.

  • below tells the for construct to halt when it reaches the specified value (in this case, 5), excluding the value itself.

  • sum adds together all values of a given expression (in this case, the expression is just i) and makes the loop return that number.

Some loop Tricks

The loop macro has a veritable cornucopia of special tokens that make just about any kind of behavior possible. Let’s look at some of the possibilities.

Counting from a Starting Point to an Ending Point

By using from and to clauses, you can make the for construct count through any specific range of integers:

> (loop for i
        from 5
        to 10
      sum i)
45

Iterating Through Values in a List

In the following example, we iterate through values in a list using the in token:

> (loop for i
        in '(100 20 3)
      sum i)
123

doing Stuff in a Loop

The do token takes an arbitrary expression and executes it inside the loop:

> (loop for i
        below 5
      do (print i))
0
1
2
3
4

Doing Stuff Under Certain Conditions

The when token lets you run the following part of the loop only as needed:

> (loop for i
        below 10
      when (oddp i)
      sum i)
25

Notice that only the sum of the odd numbers is returned.

Breaking out of a Loop Early

The following loop uses several new tricks:

image with no caption
> (loop for i
        from 0
      do (print i)
      when (= i 5)
      return 'falafel)
0
1
2
3
4
5

FALAFEL

Notice that there’s nothing in the for part of the loop that tells it to stop counting numbers—it goes from zero off to infinity. However, once we reach 5, the when clause triggers the loop to immediately return the value 'falafel.

Collecting a List of Values

image with no caption

The collect clause lets you return more than one item from the loop, in the form of a list. This command is useful when you need to modify each item in a list, as in the following example:

> (loop for i
     in '(2 3 4 5 6)
     collect (* i i))
(4 9 16 25 36)

Using Multiple for Clauses

image with no caption

It’s possible for a loop macro to have more than one for clause. Consider the following example:

(loop for x below 10
      for y below 10
      collect (+ x y))

How many numbers do you think will be returned as a result? There are two possibilities: Either it increments x and y at the same time and returns a list of 10 items, or it iterates x and y in a nested fashion and returns 100 numbers. The answer is the former:

> (loop for x below 10
        for y below 10
        collect (+ x y))
(0 2 4 6 8 10 12 14 16 18)

As you can see, both numbers incremented at the same time between 0 and 9.

If there are multiple for clauses in a Common Lisp loop, each one will be checked, and the loop will stop when any one of the clauses runs out of values. This means that for clauses do not loop independently across multiple looping variables, so if you loop on two ranges of 10 values each, it will still just loop 10 times.

However, sometimes you want to generate the Cartesian product between multiple ranges. In other words, you want a loop to run once for every possible combination of two or more ranges. To accomplish this, you need to use nested loops for x and y:

> (loop for x below 10
        collect (loop for y below 10
                      collect (+ x y)))
((0 1 2 3 4 5 6 7 8 9) (1 2 3 4 5 6 7 8 9 10) (2 3 4 5 6 7 8 9 10 11)
 (3 4 5 6 7 8 9 10 11 12) (4 5 6 7 8 9 10 11 12 13) (5 6 7 8 9 10 11 12 13 14)
 (6 7 8 9 10 11 12 13 14 15) (7 8 9 10 11 12 13 14 15 16)
 (8 9 10 11 12 13 14 15 16 17) (9 10 11 12 13 14 15 16 17 18))

In this case, we’ve created 10 lists of 10 items each, looping for a total of 100 items.

Also, notice that using a for variable starting at zero, such as the i variable in the following example, provides a clean way to track the index number of items in a list:

> (loop for i
        from 0
        for day
        in '(monday tuesday wednesday thursday friday saturday sunday)
        collect (cons i day))
((0 . MONDAY) (1 . TUESDAY) (2 . WEDNESDAY)
 (3 . THURSDAY) (4 . FRIDAY) (5 . SATURDAY) (6 . SUNDAY))

You might think we’ve covered every conceivable variation of looping at this point. If so, you are gravely mistaken. Behold! The Periodic Table of the Loop Macro!

image with no caption
image with no caption

Everything You Ever Wanted to Know About loop

The individual examples we’ve discussed so far give only the briefest hint of the full capabilities of loop. But fear not! You now have the world’s first and only Periodic Table of the Loop Macro. Just tape it to your monitor, glue it to your wallet, or laser-etch it directly into your retina, and you’ll be guaranteed to reach loop proficiency in no time!

Almost every legal command that can be used in a loop macro is covered by the periodic table. It shows how to manipulate hash tables and arrays, and perform special looping operations. Each square in the periodic table contains an example. If you run the example, you should be able to figure out the behavior of the given command.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.151.164