On Fri, 24 Feb 2012 00:03:34 +0000
Imran Rafique <im...@rafique.org> wrote:

> Picolisp'ers,
> 
> As the subject asks, is it possible to return multiple distinct
> closures from a single function? I was trying out a simple lazy lists
> implementation. The lazy function takes in something and returns that
> something wrapped in another function. If you want to 'force' the
> lazy value, you execute the wrapped function.
> 
> The closure is needed to ensure that when you force a value more than
> once, the wrapped function only gets executed the first time (and the
> cached value is used thereafter).
> 
> So:
> 
> (de lazy @Bdy
>   (fill
>     '(job '((forced? . NIL)
>             (value . "delayed"))
>        (unless forced?
>          (setq value (eval (car '@Bdy)))
>          (setq forced? T))
>        value)))
> 
> (de force (Lz)
>   (eval Lz))
> 
> Pretty simple stuff, but it doesn't work as intended. The closure
> returned by 'lazy' is the same job closure for ALL invocations of
> lazy.
> 
> (setq foo (lazy
>             (prog
>               (prinl "!")
>               2)))
> 
> (setq bar (lazy
>             (prog
>               (prinl "!!")
>               3)))
> 
> 
> pico λ: (force foo)
> !
> -> 2
> pico λ: (force foo)
> -> 2
> pico λ: (pretty bar)
> (job '((forced? . T) (value . 2))
>    (unless forced?
>       (setq
>          value (eval (car '((prog (prinl "!!") 3)))) )
>       (setq forced? T) )
>    value )-> ")"
> pico λ: (force bar)
> -> 2
> 
> Is this an artifact of how 'job' works, by rewriting the internal
> definition of the function which contains the call to job? How can
> one return distinct *different* closures from a single function?
> 
> Returning a properly formed anonymous function (as opposed to a 'job'
> form) doesn't make a difference:
> 
> (de lazy2 @Bdy
>   (fill
>     '(()
>       (job '((forced? . NIL)
>              (value . "delayed"))
>         (unless forced?
>           (setq value (eval (car '@Bdy)))
>           (setq forced? T))
>         value))))
> 
> (de force2 (Lz)
>   (Lz))
> 
> --
> Regards,
>        Imran Rafique

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 ) ) ) )
(====)

(de force (Lz)
   (Lz) )

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

(setq bar (lazy
            (prog
              (prinl "!!")
              3)))

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

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

Reply via email to