I've been thinking about the issue of needing Transient symbols.
On the whole I think it will be better to use transient symbols where necesary.

My line of though is that using destructive operators is exactly where
this is an issue. And that is what I'm trying to write about. I have
to say I'm always annoyed when I've spent a while examining a sample
program in some book, and getting to the Ahh so that's how you do it
moment, only have the author tell me, well that's not how you really
do it because we haven't considered X, Y and Z.


As such I think a more complex but actually safe example is more
valuable, even if in reality you would just use the built in fifo. How
do other people feel about incomplete teaching examples?

regs

Konrad.

On 15/10/2008, konrad Zielinski <[EMAIL PROTECTED]> wrote:
> 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]

Reply via email to