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


Re: box? on address

2017-02-09 Thread pd
On Thu, Feb 9, 2017 at 6:13 PM, Christopher Howard  wrote:

> Hi, I was just trying to understand...
>
> : (box? (box (4 5 6)))
> -> $384375304
> : (box? $384375304)
> -> NIL
> : (car $384375304)
> -> 4
>
> Shouldn't (box? $384375304) be non-NIL?
>

As Danilo said box? evaluates its arguments and that's the reason to return
NIL because a list is not an anonymous symbol

The same happens with the call to car, car evaluates its arguments so you
get the car of the list

To allow box? to deal with anonymous symbol you must quote it

If you type the $-number representing the anonymous symbol in the pil
prompt you see its value, in your case:

: $384375304
-> (4 5 6)

The result of evaluating the anonymous symbols and that explains the
behaviour of your calls to both box? and car,

: (car $384375304)# = (car (4 5 6))
-> 4

but what if you call car with real anonymous symbol (quoting it to prevent
evaluation)?

: (car '$384375304)
-> (4 5 6)

why? my guess is anonymous symbols store its value in the car of its cell


Re: box? on address

2017-02-09 Thread Mike Pechkin
hi,

Lets talk about
​​t
ransient
​s​
ymbols
​ from this two links:
http://software-lab.de/doc/ref.html#transient
http://pastebin.com/AsuveCFY

​

On Thu, Feb 9, 2017 at 7:13 PM, Christopher Howard  wrote:

> Hi, I was just trying to understand...
>
> : (box? (box (4 5 6)))
> -> $384375304
> : (box? $384375304)
> -> NIL
> : (car $384375304)
> -> 4
>
> Shouldn't (box? $384375304) be non-NIL?
>
> --
> Christopher Howard, Computer Assistant
> Alaska Satellite Internet
> 3239 La Ree Way, Fairbanks, AK 99709
> 907-451-0088 or 888-396-5623 (toll free)
> fax: 888-260-3584
> mailto:christop...@alaskasi.com
> http://www.alaskasatelliteinternet.com
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>


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


Re: box? on address

2017-02-09 Thread Danilo Kordic
`box?' evaluates it's argument.  In this case it is `lst' ``(4 5 6)''.

BTW I didn't know `print'ed box can be `read' back.
For example ``$0'' does have a name, but `print'ed one does not.
It makes no sense to me.


On 2/9/17, Christopher Howard  wrote:
> Hi, I was just trying to understand...
>
> : (box? (box (4 5 6)))
> -> $384375304
> : (box? $384375304)
> -> NIL
> : (car $384375304)
> -> 4
>
> Shouldn't (box? $384375304) be non-NIL?
>
> --
> Christopher Howard, Computer Assistant
> Alaska Satellite Internet
> 3239 La Ree Way, Fairbanks, AK 99709
> 907-451-0088 or 888-396-5623 (toll free)
> fax: 888-260-3584
> mailto:christop...@alaskasi.com
> http://www.alaskasatelliteinternet.com
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: binding free symbols in a lambda definition

2017-02-09 Thread Lindsay John Lawrence
Hi Alex,

> However, a function call is about the most expensive thing in PicoLisp. It
> interprets the parameter list (X), saves the old value of X, evaluates
(not X)
> and restores the value of X.

(de null..) was really unnecessary here :) I just wrote it for completeness
as part of the book exercise and after my earlier confusion regarding 'NIL,
NIL, '()...
Nice to know about 'def' when I need a bit of syntax sugar though !

I am starting to get the hang of the basics here I think.
I've been spending a bit of time bench'ing some of the recursive functions
and trying to eliminate the recursion or use a built-in function, as you
have often shown.

