undefined variable: COMMON-LISP:PROGN when running DO

64 views Asked by At

Using SBCL (2.4.1) on Mac (MacOS Sonoma 14.2.1), I have the following function:

    (defun getEndLoop(n)
        (let ((lpCntThrshld 8192)) ; To be safe and avoid any possible infinite loop.
            (do ((count 0 (+ count 1)) (token n (collatzNext token PrimeList))
                 ; tail implements a mechanism to detect loops in the flow of values.
                 (tail n (if (and (eq stage 0) (eq (mod count 2) 1))
                            (collatzNext tail PrimeList) tail))
                     (stage 0 (if (and (> count 0) (eql token tail)) 1 stage)))

                (progn
                    (if (> count lpCntThrshld) (return-from getEndLoop (list -1 fnID n)))

                    (if (eq stage 1) ;(and (> count 0) (eql token tail))
                                    (progn
                                        (format t "stage=~a" stage)
                                        (return-from getEndLoop NIL)
                                    )
                            ))
            ) ; End do.
        ) ; End getEndLoop-let.
    ) ; End getEndLoop.

When I want to run the program containing this function, I see the following message:

    ; caught WARNING:
    ;   undefined variable: COMMON-LISP:PROGN
    ; 
    ; compilation unit finished
    ;   Undefined variable:
    ;     PROGN
    ;   caught 1 WARNING condition
    Unhandled UNBOUND-VARIABLE in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                    {7005550003}>:
      The variable PROGN is unbound.

What is wrong with my using progn? Or am I using in some wrong environment?

I have been using it a lot in other programs (GNU clisp) and I use it in other parts of this program too, with no issue at all.

Can someone spot where I am making a mistake?

1

There are 1 answers

0
Ehvince On

rajashekar is spot on. To illustrate:

(defun getEndLoop(n)
  (let ((lpCntThrshld 8192)) 
    (do ((count 0 (+ count 1))
         (token n (collatzNext token PrimeList))
         (tail n (if (and (eq stage 0) (eq (mod count 2) 1))
                     (collatzNext tail PrimeList) tail))
         (stage 0 (if (and (> count 0) (eql token tail)) 1 stage))) ;; <-- end of loop variable definitions

        ;; now DO expects the end test form
        ;; If you don't want one it can be
        ;; (nil)

        ;; but you give what you think is the body
        (progn

so for example:

    (do ((count 0 (+ count 1))
         (token n (collatzNext token PrimeList))
         (tail n (if (and (eq stage 0) (eq (mod count 2) 1))
                     (collatzNext tail PrimeList) tail))
         (stage 0 (if (and (> count 0) (eql token tail)) 1 stage)))

        ;; end test form
        ((> count lpCntThrshld)
         (list -1 fnID n))

        (progn
           ;; etc

but the body is written in an implicit progn so you don't need to write it. And consequently, we see better the DO structure with the indentation:

    (do ((count 0 (+ count 1))
         (token n (collatzNext token PrimeList))
         (tail n (if (and (eq stage 0) (eq (mod count 2) 1))
                     (collatzNext tail PrimeList) tail))
         (stage 0 (if (and (> count 0) (eql token tail)) 1 stage)))

        ;; end test form
        ((> count lpCntThrshld)
         (list -1 fnID n))

      (do-something)
      (do-something-else))    

In general, when I see a surprising message like

undefined variable: COMMON-LISP:PROGN

it's a clue I got the parenthesis wrong, I have a bad syntax structure, or I got an indentation wrong.


You have a couple if with no else branch, they should be when.