Search                        Top                                  Index
HELP PARTAPPLY                                      A Sloman, April 1985

    partapply(<procedure>, <list>) -> closure

This procedure produces a closure  of an existing procedure (which may
itself be a closure). It takes two arguments - a  procedure and a list;
its result is a new procedure based upon the given procedure, but
requiring fewer arguments, the rightmost of the arguments of the new
procedure being supplied by the values in the list at the time PARTAPPLY
is called.

Some examples are presented in TEACH * PERCENT.

If the procedure being partially applied has an updater then the
resulting closure will have an appropriate updater too. Here is an
example of the use of PARTAPPLY:-

     define f(x,y,z);
         [%x,y,z%]
     enddefine;

     f(1,2,3) =>
     ** [1 2 3]

     f(4,5,6) =>
     ** [4 5 6]

     vars g; partapply(f,[3]) -> g;

     g(1,2) =>
     ** [1 2 3]

     g(4,5) =>
     ** [4 5 3]

     partapply(f,[10 20]) -> g;

     g(4) =>
     ** [4 10 20]

Some 'syntactic sugar' is provided so that

    partapply(f,[3])

can be written as:

    f(%3%)

In fact, both of these make use of the more primitive construct

    consclosure(f,3,1)

described in REF * PROCEDURE

Partial application is a useful technique in a variety of situations.
The most common is to make a general procedure more specific. For
example:

     vars iscolour;
     member(%[red blue green yellow]%) -> iscolour;

     iscolour("red") =>
     ** <true>

     iscolour("apple") =>
     ** <false>

A procedure to find an element of a list satisfying a predicate:

    define findone(list,predicate);
        if  list = []
        then    false
        elseif  predicate(hd(list))
        then    hd(list)
        else    findone(tl(list),predicate)
        endif
    enddefine;

     findone([apple red house], iscolour) =>
     ** red

Special cases of findone can be created by partial application:

     vars getcolour; findone(%iscolour%) -> getcolour;

     getcolour([apple red house]) =>
     ** red

Another use of PARTAPPLY is to ensure that when a procedure P1 using a
variable, say X, is given as argument to another procedure P2, which
also uses the variable X, then when P1 runs inside P2 it doesn't get
P2's value of X, but the value in the caller of P2. For example, try the
following:

    define p2(p1);
        ;;; gives x a value, then runs its argument
        vars x;
        99 -> x;
        p1();
    enddefine;

    define test(x);
        ;;; run p2, giving it a procedure to run
        p2(procedure; x => endprocedure);
        ;;; you might expect this to print the value of x in test
    enddefine;

    test(33);
    ** 99

When P2 is running it has a value for X, so its argument, which uses X
NON-locally, gets the value of X in P2, when it runs inside an
activation of P2. (This is a consequence of local variables using
dynamic binding by default.) To prevent this, define TEST thus, using
partial application:

    define test(x);
        p2(procedure(x); x => endprocedure(%x%))
    enddefine;

    test(33);
    ** 33

The expression

        procedure(x); x => endprocedure(%x%)

creates a POP-11 closure, which is in effect a procedure with a
'built-in' value for X, namely the value X had when the closure was
CREATED, as opposed to the value X has when the closure is RUN. By
contrast the procedure

        procedure; x => endprocedure

gets whatever value X had just before the procedure was run. If the
procedure P2 had been defined using LVARS instead of VARS, it would not
have been necessary to use partial application, since a non-local
variable used in the anonymous procedure in TEST cannot access a
'lexically scoped' variable in procedure P2. But sometimes dynamic
scoping is needed for variables that are accessed non-locally by lots of
procedures, e.g. CUCHAROUT, INTERRUPT, PRMISHAP. Partial application
can be used to freeze the current value of a dynamically scoped variable
into a procedure which is to be called later, using that value.

See REF *PROCEDURES for more detailed information on procedures in
POP-11.

See also HELP
*PERCENT  - summarises the syntax for partial application
*FROZVAL  - to access values frozen into closures
*PDPART   - returns the procedure on which a closure is based
*CLOSURES - on the construction of closures in POP-11
*VARS     - on the use and declaration of dynamically scoped variables
*LEXICAL *LVARS    - on lexically scoped variables

--- C.all/help/partapply -----------------------------------------------
--- Copyright University of Sussex 1988. All rights reserved. ----------