Wrapped Subroutines

Sometimes you might want to wrap extra functionality around a subroutine that was already defined (perhaps in a standard module), but still call it with the same name. The .wrap method is similar to the .assuming method, but more powerful. It takes a subroutine reference as an argument and returns an ID object. Inside the subref wrapper, the call statement marks the point where the original subroutine will be executed.

$id = &subname.wrap ({
    # preprocess arguments
    # or execute additional code
    call;
    # postprocess return value
    # or execute additional code
})

subname( . . . ); # call the wrapped subroutine

By default, the inner subroutine is passed the same arguments as the wrapping subroutine, and the wrapping subroutine returns the same result as the inner subroutine. You can alter the arguments passed to the inner subroutine by adding an explicit argument list to call, and alter the outer return value by capturing the result from call and explicitly returning a value in the wrapper.

$id = &subname.wrap (sub (*@args) {
    # preprocess arguments
    $result = call('modified', 'arguments');
    # postprocess return value
    return $result;
})

A subroutine can have multiple wrappers at the same time. Each new wrapper wraps around the previous one, and the outermost wrapper executes first. The ID object returned by .wrap allows the .unwrap method to remove a specific wrapper:

&subname.unwrap($id);

If you’d rather not manually unwrap your sub, wrap a temped version instead. The ...

Get Perl 6 and Parrot Essentials, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.