A tower is equivalent to the Ruby gem Rack's notion of middleware.
tower(functions = list())
functions | list. A list of functions in the tower. The
first argument of each function must be named "object" and
each function must take a |
---|
An S3 "tower" object, which is a callable function
and must be passed the object
as the first argument.
Additional arguments will be passed to the first function
in the tower.
Imagine a function f1
that, in the middle of its processing,
calls another function, f2
, which in the middle of its
processing, calls another function, f3
, and so on.
To construct such a structure from the list of functions
list(f1, f2, ...)
we need to be able to call the
next "inner" function from the previous outer function.
This is accomplished by providing a yield
keyword
which simply calls the next function in the tower.
The purpose of a tower is to modify some primary object
throughout its operation. To this end, an object
keyword
will be provided to each tower function. If object
is
modified prior to a yield
call, the next function in
the tower will receive the modified object.
For composability, every function in a tower should have a
yield
keyword. The last function in the tower will
yield to an identity function that simply returns the object
.
functions <- list( function(object, ...) { object <- object + 1 object <- yield() object + 1 }, function(object, ...) { object <- object * 2 yield() } ) t <- tower(functions) v <- t(1) # This is now 5, since in the tower, we increment object, # Multiply it by 2 in the next function, then increment it # again after receiving the previous function. stopifnot(v == 5)