Author: John Mount, Win-Vector LLC
Date: 2023-08-19

# wrapr_applicable

#### John Mount, Win-Vector LLC

#### 2023-08-19

`wrapr` includes de-referencing, function evaluation, and a new concept called `"wrapr_applicable"`. `"wrapr_applicable"` is dispatch by type of right hand side argument scheme.

## Basic `wrapr`

The `wrapr` pipe operators (`%.>%` and `%>.%`) are roughly defined as: `a %>.% b ~ { . <- a; b };`. This works under the assumption that `b` is an expression with free-instances of “`.`”. A typical use is:

    library("wrapr")

    5 %.>% sin(.)
    #> [1] -0.9589243

The above is performed by standard `S3` dispatch on the left argument of an exported generic functions called `apply_left()` and `apply_right()`. A formal description of `wrapr` piping can be found here.

## Dereferencing and function evaluation

`wrapr` works primarily over expressions and “`.`”. `wrapr` does tries to de-reference names found in the right-hand side of pipe stages, and also dispatches functions. One can also write the following.

    5 %.>% sin
    #> [1] -0.9589243
    5 %.>% base::sin
    #> [1] -0.9589243

## `"wrapr_applicable"`

Arbitrary objects ask `wrapr` to treat them as special expressions by overriding one or more of `apply_left()` and `apply_right()` for the `S3` class they wish managed.

For example:

    function_reference <- list(f = sin)
    class(function_reference) <- c("wrapr_applicable", "ourclass")

    apply_right.ourclass <- function(pipe_left_arg,
                                     pipe_right_arg,
                                     pipe_environment,
                                     left_arg_name,
                                     pipe_string,
                                     right_arg_name) {
      pipe_right_arg$f(pipe_left_arg)
    }

    function_reference
    #> $f
    #> function (x)  .Primitive("sin")
    #>
    #> attr(,"class")
    #> [1] "wrapr_applicable" "ourclass"

    5 %.>% function_reference
    #> [1] -0.9589243

    function_reference$f <- sqrt
    5 %.>% function_reference
    #> [1] 2.236068

The signature arguments work as follows:

- `pipe_left_arg`: The value moving down the pipeline.
- `pipe_right_arg`: The right pipeline operator (essentially “`self`” or “`this`” in object oriented terms, used for `S3` dispatch).
- `pipe_environment`: The environment the pipeline is working in (not usually needed).
- `left_arg_name`: If the left arguement was passed in by name, what that name was.
- `pipe_string`: The name of the pipe operator (not usually needed).
- `right_arg_name`: If the right arguement was passed in by name, what that name was.

This functionality allows arbitrary objects to directly specify their intended pipeline behavior.

Let’s use a debugging function to see the values of all of the arguments.

    apply_right.ourclass <- function(pipe_left_arg,
                                     pipe_right_arg,
                                     pipe_environment,
                                     left_arg_name,
                                     pipe_string,
                                     right_arg_name) {
      print("pipe_left_arg")
      print(pipe_left_arg)
      print("pipe_right_arg")
      print(pipe_right_arg)
      print("pipe_environment")
      print(pipe_environment)
      print("left_arg_name")
      print(left_arg_name)
      print("pipe_string")
      print(pipe_string)
      print("right_arg_name")
      print(right_arg_name)
      pipe_right_arg$f(pipe_left_arg)
    }

    5 %.>% function_reference
    #> [1] "pipe_left_arg"
    #> [1] 5
    #> [1] "pipe_right_arg"
    #> $f
    #> function (x)  .Primitive("sqrt")
    #>
    #> attr(,"class")
    #> [1] "wrapr_applicable" "ourclass"
    #> [1] "pipe_environment"
    #> <environment: R_GlobalEnv>
    #> [1] "left_arg_name"
    #> NULL
    #> [1] "pipe_string"
    #> [1] "%.>%"
    #> [1] "right_arg_name"
    #> function_reference
    #> [1] 2.236068

    a <- 5

    a %.>% function_reference
    #> [1] "pipe_left_arg"
    #> [1] 5
    #> [1] "pipe_right_arg"
    #> $f
    #> function (x)  .Primitive("sqrt")
    #>
    #> attr(,"class")
    #> [1] "wrapr_applicable" "ourclass"
    #> [1] "pipe_environment"
    #> <environment: R_GlobalEnv>
    #> [1] "left_arg_name"
    #> a
    #> [1] "pipe_string"
    #> [1] "%.>%"
    #> [1] "right_arg_name"
    #> function_reference
    #> [1] 2.236068

## Conclusion

`wrapr` values (left-hand sides of pipe expressions) are completely general. `wrapr` operators (right-hand sides of pipe expressions) are primarily intended to be expressions that have “`.`” as a free-reference. `wrapr` can also be used with right-hand sides that are function references or with arbitrary annotated objects.