Re: Walking a list
- From: Pascal Bourguignon <pjb@xxxxxxxxxxxxxxxxx>
- Date: Wed, 27 Jun 2007 15:57:44 +0200
Dan Bensen <randomgeek@xxxxxxxxxxxxxx> writes:
The OP explicitly asked for the "Lisp way" of solving the problem,
which does require implicit pointers in the Lisp sense, and every
C programmer knows that multiple references can point to the same
memory location. So all the OP really needed to know was how to
do what they were describing.
Well, I hesitated to answer to the OP because he blatantly lied us,
since he mentionned singly and doubly linked lists, but the code he
showed cannot be list processing code in C (it could be in C++, but
he only mentionned C).
"Leslie P. Polzer" <leslie.polzer@xxxxxxx> wrote:
Suppose I want to keep track of the current element in a {singly,
doubly}-linked list (that might be circular) and at some point cleanly
advance it by one or more steps.
In C I'd do something like that:
list* p = LIST; /* let p initially point to the list head */
p++; /* might also be p += 5; */
/* assertion: p always points at the current element of the list */
And would walk it by just saying
while (p++); /* this obviously doesn't work out for circular lists,
but let's keep things simple */
What's the idiom for this stuff in Lisp? I'm sure there must be some
smug solution
that, as usual, eludes me. Thanks, folks.
Now, if we ignore almost totally the request of the OP, we could say
that one can easily walk a list in lisp. After all, LISP means LISt
Processing.
In the case of a simple singly-linked list:
(let ((p (list 1 2 3 4 5)))
(loop
:while p
:do (process (car p))
:do (pop p)))
or:
(let ((p (list 1 2 3 4 5)))
(loop
:for item :in p
:do (process item)))
or:
(let ((p (list 1 2 3 4 5)))
(dolist (item p)
(process item)))
or:
(map nil (function process) (list 1 2 3 4 5))
etc... There is no single idiom in lisp....
In the case of a circular singly-linked list:
(defun make-circular (list) (setf (cdr (last list)) list))
(let ((p (make-circular (list 1 2 3 4 5))))
(loop
:while (some-condition)
:do (process p)
:do (pop p)))
In the case of doubly-linked lists, it would depend on the data
structure used for them.
For example, with a non-circular dll:
(defstruct dll next previous item)
(defun dll-first (dll)
(loop
:until (null (dll-previous dll))
:do (setf dll (dll-first (dll-previous dll)))
:finally (return dll)))
(defun dll-list (&rest items)
(loop
:with dll = (make-dll)
:while items
:do (setf (dll-next dll) (make-dll :item (car items) :previous dll)
dll (dll-next dll))
:finally (return (dll-first dll))))
Then you can write:
(let ((p (dll-list 1 2 3 4 5)))
(loop
:while p
:do (process (dll-item p))
:do (setf p (dll-next p))))
or:
(let ((p (dll-list 1 2 3 4 5)))
(loop
:for cur = p :then (dll-next cur)
:do (process (dll-item cur))))
etc...
I still don't see the point of the OP's question...
On the other hand, in C I'd write something like:
{ dll* p=dll_list(5,1,2,3,4,5);
while(!dll_empty_p(p)){
process(dll_item(p));
p=dll_next(p); }}
so...
--
__Pascal Bourguignon__ http://www.informatimago.com/
NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
.
- Follow-Ups:
- Re: Walking a list
- From: Dan Bensen
- Re: Walking a list
- References:
- Walking a list
- From: Leslie P. Polzer
- Re: Walking a list
- From: Chris Russell
- Re: Walking a list
- From: Leslie P. Polzer
- Re: Walking a list
- From: Giorgos Keramidas
- Re: Walking a list
- From: Dan Bensen
- Walking a list
- Prev by Date: Re: Start of Web application tutorial with CLSQL, CL-WHO and HUNCHENTOOT - Anewbies wait untill few more additions are ready
- Next by Date: Re: fibonacci with ITERATE
- Previous by thread: Re: Walking a list
- Next by thread: Re: Walking a list
- Index(es):
Relevant Pages
|