Hi Konrad,
> I decided to re-implemtn the fifo function using these primitives.
Good idea! This will give a lot of useful and practical examples.
> (de my-fifo (Fifo Item)
> (let RealFifo (eval Fifo)
> (if Item
> (if RealFifo # Adding to a Fifo
> (let NewHead (cons Item (cdr RealFifo))
> (con RealFifo NewHead)
> (set Fifo NewHead)
> Item)
> (prog # Creating a new fifo
> (set Fifo (list Item) 'RealFifo (eval Fifo))
> (con RealFifo RealFifo)
> Item))
> (if (== RealFifo (cdr RealFifo))
> (prog1 # Returning the Last Item
> (car RealFifo)
> (set Fifo NIL))
> (prog1 # Returning an Item
> (cadr RealFifo)
> (con RealFifo (cddr RealFifo)))))))
>
> Questions, Comments, Suggestions ?
There are some minor changes I would suggest:
1. The 'Item' argument is used as an indicator whether a value is going
to be inserted into the queue (non-NIL), or removed from the queue
(NIL). The problem is then that NIL itself can never be inserted.
Therefore, I would suggest to make 'Item' an optional argument, by
using the '@' notation, and use retrieval functions like (args) and
(next).
2. Instead of (eval Fifo) I would use (val Fifo). While this makes no
difference if 'Fifo' is bound to a symbol, it also allows cell
arguments (see also the 'var' discussion shortly ago):
: (setq L (need 3))
-> (NIL NIL NIL)
: (my-fifo (cdr L) 1)
-> 1
: (my-fifo (cdr L) 2)
-> 2
: (my-fifo (cdr L) 3)
-> 3
: L
-> (NIL (3 1 2 .) NIL)
: (my-fifo (cdr L))
-> 1
: L
-> (NIL (3 2 .) NIL)
3. The 'prog' ("Creating a new fifo") is not really needed, as it is
implied in the 'else' part of 'if'. It does no harm, though.
With these changes, my version would be:
(de my-fifo (Fifo . @)
(let RealFifo (val Fifo)
(if (args)
(if RealFifo # Adding to a Fifo
(let NewHead (cons (next) (cdr RealFifo))
(con RealFifo NewHead)
(set Fifo NewHead)
(arg) )
# Creating a new fifo
(set Fifo (list (next)) 'RealFifo (val Fifo))
(con RealFifo RealFifo)
(arg) )
(if (== RealFifo (cdr RealFifo))
(prog1 # Returning the Last Item
(car RealFifo)
(set Fifo NIL) )
(prog1 # Returning an Item
(cadr RealFifo)
(con RealFifo (cddr RealFifo)) ) ) ) ) )
However! Now one ugly detail remains, and I would probably not put this
into such an educational example. But it is one of the sore spots in
PicoLisp:
4. To make it absolutely correct, all locally bound symbols (i.e. Fifo,
RealFifo and NewHead) should be transient symbols (i.e. "Fifo",
"RealFifo" and "NewHead"). Otherwise a call like
(my-fifo 'Fifo 1)
would fail. This is explained a bit in "doc/faq.html#problems". Here
we have the case that a symbol might be bound to itself and its value
is being accessed.
For a real production library, I would definitely write it with
transient symbols. For part of an application, it is usually not so
critical as you usually have some naming conventions. But even then
you might run into an error during testing.
Cheers,
- Alex
--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]