Re: conc: unexpected results

2017-02-10 Thread Alexander Burger
On Fri, Feb 10, 2017 at 08:32:06PM +0100, Pierpaolo Bernardi wrote:
> On Fri, Feb 10, 2017 at 6:24 PM, Alexander Burger  
> wrote:
> 
> > Right Lindsay, this is called "nconc" in other versions of Lisp. There was 
> > the
> > convention - for some obscure reason - to put an "n" in front of the names 
> > of
> > destructive list operations: nconc, nreverse, ndelete ...
> 
> In case someone wonders, the n prefix stood for 'non-consing'

Cool! Thanks!!

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


Re: conc: unexpected results

2017-02-10 Thread Alexander Burger
On Fri, Feb 10, 2017 at 10:31:20AM +0100, pd wrote:
> On Fri, Feb 10, 2017 at 6:47 AM, Lindsay John Lawrence <
> > Apologies for bothering everyone with this. It took some research (there
> > is surprising little discussion of the function online or even in most
> > books), but I at least understand how it works now.
> 
> It would be great if you explain how it works, at least for me since I
> cannot understand why 2. returns NIL rather than (A)

'conc' is the destructive version of 'append'.

Right Lindsay, this is called "nconc" in other versions of Lisp. There was the
convention - for some obscure reason - to put an "n" in front of the names of
destructive list operations: nconc, nreverse, ndelete ...

'conc' traverses each list argument and puts the next argument into the CDR of
the last cell:

   : (conc (1 2) (3))
   -> (1 2 3)

This has the consequence that if the last arg is atomic

   : (conc (1 2) 'a)
   -> (1 2 . a)

that atom is of course stored in that last CDR.

Now, if yet another argument follows, this last CDR gets overwritten

   : (conc (1 2) 'a (3))
   -> (1 2 3)

So as a result atomic arguments are simply lost. This happens also if the atom
is the first argument

   : (conc 'a (1 2))
   -> (1 2)


BTW, all the above applies to 'append' as well.

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


Re: conc: unexpected results

2017-02-10 Thread pd
On Fri, Feb 10, 2017 at 6:47 AM, Lindsay John Lawrence <
lawrence.lindsayj...@gmail.com> wrote:

>
> Apologies for bothering everyone with this. It took some research (there
> is surprising little discussion of the function online or even in most
> books), but I at least understand how it works now.
>

It would be great if you explain how it works, at least for me since I
cannot understand why 2. returns NIL rather than (A)


Re: conc: unexpected results

2017-02-10 Thread Danilo Kordic
Hi Lindsay.

AFAIK there is only one empty `list' in PL, and that is `NIL'.  So
after `conc'atenating to it's end it would no longer be empty.

How about:

[de ex1 []
  [make
[do 10
  [link 'A] ] ] ]

[de ex2 []
  [let [R [list]]
[do 10
  [conc R [list 'A]] ]
# Will have to find the end of `R' each time!!
# Even worse if `R' is `circ'ular, which will result in
infinite recursion and out of stack memory.
# In Your second implementation `'[A]' was `conc'ed to itself,
which resulted in `circ'ular list `[A .]'.
  # : [setq L1 '[A]] [conc [] L1 L1]
  # -> [A .]
# To avoid that it was corrected to `[list 'A]'.
(cdr R) ] ]

[de ex3 [N]
  [default N 10]
  [let [R []]
[for I 10
  [fifo 'R I] ]
[prog1 (cdr R)
  (con R []) ] ] ]
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: conc: unexpected results

2017-02-09 Thread Lindsay John Lawrence
Apologies for bothering everyone with this. It took some research (there is
surprising little discussion of the function online or even in most books),
but I at least understand how it works now.

It seems that it is not often used in everyday programming: "It is a good
idea to leave the use of NCONC, RPLACA, RPLACD, and DELETE to risk-loving
programmers. Unless desperate for time or space saving, using them just
leads to unnecessary bugs. "--Lisp (Winston, Horn) P. 117

/Lindsay


On Thu, Feb 9, 2017 at 5:21 PM, Lindsay John Lawrence <
lawrence.lindsayj...@gmail.com> wrote:

> I tried conc to an empty list on both 32 and 64 bit versions of picolisp
> I even installed SBCL just to try the similar 'nconc' on that platform.
>
> The results are consistent for all of them.
> I  just don't understand why Is it simply 'standard', historical
> reasons? because of the way evaluation works?
>
> As it is, I would not be able to build a list 'destructively' without
> conditional logic for the initial empty list.
> conc works as expected when M is not empty. i.e M is rewritten.
>
>
> # 
> # Could also use NIL to represent the empty list (
> http://software-lab.de/doc/ref.html#nilSym)
> : (setq M '() N '(A B C))
> -> (A B C)
> : (conc M N)
> -> (A B C)
> : M
> -> NIL
> : N
> -> (A B C)
>
> # This is even weirder to me...
> # Again, I expected M, not N, to be rewritten
> : (setq M NIL N '(A B C) L '(1 2 3))
> -> (1 2 3)
> : (conc M N L)
> -> (A B C 1 2 3)
> : M
> -> NIL
> : N
> -> (A B C 1 2 3)
> : L
> -> (1 2 3)
> # -
>
> /Lindsay
>
>
>


Re: conc: unexpected results

2017-02-09 Thread Lindsay John Lawrence
I tried conc to an empty list on both 32 and 64 bit versions of picolisp
I even installed SBCL just to try the similar 'nconc' on that platform.

The results are consistent for all of them.
I  just don't understand why Is it simply 'standard', historical
reasons? because of the way evaluation works?

As it is, I would not be able to build a list 'destructively' without
conditional logic for the initial empty list.
conc works as expected when M is not empty. i.e M is rewritten.


# 
# Could also use NIL to represent the empty list (
http://software-lab.de/doc/ref.html#nilSym)
: (setq M '() N '(A B C))
-> (A B C)
: (conc M N)
-> (A B C)
: M
-> NIL
: N
-> (A B C)

# This is even weirder to me...
# Again, I expected M, not N, to be rewritten
: (setq M NIL N '(A B C) L '(1 2 3))
-> (1 2 3)
: (conc M N L)
-> (A B C 1 2 3)
: M
-> NIL
: N
-> (A B C 1 2 3)
: L
-> (1 2 3)
# -

/Lindsay


conc: unexpected results

2017-02-09 Thread Lindsay John Lawrence
conc does not rewrite N if N is an empty list.

# 1.
: (let (N '()) (conc N '(A)))
-> (A)
# 2
: (let (N '()) (conc N '(A)) N)
-> NIL
# 3.
: (let (N '(NIL)) (conc N '(A)) N)
-> (NIL A)
# 4.
: (let (N '()) (setq N (conc N '(A))) N)
-> (A)

In #2 above, I was expecting N to be (A)
If N is not empty, as in #3 it works as expected, or I can force the
assignment, as in #4... which shouldn't be necessary.

Originally I wanted to do:
:  (let (N '()) (for X 10 (conc N '(A))) N)
-> NIL  # expected '(A A A A A A A A A A)

..and this goes into never land. [kill -9]
 (let (N '()) (for X 10 (setq N (conc N '(A N)


/Lindsay