Mythul
Mythul

Reputation: 1807

How does Lisp "prog" work in this example?

I'm a beginner in lisp and I need somebody to explain to me how the prog form works, step by step. What is the initial value of l1 ? Nil ?

The problem outputs T if the list has an even number of elements on the first level, nil if not.

(defun nr_par (l)
  (prog ((l1 l))
    ciclu
    (cond
      ((null l1) (return T))
      ((null (cdr l1)) (return NIL))
      ((null (cddr l1)) (return T))
      (T (setf l1 (cddr l1))
         (go ciclu)))))

On console:

(nr_par '(1 2 3 4 5 6 7 8))

T

Upvotes: 1

Views: 3635

Answers (3)

Will Ness
Will Ness

Reputation: 71119

As the CLHS page for prog says, it does three things: lets you have local vars and initialize them; lets you have tags as in tagbody and use go; and lets you use return as inside a block named NIL:

(defun nr_par (l)                     
  (prog ((l1 l))                           ; local binding(s)
    ciclu                             
    (if (null l1)       (return T))        ; return
    (if (null (cdr l1)) (return NIL)) 
    (setf l1 (cddr l1))  
    (go ciclu)))                           ; go

(defun nr_par1 (l)                         ; directly equivalent
  (labels ((ciclu (l1) 
             (if (null l1)       (return-from ciclu T)) 
             (if (null (cdr l1)) (return-from ciclu NIL)) 
             (ciclu (cddr l1))))
    (ciclu l)))

(defun nr_par2 (l)                         ; also equivalent
  (do ((l1 l (cddr l1)))
      (NIL)                                ; while T ...
    (cond
      ((null l1)       (return T))
      ((null (cdr l1)) (return NIL)))))

Function call is a glorified goto after all, isn't it?

See also Longest decreasing sequence in Lisp for an example representing several mutually-recursive functions hand-compiled into a prog with a bunch of GO statements.

Upvotes: 1

Diego Sevilla
Diego Sevilla

Reputation: 29019

The program is straightforward, but not very idiomatic lisp (it is rather imperative instead of functional). Step by step goes as follows.

prog uses a series of variable bindings, in this case, l1 is assigned the value of l initially. Then, a series of statements in which a loop starts (again, not very lisp idiomatic).

This type of loops use a tag (ciclu) and a goto instruction (go), again, not recommended, but it is there. After that, the cond checks a series of cases. When the list is empty (null), you return true, in other cases, you check if the length is even or odd, and return the value in consequence.

In the case that the list is longer than one or two elements (neither of the cases is null), the l1 list is adjusted to point to the next of the next element of itself (the cddr function).

Finally, the go function turns the program back to the ciclu tag.

The program will finish when any of the cond clauses is met, returning either T or NIL.

Upvotes: 6

Anton Kovalenko
Anton Kovalenko

Reputation: 21517

See PROG in CLHS: L1 is var, L is init-form, so the initial value of L1 is the value of L.

Upvotes: 2

Related Questions