3 Error Conditions

3.1 About error conditions

Sinceloop is a macro, it translates the form you supply into another form. Thus, any syntactic error messages occur during macro expansion rather than during evaluation or compilation. When the Loop Facility parses the given form, it expects clauses to have loop keywords and data supplied in specific orders. Unexpected symbols or data generate an error and an error message. The message explains what the Loop Facility did not understand and where the error occurred.

There are some common errors that occur when the Loop Facility is used, and many are easily corrected. This chapter discusses these errors, their causes, and possible solutions. Examples that would generate errors are also supplied.

Problem: The loop form is being translated into an infinite loop; it never returns.

Reason: You forgot to specify a loop termination clause, or you supplied a termination clause that is not being executed.

Example: Lacking proper termination conditions.

> (loop)                               ; This is an infinite loop.
> (loop for i from 1 count i)          ; This is an infinite loop.
> (loop for i = 1 then 2               ; This is a third infinite loop.
        while i
        collect i)
Solution: To correct this problem, either specify a termination clause or revise the iteration conditions so that termination is possible.

Problem: An unrecognized form is encountered where a loop keyword is expected.

Reason: The Loop Facility parses the form that you give it token by token. Each token is one of the items in the form. If the Loop Facility cannot recognize a token as a loop keyword when a loop keyword is expected, it generates an error and a message.

The most common reasons that a token cannot be recognized as a loop keyword are as follows:

