Re: returning multiple distinct closures

2012-02-24 Thread Alexander Burger
On Thu, Feb 23, 2012 at 09:48:14PM -0300, José Romero wrote:
 Your problem is using the quote function instead of making a copy of
 the list on return, this rewritten version should work:
 
 (de lazy Prg
(list NIL
   (list 'job (list 'quote (cons 'Value delayed))
  (list 'if '(== Value delayed)
 (list 'setq 'Value (cons 'run Prg))
 'Value ) ) ) )

That's right.


A slight simplification might be directly using 'prog' instead of 'run'

   (list 'setq 'Value (cons 'prog Prg))

This has the advantage that instead of

 (setq foo (lazy
 (prog
   (prinl !)
   2)))

You can write

   (setq foo (lazy (prinl !) 2))

or even better

   (def 'foo (lazy (prinl !) 2))

   : (pp 'foo)
   (de foo NIL
  (job '((Value . delayed))
 (if (== Value delayed)
(setq Value (prog (prinl !) 2))
Value ) ) )
   - foo
   : (foo)
   !
   - 2
   : (foo)
   - 2

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: returning multiple distinct closures

2012-02-24 Thread José Romero
I've been thinking on the problem a bit and found another way to tackle
it, using this incredibly *UGLY* function (all of them formatted as
the output of 'pp, I have no idea how to make it more aesthetically
pleasing):

(de lazy Prg
   (let L (box (cons))
  (con
 (val L)
 (list
(list
   'cdar
   (list
  'con
  L
  (list
 'list
 (list 'cons ''quote (cons 'prog Prg)) ) ) ) ) )
  (val L) ) )
- lazy
: (setq A (lazy (prinl Computing...) 42))
- (NIL (cdar (con $384526428 (list (cons 'quote (prog (prinl
Computing...) 42)) 
: (A)
Computing...
- 42
: (A)
- 42
: A
- (NIL '42)

As you can see, the resulting lambda modifies itself to become just the
quoted result on the first call. 

The way 'lazy works is by first boxing a cons pair to form the head of
the lambda expression. Then it concatenates a function body to that
head that is itself a call to 'con to replace itself with the computed
result in a quote. 

The box symbol is not necessary at all, I included it to make the
resulting expression printable. This version works the same, but
crashes print (rather, puts it in an infinite loop) if you use it in
the repl without a 'nil guard.

(de lazy Prg
   (let L (cons)
  (con
 L
 (list
(list
   'cdar
   (list
  'con
  (cons 'quote L)
  (list
 'list
 (list 'cons ''quote (cons 'prog Prg)) ) ) ) ) )
  L ) )
- lazy
: (nil (setq A (lazy (prinl Computing...) 42)))
- NIL
: (A)
Computing...
- 42
: (A)
- 42
: A
- (NIL '42)

Cheers,
José
--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: returning multiple distinct closures

2012-02-24 Thread Alexander Burger
Hi José,

 I've been thinking on the problem a bit and found another way to tackle
 it, using this incredibly *UGLY* function (all of them formatted as
 the output of 'pp, I have no idea how to make it more aesthetically
 pleasing):

Me neither ;-)

 (de lazy Prg
(let L (box (cons))
   (con
  (val L)
  (list
 (list
'cdar
(list
   'con
   L
   (list
  'list
  (list 'cons ''quote (cons 'prog Prg)) ) ) ) ) )
   (val L) ) )
 ...
 As you can see, the resulting lambda modifies itself to become just the
 quoted result on the first call. 
 
 The way 'lazy works is by first boxing a cons pair to form the head of
 the lambda expression. Then it concatenates a function body to that
 head that is itself a call to 'con to replace itself with the computed
 result in a quote. 


For a general-use 'lazy' functionn, I would use the one from the
RosettaCode task

   http://rosettacode.org/wiki/Formal_power_series#PicoLisp

It simply uses the 'cache' function which is intended for such purposes,
and has the advantage in that it lets you define real lazy functions
(i.e. with arguments):

   (de lazy Args
  (def (car Args)
 (list (cadr Args)
(cons 'cache (lit (cons))
   (list 'pack (list 'char (list 'hash (caadr Args))) (caadr Args))
   (cddr Args) ) ) ) )

   (lazy foo ()
  (prinl !)
  2 )

   : (foo)
   !
   - 2
   : (foo)
   - 2


   : (lazy bar (X Y)
  (prinl !!)
  (+ X Y) )
   - bar

   : (bar 2 3)
   !!
   - 5

   : (bar 3 4)
   !!
   - 7

   : (bar 2 3)
   - 5

   : (bar 3 4)
   - 7

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: closures

2008-10-26 Thread Tomas Hlavaty
Hi Alex,

(let @S '((I . 0))
   (def 'count (curry (@S) () (job '@S (inc 'I
   (def 'reset (curry (@S) () (job '@S (zero I )

(let @S (list (cons 'I 0))
(let I (cons 0)

I like it this way, thanks.

I also found that once the things inside the closures get complicated,
it might be worth using objects to get better code factoring:

(class +Counter) # i
(dm T () (=: i 0))
(dm count () (inc (:: i)))
(dm reset () (=: i 0))

(let @C (list (cons 'C (new '(+Counter
   (def 'count (curry (@C) () (job '@C (count C
   (def 'reset (curry (@C) () (job '@C (reset C )

Or using objects directly so that I can have many independent
counters...  It did the job for my understanding of closures in
picoLisp, I hope:-)

 Sometimes non-evaluating functions are a little more convenient, and
 at least theoretically more efficient.

 (zero A) occupies two cells.

 (zero 'A) would be three, and that's the same as (setq A 0), so it
 would not save any space.

Have you measured and/or noticed impact on performance of these
micro-optimizations?  I mean, are they really worth it?

Thanks,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


closures

2008-10-24 Thread Tomas Hlavaty
Hi Alex,

is there a better way of achieving the following?

(let @S '((I . 0))
   (def 'count (fill '(() (job '@S (inc 'I)
   (def 'reset (fill '(() (job '@S (zero I))

The two functions are closed over the same var/env.

(count) = 1
(count) = 2
(reset) = 0
(count) = 1

http://www.software-lab.de/faq.html#closures discusses curry function
which allows closure inside a single function only.

Thank you,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]