Thanks Alex, I had misgivings about using eval in my code, and a feeling that there must be a better way.
The inability to add NIL is something I completely missed, though. True not somthing that you would ordinarily do at the prompt but quite likely deep inside application code. As to useing Transient symbols. I think I will note it in my description as you have. As far as I know Inadvertant variable capure is a problem somwhere in most Lisp dialects. I know it can be an issue in Common Lisp as well. Granted the circumstancs are different, but the problem seems to keep cropign up. regs Konrad. On 14/10/2008, Alexander Burger <[EMAIL PROTECTED]> wrote: > 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] > -- UNSUBSCRIBE: mailto:[EMAIL PROTECTED]