On Fri, 24 Feb 2012 00:03:34 +0000
Imran Rafique <[email protected]> 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:[email protected]?subject=Unsubscribe