I have been an enthusiastic user of R's purrr package for quite a while and recently ran into a question regarding purrr::partial. Suppose I define a two-argument function
f <- function(x, y) x + y
and partialize it by setting the y argument to some global variable's value:
yy <- 1
fp <- partial(f, y = !!yy)
fp(3) # 3 + 1 = 4
Unquoting yy (that is, using y = !!yy as opposed to y = yy) causes yy to be evaluated only once when fp is created; in particular, modifying yy after this step does not alter fp:
yy <- 2
fp(3) # still: 3 + 1 = 4
Here is my question: What exactly does partial do after evaluating yy? -- I see two possibilities:
- The value of
yyis "hard-wired" into the body offp, meaning that it is not passed as an argument whenfpis called. - The value of
yyis more or less treated as if it was theyargument's default value (without the option of overriding the default), meaning thatfpinternally callsf(or a copy of it) to which the value ofyyis silently passed as an argument matched withy. In this casefpis no more than a syntactic wrapper aroundf.
Trying to explore the second possibility I modfied the definition of f after defining fp. This does not alter fp, meaning that fp does not contain any outside reference to f; however, this does not rule out the (theoretical) possibility of fp containing a copy of the old version of f. (Conclusion: This approach does not help.)
Some practical background to motivate my question: In my current project I have defined lots of functions that use (a) arguments varying from call to call, (b) arguments representing "configuration data" or "domain knowledge". The data matched with the (b) arguments (which may be considerable amounts of data) do not change from call to call, but may change when I commit an update; in any case I believe this data should not be hard-coded in my functions. My strategy is to read the configuration data from some files at start-up time and integrate it into my functions by partializing the arguments in (b). Applying the partialized functions via purrr::pmap to some tibbles turned out to be kind of slow, which made me suspect that the configuration data may still be passed when the function is called -- hence my question. (If anyone has some thoughts on the "partialization strategy" briefly described above, I will be keenly interested in these, too.)