Reputation: 1807
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
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
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
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