Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

very newbie

32 views
Skip to first unread message

Markanoid

unread,
Oct 12, 2004, 11:01:51 AM10/12/04
to
I must do a circular list. (it is a normal list?)

i create the list
(setq lista '(1 2 3 4 5))

then define a function to add something
(defun aggiungi (x L)

( setq L (cons x L)))

but when i call
(aggiungi 10 lista)

the result is
(10 1 2 3 4 5)

it' s ok but the nexxt time i will aspect
(10 10 1 2 3 4 5)

BUT the result is always
(10 1 2 3 4 5)
for every time i call.
I do not understand why.. ( setq L (cons x L))) line doesn' t save my
new variable... ?

tnk fr help, bye

Frank Buss

unread,
Oct 12, 2004, 12:20:25 PM10/12/04
to
Markanoid <x...@ngi.it> wrote:

> I must do a circular list. (it is a normal list?)

no, a circular list is a list where the last cdr points to the first
cons:

http://groups.google.de/groups?threadm=uwGc9O%23f9GA.330%40nih2naac.prod2.compuserve.com

> i create the list
> (setq lista '(1 2 3 4 5))

you should not use setq for declaring or changing new variables at
top-level:

http://groups.google.de/groups?selm=_badnZ8rXbR-G0rd4p2dnA%40speakeasy.net

> then define a function to add something
> (defun aggiungi (x L)
>
> ( setq L (cons x L)))

you should read the article about variables in the nice book from Peter
Seibel and try to understand what "lexical binding" means:

http://www.gigamonkeys.com/book/variables.html

BTW: The "push" macro implements what you want with your
function aggiungi:

CL-USER 1 > (defparameter *lista* '(1 2 3 4 5))
*LISTA*

CL-USER 2 > (push 10 *lista*)


(10 1 2 3 4 5)

CL-USER 3 > (push 20 *lista*)
(20 10 1 2 3 4 5)

CL-USER 4 > *lista*
(20 10 1 2 3 4 5)

--
Frank Buß, f...@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de

Pascal Bourguignon

unread,
Oct 12, 2004, 12:54:38 PM10/12/04
to
Markanoid <x...@ngi.it> writes:

> I must do a circular list. (it is a normal list?)
>
> i create the list
> (setq lista '(1 2 3 4 5))
>
> then define a function to add something
> (defun aggiungi (x L)
>
> ( setq L (cons x L)))
>
> but when i call
> (aggiungi 10 lista)
>
> the result is
> (10 1 2 3 4 5)

That's because Lisp does not call by reference, it calls by value, like C!

So when you pass lista to aggiungi, L gets the value of lista, ie (1
2 3 4 5), and knows nothing about lista.

It happens that setq returns the last value assigned so you get the
right result, but you did not change lista!

Forget about setting in a _function_. Use a functional style:

(defun aggiungi (x l)
(cons x l))

(defparameter lista '(1 2 3 4 5))
(setf lista (aggiungi 10 lista))
(setf lista (aggiungi 11 lista))


> it' s ok but the nexxt time i will aspect
> (10 10 1 2 3 4 5)
>
> BUT the result is always
> (10 1 2 3 4 5)
> for every time i call.
> I do not understand why.. ( setq L (cons x L))) line doesn' t save my
> new variable... ?
>
> tnk fr help, bye

--
__Pascal Bourguignon__ http://www.informatimago.com/

Voting Democrat or Republican is like choosing a cabin in the Titanic.

Svein Ove Aas

unread,
Oct 12, 2004, 1:47:31 PM10/12/04
to
Frank Buss wrote:

> BTW: The "push" macro implements what you want with your
> function aggiungi:
>
> CL-USER 1 > (defparameter *lista* '(1 2 3 4 5))
> *LISTA*
>
> CL-USER 2 > (push 10 *lista*)
> (10 1 2 3 4 5)
>
> CL-USER 3 > (push 20 *lista*)
> (20 10 1 2 3 4 5)
>
> CL-USER 4 > *lista*
> (20 10 1 2 3 4 5)
>

Note that this only works because push is a macro, and can't be implemented
as a function. The push macro expands to (setf *lista* (cons 10 lista)).

Svein Ove Aas

unread,
Oct 12, 2004, 1:44:49 PM10/12/04
to
Pascal Bourguignon wrote:

> Markanoid <x...@ngi.it> writes:
>
>> I must do a circular list. (it is a normal list?)
>>
>> i create the list
>> (setq lista '(1 2 3 4 5))
>>
>> then define a function to add something
>> (defun aggiungi (x L)
>>
>> ( setq L (cons x L)))
>>
>> but when i call
>> (aggiungi 10 lista)
>>
>> the result is
>> (10 1 2 3 4 5)
>
> That's because Lisp does not call by reference, it calls by value, like C!
>

This is at least misleading; while Lisp does indeed call by value, many of
those values happen to be references. As follows...

> So when you pass lista to aggiungi, L gets the value of lista, ie (1
> 2 3 4 5), and knows nothing about lista.
>

L gets the value of lista, but fundamentally the value of lista isn't (1 2 3
4 5); it's (1 x), with x being a pointer to (2 3 4 5). The scheme is
approximately the same as in Java, in fact.

Another way to write lista would be as (1 . (2 . (3 . (4 . (5 . nil))))).
Only the outermost layer is passed by value, and that value includes a
reference to the inner layers.

> It happens that setq returns the last value assigned so you get the
> right result, but you did not change lista!
>

This is true. lista isn't changed, only L is. The only thing you can do to L
that would work is to append something to it, and that's messy - it would
only work if lista is a list of two or more elements, which is rarely what
you want.

> Forget about setting in a _function_. Use a functional style:
>
> (defun aggiungi (x l)
> (cons x l))
>
> (defparameter lista '(1 2 3 4 5))
> (setf lista (aggiungi 10 lista))
> (setf lista (aggiungi 11 lista))
>

This is good advice, and probably the best way to do it.

Frank Buss

unread,
Oct 12, 2004, 1:53:50 PM10/12/04
to
Pascal Bourguignon <sp...@mouse-potato.com> wrote:

> That's because Lisp does not call by reference, it calls by value,
> like C!
>
> So when you pass lista to aggiungi, L gets the value of lista, ie (1
> 2 3 4 5), and knows nothing about lista.

this is a bit misleading. You are right, you can't change the variable,
but the list is bound like a pointer, so it is like a C-pointer (a
reference would be a C-pointer-pointer or a C++ reference). With this in
mind you can hack it like this (to the OP: don't do it like this, the
following is really ugly code and not something a Lisp programmer expects
from a function!)

(defun aggiungi (x l)
(let ((next-object (car l))
(next-cons (cdr l)))
(rplaca l x)
(rplacd l (cons next-object next-cons))))

CL-USER > (defparameter *l* '(1 2 3))
*L*

CL-USER > (aggiungi 10 *l*)
(10 1 2 3)

CL-USER > (aggiungi 20 *l*)
(20 10 1 2 3)

CL-USER > *l*
(20 10 1 2 3)

> Forget about setting in a _function_. Use a functional style:
>
> (defun aggiungi (x l)
> (cons x l))
>
> (defparameter lista '(1 2 3 4 5))
> (setf lista (aggiungi 10 lista))
> (setf lista (aggiungi 11 lista))

yes, this would be better, or using a macro.

Fred Gilham

unread,
Oct 12, 2004, 12:06:46 PM10/12/04
to

> but when i call
> (aggiungi 10 lista)
>
> the result is
> (10 1 2 3 4 5)

Note the following:

common-lisp-user [1]: (setq lista '(1 2 3 4 5))
Warning: Declaring LISTA special.

(1 2 3 4 5)

common-lisp-user [2]: (defun aggiungi (x L)



( setq L (cons x L)))

AGGIUNGI
common-lisp-user [3]: (aggiungi 10 lista)

(10 1 2 3 4 5)

common-lisp-user [4]: (aggiungi 10 lista)

(10 1 2 3 4 5)

common-lisp-user [5]: lista

(1 2 3 4 5)

Does this give you a clue?

To put it in box and arrow notation (without bothering to draw the
boxes):

lista -> | -> | -> | -> | -> | -> nil
1 2 3 4 5


Each

| ->

is a "cons cell", that is, it is a cell that can hold 2 data
references. Note also that lista is a symbol. It can hold a data
reference (along with other things).

The aggiungi function calls cons which creates a new cons cell whose
car (first data reference) is set to the x parameter and whose cdr
(second data reference) is set to the L parameter. But note that the
L parameter is *not* a pointer to the symbol lista. It is the
contents of the data reference that lista contains. So the cdr of the
new cons cell is set to point to the same thing lista was pointing to:


new
cons
cell
| -> |
10 |
|
lista -> | -> | -> | -> | -> | -> nil
1 2 3 4 5


So lista points to the old list structure, while aggiuni returns a
reference to a new cons cell whose first reference points to the x
value and whose second reference points to the old list that lista
points to.

To get the effect you want, you would have to do

common-lisp-user [7]: (setf lista (aggiungi 10 lista))
;

(10 1 2 3 4 5)

common-lisp-user [8]: lista

(10 1 2 3 4 5)

common-lisp-user [9]: (setf lista (aggiungi 10 lista))

(10 10 1 2 3 4 5)

common-lisp-user [10]: lista

(10 10 1 2 3 4 5)

common-lisp-user [11]:

--
Fred Gilham gil...@csl.sri.com
In matters of religion I have considered that its free exercise is
placed by the Constitution independent of the powers of the General
Government. I have therefore undertaken on no occasion to prescribe
the religious exercises suited to it, but have left them, as the
Constitution found them, under the direction and discipline of the
church or state authorities acknowledged by the several religious
societies. --- Thomas Jefferson, Second Inaugural Address

Philip Haddad

unread,
Oct 12, 2004, 4:10:33 PM10/12/04
to
Markanoid <x...@ngi.it> wrote in message news:<t6snm0tts7rloo7ft...@4ax.com>...

That's because you're variable L only has lexial scope, enough for one
use of the variable. It is released as soon as it is used by cons.
Try:
(let ((L (cons x L)))
......)
instead, that should work.

> tnk fr help, bye

--
May the Source be with you.
Philip Haddad

Markanoid

unread,
Oct 12, 2004, 6:28:24 PM10/12/04
to
>I must do a circular list. (it is a normal list?)
>
>i create the list
>(setq lista '(1 2 3 4 5))
>
>then define a function to add something
>(defun aggiungi (x L)
Thank you everyone for responses,
lisp is difficult but with a community like this become simpler.

Tomorrow i will try to correct my program, now i' m quite happy
because i cannod do it right because it was impossible.
I wanted create first of all a circular list;
than a function that append an atom to the list; all this avoid usng
macros , using pure lisp (at least using set) but now i think it is
impossible because there is no way to savesomting fo a futher
reelaboration.
Bye

Pascal Bourguignon

unread,
Oct 12, 2004, 7:54:48 PM10/12/04
to
Markanoid <x...@ngi.it> writes:

> >I must do a circular list. (it is a normal list?)
> >
> >i create the list
> >(setq lista '(1 2 3 4 5))
> >
> >then define a function to add something
> >(defun aggiungi (x L)
> Thank you everyone for responses,
> lisp is difficult but with a community like this become simpler.
>
> Tomorrow i will try to correct my program, now i' m quite happy
> because i cannod do it right because it was impossible.
> I wanted create first of all a circular list;

Note that transforming a proper list into a circular list can be done
and without needing the variable that hold the head of the list!
But is that what you want?


You're starting with a proper list:
+-----------------------------------------------------------+
| lst = (A B C D E) |
| | |
| v |
| +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
| | | | | | |
| v v v v v |
| +---+ +---+ +---+ +---+ +---+ |
| | A | | B | | C | | D | | E | |
| +---+ +---+ +---+ +---+ +---+ |
+-----------------------------------------------------------+


And you want to end with a circular list:
+-----------------------------------------------------------+
| lst = (A B C D E) |
| |+--------------------------------------------------+ |
| || | |
| vv | |
lista | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
+---|>| * | * |-->| * | * |-->| * | * |-->| * | * |-->| * | * | |
| +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |
| | | | | | |
| v v v v v |
| +---+ +---+ +---+ +---+ +---+ |
| | A | | B | | C | | D | | E | |
| +---+ +---+ +---+ +---+ +---+ |
+-----------------------------------------------------------+

If you have other variables holding the first cons cell, you can see
that they will see the change as well. You may note too that only the
last cons cell is changed, namely it's cdr. And that it must now
point to the first cons cell, the one that is referenced ot by lst.

So, we have: last, cdr, setf, lst. You should be able make it circular:

(defun loop-the-loop (lst)
(____ (____ (____ ____)) ____)) ;; fill the spaces.


Note that since loop-the-loop will modify the list, you cannot pass it
a list that appears in the source. No '(a b c d e)! You have to
construct the list (with cons or list), or copy a literal list.

(setf *print-circle* t)

(defparameter lista (copy-seq '(1 2 3 4 5)))
(loop-the-loop lista)
lista

(defparameter listb (list 'a 'b 'c 'd 'e)))
(loop-the-loop listb)
listb

Kenny Tilton

unread,
Oct 12, 2004, 7:22:02 PM10/12/04
to

Yes there is. You just have to do exactly that: "save something"

(setq *lista* (aggiungi 10 *lista*))

As someone noted, your particular example is something done by the macro
PUSH:

(push 10 *lista*)

...but that works only because it expands into the same thing as above:

(macroexpand-1 '(push atom list))
=> (SETQ LIST (CONS ATOM LIST))

You would have the same situation in "C", by the way, if you just passed
to aggiungi a variable containing the address of the first link in a
linked list. You would have to pass the address of the /variable/, which
is what Lisp does not do.

This is a frequent newby (and oldby) mistake with Lisp: even when using
destructive functions, one must often capture the result returned by the
destructive function. Knowing when requires /really/ understanding CONS,
CAR, and CDR, and (in this case) that the (setq L...) in your code was
not acting on *lista*.

kenny


--
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Peter Seibel

unread,
Oct 12, 2004, 2:50:57 PM10/12/04
to
Frank Buss <f...@frank-buss.de> writes:

A more important that this is a bad idea is it doesn't work with all
lists:

CL-USER> (aggiungi 10 nil)

Attempt to store in the car field of NIL which is not a cons.
[Condition of type SIMPLE-ERROR]

Restarts:
0: [ABORT] Abort handling SLIME request.
1: [ABORT] Abort entirely from this process.

-Peter

--
Peter Seibel pe...@javamonkey.com

Lisp is the red pill. -- John Fraser, comp.lang.lisp

Svein Ove Aas

unread,
Oct 14, 2004, 8:42:25 AM10/14/04
to
K. Ari Krupnikov wrote:

> Pascal Bourguignon <sp...@mouse-potato.com> writes:
>
>> Note that since loop-the-loop will modify the list, you cannot pass it
>> a list that appears in the source. No '(a b c d e)! You have to
>> construct the list (with cons or list), or copy a literal list.
>

> Stupid question - why?

Depending on the implementation, that list may be in read-only space
(hopefully), or ordinary space. (More likely)

Obviously, modifying it won't work in the first case. In the second it will,
but you get undefined behaviour... what's most likely to happen is that the
list will get modified, and it'll *stay* modified, meaning that the next
invocation of the same code won't read the same constant as it did the
first time.

And no, you may *not* use this to make static variables. That's what
closures are for.

Coby Beck

unread,
Oct 13, 2004, 4:14:25 PM10/13/04
to

"Philip Haddad" <philip...@gmail.com> wrote in message
news:ba57c4f9.04101...@posting.google.com...

> Markanoid <x...@ngi.it> wrote in message
> news:<t6snm0tts7rloo7ft...@4ax.com>...
>> I must do a circular list. (it is a normal list?)
>>
>> i create the list
>> (setq lista '(1 2 3 4 5))
>>
>> then define a function to add something
>> (defun aggiungi (x L)
>>
>> ( setq L (cons x L)))
>>
>> but when i call
>> (aggiungi 10 lista)
>>
>> the result is
>> (10 1 2 3 4 5)
>>
>> it' s ok but the nexxt time i will aspect
>> (10 10 1 2 3 4 5)
>>
>> BUT the result is always
>> (10 1 2 3 4 5)
>> for every time i call.
>> I do not understand why.. ( setq L (cons x L))) line doesn' t save my
>> new variable... ?
>
> That's because you're variable L only has lexial scope,

Right,

> enough for one
> use of the variable.

Don't quite know what this means?!

> It is released as soon as it is used by cons.

No (again this is non-standard terminology). It is no longer in scope after
the function returns.

> Try:
> (let ((L (cons x L)))
> ......)
> instead, that should work.

That won't work.


--
Coby Beck
(remove #\Space "coby 101 @ big pond . com")


K. Ari Krupnikov

unread,
Oct 14, 2004, 9:17:48 PM10/14/04
to
Svein Ove Aas <svei...@aas.no> writes:

> K. Ari Krupnikov wrote:
>
> > Pascal Bourguignon <sp...@mouse-potato.com> writes:
> >
> >> Note that since loop-the-loop will modify the list, you cannot pass it
> >> a list that appears in the source. No '(a b c d e)! You have to
> >> construct the list (with cons or list), or copy a literal list.
> >
> > Stupid question - why?
>
> Depending on the implementation, that list may be in read-only space
> (hopefully), or ordinary space. (More likely)
>
> Obviously, modifying it won't work in the first case. In the second it will,
> but you get undefined behaviour... what's most likely to happen is that the
> list will get modified, and it'll *stay* modified, meaning that the next
> invocation of the same code won't read the same constant as it did the
> first time.

You mean next time I say '(1 2 3 4 5) I'll get the modified, circular
copy?

Ari.

--
Elections only count as free and trials as fair if you can lose money
betting on the outcome.

Pascal Bourguignon

unread,
Oct 15, 2004, 12:20:56 AM10/15/04
to
a...@lib.aero (K. Ari Krupnikov) writes:

> Svein Ove Aas <svei...@aas.no> writes:
>
> > K. Ari Krupnikov wrote:
> >
> > > Pascal Bourguignon <sp...@mouse-potato.com> writes:
> > >
> > >> Note that since loop-the-loop will modify the list, you cannot pass it
> > >> a list that appears in the source. No '(a b c d e)! You have to
> > >> construct the list (with cons or list), or copy a literal list.
> > >
> > > Stupid question - why?
> >
> > Depending on the implementation, that list may be in read-only space
> > (hopefully), or ordinary space. (More likely)
> >
> > Obviously, modifying it won't work in the first case. In the second it will,
> > but you get undefined behaviour... what's most likely to happen is that the
> > list will get modified, and it'll *stay* modified, meaning that the next
> > invocation of the same code won't read the same constant as it did the
> > first time.
>
> You mean next time I say '(1 2 3 4 5) I'll get the modified, circular
> copy?

Exactly.

CL-USER> (setf *print-circle* t)
T
CL-USER> (defun give-a-list () '(1 2 3 4 5))
GIVE-A-LIST
CL-USER> (defparameter x (give-a-list))
X
CL-USER> x


(1 2 3 4 5)

CL-USER> (setf (cdr (last x)) x)
#1=(1 2 3 4 5 . #1#)
CL-USER> x
#1=(1 2 3 4 5 . #1#)
CL-USER> (give-a-list)
#1=(1 2 3 4 5 . #1#)
CL-USER> (function-lambda-expression 'give-a-list)
(LAMBDA NIL (DECLARE (SYSTEM::IN-DEFUN GIVE-A-LIST))
(BLOCK GIVE-A-LIST '#1=(1 2 3 4 5 . #1#)))
#(NIL NIL NIL NIL ((DECLARATION VALUES OPTIMIZE DECLARATION)))
GIVE-A-LIST
CL-USER>

'(1 2 3 4 5) was in the source, you modified the source. Literal data
will stay even in compiled code, so you could be modifying even a
compiled fonction!

Markanoid

unread,
Oct 17, 2004, 3:16:23 PM10/17/04
to


I finished my newbies program, tell me if it' s fine ;)
(implementation of a FIFO list withoutusing macro (close to pure
lisp))

;FUNCIONS
(defun lung (L)
(if (null L) 0
(+ 1(lung(cdr L)))))

(defun aggiungi (x L)
(if (= (lung L) 5) L
(cons x L)))

(defun rimuovi (L)
(if (null (cdr L))(cdr L)
(cons(car L)(rimuovi (cdr L)))))

; WRITE AT RUNTIME...
(setq lista (list ))
(setq lista (list 34 5 67 89 078 89))

(setq lista (aggiungi 1 lista))
(setq lista (aggiungi 2 lista))
(setq lista (aggiungi 3 lista))
(setq lista (aggiungi 4 lista))
(setq lista (aggiungi 5 lista))
(setq lista (aggiungi 9 lista))

(setq lista (rimuovi lista))

(lung lista)

tk, bye

Pascal Bourguignon

unread,
Oct 17, 2004, 3:49:51 PM10/17/04
to

Pascal Bourguignon

unread,
Oct 17, 2004, 4:16:18 PM10/17/04
to

1- define the API (the abstract type).
2- implement it.

For example:

1- for an informal specification of the abstract data type FIFO:

(make-fifo max-count) --> fifo

(fifo-max-count fifo) --> integer
(fifo-max-count (make-fifo x)) == x

(fifo-count fifo) --> integer
(fifo-count (make-fifo x)) == 0

(fifo-enqueue fifo element) --> fifo
if (fifo-count fifo) < (fifo-max-count fifo)
then (fifo-count (fifo-enqueue fifo x)) == 1 + (fifo-count fifo)
else (fifo-count (fifo-enqueue fifo x)) == (fifo-count fifo)

if (fifo-count fifo) == 0
then (fifo-dequeue fifo) --> nil
else (fifo-dequeue fifo) --> element


2- implementation:

(defun make-fifo (max-count)
(assert (and (integerp max-count) (< 0 max-count)))
(list :fifo max-count 0 nil nil))

(defun fifo-max-count (fifo)
(assert (and (listp fifo) (eq :fifo (first fifo))))
(second fifo))

(defun fifo-count (fifo)
(assert (and (listp fifo) (eq :fifo (first fifo))))
(third fifo))

(defun fifo-enqueue (fifo element)
(assert (and (listp fifo) (eq :fifo (first fifo))))
(cond ((= (second fifo) (third fifo)))
((null (fourth fifo))
(setf (fourth fifo) (list element)
(fifth fifo) (fourth fifo)
(third fifo) 1))
(t (setf (cdr (fifth fifo) (list element))
(fifth fifo) (cdr (fifth fifo)))
(incf (third fifo))))
fifo)

(defun fifo-dequeue (fifo)
(assert (and (listp fifo) (eq :fifo (first fifo))))
(when (< 0 (third fifo))
(prog1 (pop (fourth fifo))
(when (null (fourth fifo))
(setf (fifth fifo) nil))
(decf (third fifo)))))

As you can see, even though I did not use car/cdr/caddr, etc, it's
quite hard to read. Common-Lisp provides you with several tools to
implement such data structures: defstruct or defclass for example.

(defstruct fifo
(max-count 5 :type (integer 1))
(count 0 :type (integer 0))
(head nil :type list)
(tail nil :type list))

This automatically generates the following useful functions:

make-fifo
fifo-max-count
fifo-count
fifo-head
fifo-tail

Remains to implement:

(defun fifo-enqueue (fifo element)
(assert (typep fifo 'fifo))
(cond ((= (fifo-count fifo) (fifo-max-count fifo)))
((null (fifo-head fifo))
(setf (fifo-head fifo) (list element)
(fifo-tail fifo) (fifo-head fifo)
(fifo-count fifo) 1))
(t (setf (cdr (fifo-tail fifo)) (list element)
(fifo-tail fifo) (cdr (fifo-tail fifo)))
(incf (fifo-count fifo))))
fifo)


(defun fifo-dequeue (fifo)
(assert (typep fifo 'fifo))
(when (< 0 (fifo-count fifo))
(prog1 (pop (fifo-head fifo))
(decf (fifo-count fifo))
(when (null (fifo-head fifo))
(setf (fifo-tail fifo) nil)))))

If you need to have the fifo type be implemented with cons cells for
any reason (instead of a _structure_, you can merely change the
defstruct declaration:


(defstruct (fifo (:type list))
(max-count 5 :type (integer 1))
(count 0 :type (integer 0))
(head nil :type list)
(tail nil :type list))


Then the implementation will be exactly the same as above with cons
cells, only fifo-count is more readable than third or caddr.

(defparameter q (make-fifo :max-count 5))
(dolist (e '(il etait une souris verte qui courrait dans l\'herbe))
(fifo-enqueue q e))
(dotimes (i (fifo-count q))
(print (fifo-dequeue q)))

prints:

IL
ETAIT
UNE
SOURIS
VERTE

0 new messages