Hello,

One drawback of the implementations of closures I presented is that since the 
closure is represented as a tuple, it cannot be run via the call word. 
You have to use the call-closure word. One way around this would be to make 
call a method, and then make the closure instances delegate to an underlying 
quotation.

Another way is to simply rewrite quotations. In the most complex case of 
closures with parameters, which is very close to what a function in Scheme 
is, we have to take care of three things:

        Bind parameters
        Run in a new scope
        Keep a copy of the environment

In Scheme you get all three if you want them or not. In Factor you can endow a 
quotation with any composition of the three.

parametric-quot rewrites a quotation so that it takes arguments from the stack 
and binds them. Here is the implementation:

        : set-parameters ( seq -- ) reverse [ set ] each ;

        : parametric-quot ( parameters quot -- quot )
        [ [ swap ] set-parameters [ ] call ] make* ;

Let's turn this quotation:

        [ x> y> z> + + ]

into one which takes x and y as arguments:

        { x y } [ x> y> z> + + ] parametric-quot

The result is:

        [ { x y } set-parameters [ x> y> z> + + ] call ]

Scoping a quotation is the easiest:

        : scoped-quot ( quot -- quot ) [ with-scope ] curry ;

The parametric quotation we generated messes with the namespace that it runs 
in. We can use scoped-quot to fix that. Calling scoped-quot on our 
parametric quotation:

        { x y } [ x> y> z> + + ] parametric-quot scoped-quot

yields the following:

        [ [ { x y } set-parameters [ x> y> z> + + ] call ] with-scope ]

The z value comes from the nearest scope that contains a binding of z. 
Finally, let's preserve the environment in which the quotation is called, 
making this a true closure. This is implemented with closed-quot:

: closed-quot ( quot -- quot )
[ namestack >r [ namestack ] set-namestack [ ] call r> set-namestack ] make* ;

Calling closed-quot on our example yields:

        [ namestack >r # set-namestack
          [ [ { x y } set-parameters [ x> y> z> + + ] call ] with-scope ] call
          r> set-namestack ]

where # represents the preserved environment.

Let's see our quotation in action.


scratchpad H{ } >n      ! Establish a new scope
----------
----------
scratchpad 1 >z         ! Bind z to 1
----------
----------

! Create our closure

scratchpad { x y } [ x> y> z> + + ] parametric-quot scoped-quot closed-quot
----------
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad ndrop        ! Exit from the scope. Our closure is on the stack
----------
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad H{ } >n      ! Establish a new scope
----------
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad 2 >z         ! Bind z to 2
----------
[ namestack >r # set-namestack # call r> set-namestack ]
----------

! Create another closure

scratchpad { x y } [ x> y> z> + + ] parametric-quot scoped-quot closed-quot
----------
[ namestack >r # set-namestack # call r> set-namestack ]
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad ndrop        ! Exit from the scope. Both closures are on the stack.
----------
[ namestack >r # set-namestack # call r> set-namestack ]
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad 10 20 pick call .    ! Call the second closure we created.
32
----------
[ namestack >r # set-namestack # call r> set-namestack ]
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad 10 20 roll call .    ! Call the first closure we created.
31
----------
[ namestack >r # set-namestack # call r> set-namestack ]
----------
scratchpad 

Ed

P.S. The code uses a word called make*:

: make* ( seq -- seq ) [ dup quotation? [ call ] [ ] if ] map ;

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Factor-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/factor-talk

Reply via email to