Hi Christophe,

I can assure you that 'conc' always evaluates its first arg.


> (dm push> (elt)
>    (conc (:: elts) (list elt)) )  # this doesn't work

'conc' destructively concatinates the arguments. This means that the
pointer to the second list is stored in the CDR of the last cell of the
first list.

But here you pass (:: elts) as the first argument, which is the property
cell in the symbol. That doesn't make much sense.


What you could do is

   (dm push> (Elt)
      (conc (: elts) (list Elt)) )

But this works only if the property 'elts' is not empty (NIL). Because
despite the fact that concatenating NIL with a second list returns that
list, there is no storing in any CDR as a side effect, so the result of
the 'conc' is lost.

Thus, if you want to start with empty 'elts', you might do

   (dm push> (Elt)
      (=: elts (conc (: elts) (list Elt))) )

In this way you don't lose the result of the first 'conc'.


> So is there a mean to implement the problematic line ?
> (=: elts (append (: elts) elt))

This would be correct, and is basically the same as my proposal, just:

> but found it maybe not efficient (recreates the list?).

Correct. 'conc' and 'append' are equivalent to a certain degree, at
least as far as the return value is concerned. But 'append' copies all
arguments except for the last one.


Having said all this, if you want to implement 'push', why don't
you use 'push' directly?

   (dm push> (Elt)
      (push (:: elts) Elt)) )

This inserts the elements in opposite order as with 'conc' though, but
that is what push is after all:

   : (with 'A (push (:: elts) 123))
   -> 123
   : (with 'A (push (:: elts) (1 2 3)))
   -> (1 2 3)
   : (with 'A (push (:: elts) 'abc))
   -> abc

   : (get 'A 'elts)
   -> (abc (1 2 3) 123)

   : (with 'A (pop (:: elts)))
   -> abc
   : (get 'A 'elts)
   -> ((1 2 3) 123)

♪♫ Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to