# my append
: (de cuius (X Y) (cond ((not X) Y) (T (cons (car X) (cuius (cdr X) Y)
: (bench (let (N ()) (for X 1 (setq N (cuius N '(NIL (length N)))
2.983 sec
-> 1

# ...with nond
: (de cuius (X Y) (nond (X Y) (NIL (cons (car X) (cuius (cdr X) Y)
: (bench (let (N ()) (for X 1 (setq N (cuius N '(NIL (length N)))
2.644 sec
-> 1

# ... neither of the above are even close in performance to ...
# append
: (bench (let (N ()) (for X 1 (setq N (append N '(NIL (length N)))
0.548 sec
-> 1

# cons
: (bench (let (N '()) (for X 1 (setq N (cons NIL N))) (length N)))
0.000 sec
-> 1

# conc
: (bench (let (N (list)) (for X  (conc N (list))) (length N)))
0.067 sec
-> 1

# -- or --
: (bench (let (N ()) (setq N (need 1)) (length N)))
0.000 sec
-> 1.

Interestingly, I was expecting conc to be faster then (setq..(cons..). At
least in this case, it was not.


/Lindsay


box? on address

2017-02-09 Thread Christopher Howard
Hi, I was just trying to understand...

: (box? (box (4 5 6)))
-> $384375304
: (box? $384375304)
-> NIL
: (car $384375304)
-> 4

Shouldn't (box? $384375304) be non-NIL?

-- 
Christopher Howard, Computer Assistant
Alaska Satellite Internet
3239 La Ree Way, Fairbanks, AK 99709
907-451-0088 or 888-396-5623 (toll free)
fax: 888-260-3584
mailto:christop...@alaskasi.com
http://www.alaskasatelliteinternet.com
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: binding free symbols in a lambda definition

2017-02-09 Thread Danilo Kordic
If `and' and `or' is renamed, or just aliased, to `then' and `else',
there is little need left for `if' and `cond' >:) .
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: binding free symbols in a lambda definition

2017-02-09 Thread Alexander Burger
Hi Lindsay,

> I missed to include it...
>(de null (X) (not X))

OK! :)

However, a function call is about the most expensive thing in PicoLisp. It
interprets the parameter list (X), saves the old value of X, evaluates (not X)
and restores the value of X.

Therefore I would recommend

   (def 'null not)

This gives zero overhead :)


> I'll have to work with nond a bit more to get how/when use that.

Good. Just use the opposite conditions. Instead of

   (cond
  ((not A) (foo))
  ((not B) (bar))
  (T (mumble)) )

you write

   (nond
  (A (foo))
  (B (bar))
  (NIL (mumble)) )

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


Re: binding free symbols in a lambda definition

2017-02-09 Thread Lindsay John Lawrence
Hi Alex,

I missed to include it...
   (de null (X) (not X))

Thanks! for the suggestions.

I tried the pairlis alternatives. Much better.
'extract' will be very useful.

I'll have to work with nond a bit more to get how/when use that.

/Lindsay


On Thu, Feb 9, 2017 at 3:17 AM, Alexander Burger 
wrote:

> Hi Lindsay,
>
> > # pairlis2: gives a list of pairs of corresponding elements
> > # of the lists x and y, and appends this to the list a.
> > # (pairlis '(A B C) '(1 2) () ) -> ((A . 1) (B . 2))
> >
> > (de pairlis2 (X Y A)
> >(cond
> >   ((null X) A)
> >   ((null Y) A)
> >   (T
> >  (cons
> > (cons (car X) (car Y))
> > (pairlis2 (cdr X) (cdr Y) A) ) ) ) )
>
> Sorry, I have not tested, but 'null' should be undefined. You could
> replace it
> with 'not'. But then 'nond' is better than 'cond', avoiding it completely
> (see
> discussion here in this list).
>
>
> In general, using recursion here is quite an overkill. A simpler form
> could be
>
>(de pairlis (X Y A)
>   (conc (mapcar cons X Y) A) )
>
> or, if you want to handle the case where the first list is longer than the
> second,
>
>(de pairlis (X Y A)
>   (conc
>  (extract
> '((A B) (and A B (cons A B)))
> X
> Y )
>  A ) )
>
> ♪♫ Alex
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>


Re: binding free symbols in a lambda definition

2017-02-09 Thread Lindsay John Lawrence
Picolisp continues to astonish me with its 'Principle of Least
Astonishment'... using @ variable arguments is much nicer.

/Lindsay

# using pairlis2 and sublis from prior email...
(de curri2 @
   (let
  (Fun (next)
 Args (rest)
 Par (pairlis2 (car Fun) Args)
 dropP
 '((X Y)
(cond
   ((null Y) X)
   (T (dropP (cdr X) (cdr Y))) ) ) )
  (list
 (dropP (car Fun) Args)
 (car (sublis Par (cdr Fun))) ) ) )
-> curri2

: (setq Fun (curri2 '((X Y) (+ X Y
-> ((X Y) (+ X Y))
: (Fun 1 99)
-> 100
: (setq Fun (curri2 '((X Y) (+ X Y)) 1) )
-> ((Y) (+ 1 Y))
: (Fun 99)
-> 100
: (setq Fun (curri2 '((X Y) (+ X Y)) 1 99) )
-> (NIL (+ 1 99))
: (Fun)
-> 100


Re: binding free symbols in a lambda definition

2017-02-09 Thread Alexander Burger
Hi Andrés,

thanks for the "curri" examples!

> Sorry for the large email and even while pretending to be a clarifying text
> it is not :(

I think it was :)

> Also don't want to give an image of pretending to arrange picolisp's flaw
> design, it is absolutely not, not only I don't have the needed
> understanding of picolisp nor the knowledge to do so but I consider
> picolisp a pretty good design with very smart decisions. What I trying to

No worry, I didn't get that impression.


I knew these use cases, but until now never had practical situations where they
seemed useful. As we saw, they can be handled with the 'curry' function if
necessary, but I believe that PicoLisp has better mechanisms - like fexprs and
unlimited number of arguments to most functions - to *directly* express the
programmer's intentions.

For example,

> (mapcar ((curri **) 2)  (2 3 4))
> # equivalent to (mapcar '((X) (** 2 X)) (2 3 4))

would be written shorter in PicoLip

   (mapcar ** (2 3 4) (2 .))
   -> (4 9 16)


> (setq lstLen ((curri mapcar) length))   # equivalent to (de lstLen
> (lst) (mapcar length lst))
> (lstLen '((1) (2 3 4) (2 3)))

   (mapcar length '((1) (2 3 4) (2 3)))
   -> (1 3 2)



> yes, I have to study your classiCurry function to clearly understand how it
> works and yes maybe I'm a bit confused about dynamic binding usefulness due
> to my static binding background

You are not alone :) I try to explain more, perhaps it is also useful for other
readers here.


> (let N 4 (print N))
> 
> binds symbol N to value 4 inside print expression and so it prints 4, this
> is what we expect of let binding behaviour

Yes, though instead of "binds .. inside print" I would say "binds N to 4 inside
the body of 'let'.

A lexically binding system would indeed magically replace N in the print
expression, but in PicoLisp N is bound to 4 during the *time* this let body
runs.


> same for this code:
> 
> (let N 4 (+ 1 N))
> 
> we expect to return 5

Yes.


> In a coherent way we expect this code:
> 
> (let N 4 ((X) (+ X N)))  # erroneus code, I know it!
> 
> to return a function which adds 4 to its parameter   (and it would do it if
> it doesn't throw a X undefined error)

No. This code is not wrong per se, it just does not return a function.

As you know, Lisp evaluates expressions by taking the CAR as a function, and the
CDR as arguments to that function. So when the body of 'let' is executed, (X) is
expected to evaluate to a function, and the result of evaluating (+ X N) is
passed to that function.

There might even be situations where the above expression makes sense. The
problem is more that '+' expects a number, so let's modify it slightly:

   : (de X () # Define 'X' to return a function
  println )
   -> X

   : (let N 4 ((X) (+ (size X) N)))
   6
   -> 6

What happens? (X) evaluates to the function 'println' (the function *pointer* to
be exact, as 'println' is a primitive):

   : X
   -> (NIL println)

   : (X)
   -> 22966530359  # Function pointer to the code of 'println'

Then (+ (size X) N) is evaluated

   : (size X)
   -> 2

and passed to be printed. It prints 6.


> But here the problem is we cannot write an anonymous function (a lambda)
> this way, we *must* quote it:
> 
> (let N 4 '((X) (+ X N)))

No, you *did* write an anonymous function. It ignored the value of N though.

In PicoLisp, code and data are absolutely equivalent. Thus, the list

   ((X) (+ X N))

is, first of all, data. A list of two lists.

The fact that it might be interpreted somewhere else as a function doesn't
matter. The point is that in our head we want to return a function, but here we
have a chunk of data to be returned. Thus it must be quoted, to inhibit the
evaluation as seen above.


> but now the quoting has the effect of not evaluating the lambda and thus
> preserving it from let symbol binding, this is an undesiderable effect in
> my opinion

Yes, because there is no lexical (static) binding. All symbols are evaluated
solely at runtime. If you need the values statically, you have to do it
explicitly, e.g. with 'curry' or simply with list operations:

   (let N 4 (list '(X) (list '+ 'X N)))
   -> ((X) (+ X 4))

Voila, the expected function is returned.


> So what to do? (from here I'm just reasoning loud) well, the key is to
> separate function evaluation from function calling, what if there would be
> a mark for type function?

No, this would be a big drawback. You lose the equivalence of code and data.

The term "function evaluation" is the same as "function calling". What you mean
is "function building", i.e. the process of building a function from data, to be
evaluated (or called) later.


> 1- read the whole let expression
> 2- read-macros get executed inmmediately (really I think this is part of
> step 1)
> 3- perform the bindings in "let prog" expression
> 4- evaluate the "let prog" in te context set by let bindings (due to step 3)

Exactly. And this is what happens. The point is just that the bindings 

Re: binding free symbols in a lambda definition

2017-02-09 Thread Lindsay John Lawrence
I've enjoyed the discussion. Curry is a common idiom in the javascript
world (my current day job) so it was very interesting to explore it here.

Being relatively new to picolisp I have a lot to learn about built-in
functionality so exploring these ideas, with feedback from Alex and others
more familiar, is very productive!

Below is YAC (Yet another curry)...

A simplication, that would allow more natural writing, would be to use @
instead
of the current Args list of provided params to curri2. I am still getting
the hang of that...

/Lindsay

I apologise if it is a lot of code to post here, but this was also great
opportunity to apply a bit of what I have been learning from the "Lisp 1.5
Programmer's Manual"

# note: pairlis2, sublis are functions are adapted from the manual to
implement 'curri2'

# pairlis2: gives a list of pairs of corresponding elements
# of the lists x and y, and appends this to the list a.
# (pairlis '(A B C) '(1 2) () ) -> ((A . 1) (B . 2))

(de pairlis2 (X Y A)
   (cond
  ((null X) A)
  ((null Y) A)
  (T
 (cons
(cons (car X) (car Y))
(pairlis2 (cdr X) (cdr Y) A) ) ) ) )

# 'A is an assoc list ((u . v)..).
# sublis: treats the u's as variables
# when they occur in Y, and substitutes the
# corresponding v's from the pair list

(de sublis (A Y)
   (let
  (sub2
 '((A Z)
(cond
   ((null A) Z)
   ((= (caar A) Z) (cdar A))
   (T (sub2 (cdr A) Z)) ) ) )
  (cond
 ((atom Y) (sub2 A Y))
 (T
(cons
   (sublis A (car Y))
   (sublis A (cdr Y)) ) ) ) ) )


# And now we can make curry too!

(de curri2 (Fun Args)
   (let
  (Par (pairlis2 (car Fun) Args)
 dropP
 '((X Y)
(cond
   ((null Y) X)
   (T (dropP (cdr X) (cdr Y))) ) ) )
  (list
 (dropP (car Fun) Args)
 (car (sublis Par (cdr Fun))) ) ) )

-> curri2
: (curri2 '((X Y) (+ X Y)))
-> ((X Y) (+ X Y))
: ('((X Y) (+ X Y)) 1 2)
-> 3
: (curri2 '((X Y) (+ X Y)) (1))
-> ((Y) (+ 1 Y))
: ('((Y) (+ 1 Y)) 2)
-> 3
: (curri2 '((X Y) (+ X Y)) (1 2))
-> (NIL (+ 1 2))
: ('(NIL (+ 1 2)))
-> 3


Re: binding free symbols in a lambda definition

2017-02-09 Thread pd
Sorry for the large email and even while pretending to be a clarifying text
it is not :(

Also don't want to give an image of pretending to arrange picolisp's flaw
design, it is absolutely not, not only I don't have the needed
understanding of picolisp nor the knowledge to do so but I consider
picolisp a pretty good design with very smart decisions. What I trying to
do is speaking out loud spreading out my thoughts to see if my
understanding is right and also to see if my ideas may be useful somehow or
must be considered as nonsenses

On Thu, Feb 9, 2017 at 2:17 AM, pd  wrote:

>
>
> But let me try to better explain myself...
>
>