> (loop untl (some-condition)           ; UNTIL is misspelled.
        do (print 'hi))
>>Error: Loop macro: Unrecognized form encountered where 
loop-keyword expected: (... UNTL (SOME-CONDITION) DO (PRINT (QUOTE HI)) )

> (loop for i from 1 to 10 od (print 'hi)) ; DO is misspelled. >>Error: Loop macro: Unrecognized form encountered where loop-keyword expected: (... OD (PRINT (QUOTE HI)) )

> (loop for i from 1 to 10
        (print 'hi))                    ; A DO construct is missing.
>>Error: Loop macro: Unrecognized form encountered where 
loop-keyword expected: (... (PRINT (QUOTE HI)) )

> (loop for i in '(1 2 a 3) unless (numberp i) (return i)) ; A DO construct is missing. >>Error: Loop macro: No loop clause after conditional expression: (... UNLESS (NUMBERP I) (RETURN I)

> (loop do (print 'hi)                  ; AND can only be used in 
        and                             ; UNLESS, IF, WHEN, and
        (print 'there))                 ; WITH constructs.
>>Error: Loop macro: A parallel AND clause is misplaced 
(... AND (PRINT (QUOTE THERE)))

Solution: In these examples, the error message displays the token that the Loop Facility does not understand. Use this token to determine the appropriate action to take.

Problem: An unknown loop keyword occurs in aFOR or anAS clause.

Reason: While parsing afor or anas clause, the Loop Facility found a keyword that it did not expect.

Example: The error message displays the token that the Loop Facility did not understand in the clause, along with some contextual tokens. The misunderstood token might be a misspelled loop keyword, or it might not be a keyword at all.

> (loop for i frum 1 to 10        ; The keyword FROM is misspelled.
        do (print 'hi))
>>Error: Loop macro: Random atom found where FOR (or AS) 
preposition expected: (... FOR I FRUM TO 10 DO (PRINT (QUOTE HI)))

Solution: To correct this problem, you must replace the unknown keyword with a legitimate one.

> (loop for i from 1 to 10           ; This is the correct form. 
        do (print 'hi))   

See Also: Section 2.2 on page 12 for more information aboutfor andas constructs.

Problem: A secondary clause is misplaced at the top level of a loop.

Reason: If the Loop Facility finds the loop keywordelse at the top level, it generates an error and a message.

Example: The loop keywordelse is used inif,when,unless, andwith constructs. An error results whenelse is misplaced in those constructs or when it is used inside other constructs.

> (loop else (print 'hi))
>>Error: Loop macro: Dangling ELSE clause: (... ELSE (PRINT (QUOTE HI)))

Solution: To correct this problem, you must make certain that theelse clause is a part of and in the correct location for the appropriate construct.

See Also: Section 2.6 on page 33 for more information about usingelse in conditional constructs.

Problem: An atom is encountered as part of aDO form.

Reason: Any number of Common Lisp list forms can follow the loop keyworddo, but atoms are not allowed. The Loop Facility generates an error if it finds an atomic form in ado clause.

Example: If you have intentionally included the atom in thedo clause, you are probably trying to prevent a Compiler warning for an unused local variable. Including an atom in thedo clause does not hide the unused variable from the Compiler; instead, it generates an error, as this example shows.

> (defun print-vars (var-list stuff info-list)
    (loop for var in var-list
          for info in info-list 
          do stuff
          (format t "~S: ~S~%" var info)))
>>Error: Loop macro: Atom encountered where DO forms were
expected: (... do STUFF (FORMAT T "~S: ~S%" VAR INFO) )

Solution: Theignore declaration used with the Common Lisp special formdeclare prevents a Compiler warning for the unused variablestuff.

> (defun print-vars (var-list stuff info-list)
    (declare (ignore stuff))
    (loop for var in var-list
          for info in info-list 
          do (format t "~S: ~S~%" var info)))

See Also: Section 2.7 on page 35 for more information about thedo construct.

Problem: A hanging conditional is found in a loop.

Reason: All conditional statements must have resulting clauses. When the Loop Facility parses anif orwhen construct, it expects a conditional form, the loop keywordthen, and a result form or forms.

Example: If the Loop Facility never finds the keywordthen, it generates an error and a message.

> (loop when (true-p))               ; This clause is incomplete.
>>Error: Loop macro: No loop clause after conditional expression:
            (... WHEN (TRUE-P) 

Solution: You must make certain that allif andwhen constructs have an appropriate resulting clause beginning withthen.

> (loop when (true-p) do (print 'hi)) ; This version is correct.
See Also: Section 2.6 on page 33 for more information aboutif andwhen.

Problem: AFOR,AS, orREPEAT iteration construct follows loop body code.

Reason: Since some iteration clauses appear in the loop prologue of the translated loop form, clauses that appear in the main body of a loop must follow these clauses. The constructsdo,thereis,always, and all accumulating clauses must followfor,as, andrepeat clauses.

Example: Thefor clause should appear before thedo clause; it should never follow ado clause.

> (loop do (print 'hi) for i from 1 to 10)
>>Error: Loop macro: FOR iteration must not follow body code: 
            (... (FOR I FROM 1) )

Solution: You must move the indicated iteration clause to the beginning of the loop form to correct this problem.

> (loop for i from 1 to 10 
        do (print 'hi)) 

Problem: AFOR,AS, orREPEAT iteration starts inside of a conditional construct.

Reason: Anyfor,as, orrepeat clause must be at the top level inside a loop. Though these clauses can be part of a conditional statement, they cannot be used insidewhen,if, orunless clauses.

Example: Thefor clause is used inside of awhen clause, and an error is signaled.

> (loop for x in mylist
        when x
        as y = (+ x 3)
        collect y)
>>Error: Loop macro: FOR iteration must not start inside of
conditional: (... (AS Y = (+ X 3)) COLLECT Y )

Solution: Conditional binding is not a by-product of conditional iteration. If you want a conditional binding, you must introduce two "loop constructs" as the following example shows.

> (setq mylist '(3 7 10 13 15 18 21))
(3 7 10 13 15 18 21)
> (loop for x in mylist
        as y = (and x (+ x 3))
        when x
        collect y)
(6 10 13 16 18 21 24)

Problem: An iteration variable is duplicated somewhere in a loop.

Reason: An iteration variable cannot be used more than once inside a loop if one interpretation of its value conflicts with another interpretation.

Example 1: The Loop Facility cannot determine what the starting value of the variable should be.

> (loop for i from 1 
        for i from 10)
>>Error: Loop macro: Duplicated variable: I

Example 2: The same variable is used as an iteration variable and to accumulate local values; both operations change the variable's value, and a conflict occurs.

> (loop with i for i from 1 to 10 
        collect a into i)
>>Error: Loop macro: Duplicated variable: I

Solution: To correct these types of problems, you must use unique variable names within a loop.

Problem: One variable is used as both an accumulation variable and as a value variable.

Reason: A conflict arises when the Loop Facility tries to collect values from and accumulate values into the same variable.

Example: The form that is being collected is the same form as the local variable into which the accumulation result is put.

> (loop collect i into i)	   
>>Error: Loop macro: 'collection' accumulate form is the same as 
         the collection variable: I

Solution: To correct this problem, you must use unique variable names within a loop.

> (loop collect i into j) 
See Also: Section 2.4 on page 24 for more information about accumulating values in a loop.

Problem: An undefined loop iteration method is used.

Reason: If you invoke an iteration method that is not defined by the name you have used, the Loop Facility cannot recognize it. The name might be misspelled or might not yet be defined.

Example: The loop methodthing is not defined.

> (loop for i being each thing in 'something)
>> Loop macro: Loop method not found: 
      (... I BEING EACH THING IN (QUOTE SOMETHING) )

Solution: If the method you are using is a predefined loop method, you must check its spelling. Otherwise, you must make certain that the loop method is defined in your environment.

See Also: Chapter 2, "User extension" for a discussion of user-defined iteration methods.

Problem: The construct used is meant to iterate over numbers, but no numbers are supplied.

Reason: This is a run-time error not generated by the Loop Facility. As the Loop Facility parsed a structure, a certain variable was expected to be of a certain type, and it was not.

Example: During execution of this example, the Loop Facility attempted to add the symbolsome-var to an existing numeric value. Butsome-var is not a number, so Lisp generates this error and a message.

> (loop for i in '(1 2 3 some-var) 
        sum i)
>>Error: The value of VAR, SOME-VAR, should be a NUMBER

Solution: When using value-accumulating constructs, you must make certain that the variables involved in the iteration have the appropriate data type.

See Also: Section 2.2 on page 12 for more information about thefor andas constructs; Section 2.4 on page 24 for more information about constructs that accumulate numeric values.

Problem: An invalid variable name is encountered by the Loop Facility.

Reason: When the Loop Facility parsed a structure, it expected to find a symbol in the given position to use as a local variable. Instead it found a numeric or string value.

Example: Thefor keyword should be followed by a variable, but2 is not a valid variable name.

> (loop for 2 to 10 do
        (print i))
>>Error: Loop macro: Encountered a random constant, 2, where a 
         variable name is expected: (... FOR (TO 10 DO (PRINT I)) 

Solution: To correct this problem, you must add a symbolic variable afterfor and restructure the clause appropriately.

> (loop for i from 2 to 10 
        do (print i)) 

Problem: The Loop Facility tried to initialize a list variable to a nonlist value.

Reason: When the Loop Facility parsed a structure, it found a list variable, but the corresponding value to be assigned was not a list.

Example: Since the Loop Facility cannot determine how to match the value to the list variable, it generates an error and a message. The error message displays the list variable and the value that flagged the error.

> (loop with (a b c) = 5 return 'done)
>>Error: Loop macro: Destructuring form (A B C) isn't congruent
         to constant value 5

Solution: When initializing a list variable to a value, you must make certain that the value is also a list.

Problem: A variable occurs more than once in a lambda list.

Reason: This is a run-time error not generated by the Loop Facility. The Loop Facility has locally declared thewith variables as specified.

Example: Lisp notices at run-time that a variable is repeated; thus, it generates an error.

> (loop with (a b a) 
        do (print a))
>>Error: Loop macro: Duplicated variable: A

Solution: To correct this problem, you must make certain that there are no duplicates in local declarations.

Problem: Function or method names are encountered that are obsolete in the Loop Facility.

Reason: The functionsdefine-loop-sequence-path anddefine-loop-path and the methodsinterned-symbols andlocal-interned-symbols are obsolete in the Loop Facility.

Solution: The following substitutions are valid in the Loop Facility:

See Also: Section 2.11 on page 64 for more information about obsolete names.


The Loop Facility - 9 SEP 1996

Generated with Harlequin WebMaker