Looking inside a curried function in R (reverse currying?) - r

suppose I have
library(functional)
f = function(x, p) { x^p }
f2 = Curry(f, p=2)
Is there a way to find out what p was set to given only f2?

See if this is useful. Essentially the p argument is carried in the environment of the body of Curry()-ied function:
> body(f2)
do.call(FUN, c(.orig, list(...)))
> body(f2)[[1]]
do.call
> body(f2)[[3]]
c(.orig, list(...))
> body(f2)[[3]][[2]]
.orig
> eval(body(f2)[[3]][[2]])
Error in eval(expr, envir, enclos) : object '.orig' not found
> eval(body(f2)[[3]][[2]], environment(f2) )
$p
[1] 2
As BrodieG comments these could be used in a programming attack on the problem:
> environment(f2)$.orig
$p
[1] 2
> environment(f2)$.orig$p
[1] 2
To see why I didn't stumble upon that initially compare:
> ls( envir=environment(f2) )
[1] "FUN"
> ls( envir=environment(f2) ,all.names=TRUE)
[1] "..." ".orig" "FUN"
The ls function only displays items whose initial characters are not "dots" unless the all.names parameter is set to TRUE.
So this is also imformative:
> environment(f2) $FUN
function(x, p) { x^p }

Related

R: passing values to eval in nested functions

I want to pass some query to lower level function that uses 'eval'. Here's a simplified example:
f1 <- function(x, q) eval(substitute(q), envir=x)
f2 <- function(x, q) f1(x, q)
What's happening:
> x <- data.frame(a=1:5)
> f1(x, a<3)
[1] TRUE TRUE FALSE FALSE FALSE
> f2(x, a<3)
Error in eval(expr, envir, enclos) : object 'a' not found
While I would like f2 to produce the same output like f1. Argument 'q' is some general query that is going to be evaluated on 'x'. I keep the example simple and general but I want to extend it's behavior on more complicated functions and queries. The thing that matters to me is how to "pass" the query "q" so that eval knows what to do with it no matter how many levels of nested functions there were before.
How can I do that? Thanks!
You can do:
f1 <- function(x, q) eval(substitute(q), envir=x)
f2 <- function(x, q) eval(substitute(f1(x, q)))
y <- data.frame(a=1:5)
f1(y, a<3)
f2(y, a<3)
Because you defined just x. You need:
> f2(x, x$a<3)
> [1] TRUE TRUE FALSE FALSE FALSE

Evaluate an expression within an environment inside a function

Consider:
guy <- new.env(FALSE)
guy$stuff <- mean
guy$lib <- library
guy$stole_this_data <- mtcars
ls(guy)
How can I evaluate an expression within an environment inside a function?
For instance I can do with(guy, args(stuff)) to the below and return:
> with(guy, args(stuff))
function (x, ...)
NULL
But within a functon:
foo <- function(env, fun) {
with(env, args(fun))
}
foo(guy, stuff)
## > foo(guy, stuff)
## Error in args(fun) : could not find function "stuff"
Try this:
> foo <- function(env, fun) eval(substitute(args(fun)), env)
> foo(guy, stuff)
function (x, ...)
NULL
ADDED. Regarding the comment below here is an example where zz is not in env or its ancestors (but is in foo2 and in f, the caller of foo2) and it does give a not found error as the comment wished:
> foo2 <- function(env, fun, zz = 1) eval(substitute(fun), env)
> f <- function() { zz <- 100; foo2(guy, zz+1) }
> f()
Error in eval(expr, envir, enclos) : object 'zz' not found
If you want to continue to use the with construct, this is an alternative:
foo <- function(env, fun) {
fun <- substitute(fun)
eval(bquote(with(env, {
.(fun)
})))
}

Passing on an argument from a wrapper to an inner function when argument is allowed to be missing in inner function - possible?

I have a function which has the argument arg which is allowed to be missing. If it is missing it is assigned some value within foo.
foo <- function(x, arg) {
if (missing(arg))
arg <- TRUE
arg
}
I want to write a wrapper that calls foo for several elements of a list using sapply or lapply. And I want to pass on the arg argument as follows.
foo_wrapper <- function(x, arg) {
sapply(x, foo, arg=arg)
}
This will throw an error as arg is not found when it is evaluated within foo_wrapper.
> m <- list(1,2,3)
> foo(m)
[1] TRUE
> foo_wrapper(m)
Error in FUN(X[[1L]], ...) : argument "arg" is missing, with no default
Now, I could use the dots arguments for this purpose, which would work.
foo_wrapper <- function(x, ...) {
sapply(x, foo, ...)
}
> m <- list(1,2,3)
> foo(m)
[1] TRUE
> foo_wrapper(m)
[1] TRUE TRUE TRUE
Still, I would like to know if there is a way to include the arg argument in the wrapper function explicitly, not pass it via the dots argument.
Is there a way?
You could check for whether arg is missing before calling sapply:
foo_wrapper <- function(x, arg)
if(missing(arg)) sapply(x, foo) else sapply(x, foo, arg=arg)
but it's probably cleaner just to use ....

How to get the value of list(...) in R and S functions

I am confused by how list(...) works in R and S-plus. For following code
pp <- function(x, ...) { print( length( list(...)))}
pp(1,,,1)
In S-Plus, it works, but in R, it gives "Error in print(length(list(...))) : argument is missing, with no default"
I am more interest in how this works in R and how to get the value of list(...) in R functions.
I'm not sure why that syntax is allowed in S-plus but not in R.
Here, though, is some R code that will have essentially the same effect:
pp <- function(x, ...) {
print(length(as.list(match.call(expand.dots=FALSE))[["..."]]))
}
pp(1,,,1)
# [1] 3
Alternatively, using a trick from here:
ppp <- function(x, ...) {
print(length(substitute(...())))
}
ppp(1,,,1)
# [1] 3
You cannot use unnamed (edit: ... and missing) arguments in the dots and any arguments after the dots when these arguments are intended to be matched in an arg-list. The positional matching that automatically occurs for unnamed arguments only "works" in the typical argument processing for named arguments(in the arg list) before the dots.
> pp1 <- function(x, ...) { length( list(...))}
> pp1(1,z=NULL,xx=NULL,1)
[1] 3
> pp2 <- function(x, z, ...) { length( list(...))}
> pp2(1,z=NULL,xx=NULL,1)
[1] 2
> pp3 <- function(x, z, ...) { length( list(...))}
> pp3(1, ,xx=NULL,1)
[1] 2
> pp <- function(x, ...) { length( list(...))}
> pp(1, , xx=NULL, 1)
Error in pp(1, , xx = NULL, 1) : argument is missing, with no default
Reading the help page for match.call, the second "commonly used circumstance" is described as:
To pass most of the call to another function, often model.frame. Here the common idiom is that expand.dots = FALSE is used, and the ... element of the matched call is removed.
The sequence of argument matching (when not circumvented) is described in section 4.3.2 "Argument matching":
Positional matching. Any unmatched formal arguments are bound to unnamed supplied arguments, in order. If there is a ‘...’ argument, it will take up the remaining arguments, tagged or not.
If any arguments remain unmatched an error is declared.

binding a function to a list

Where am I missing something?
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-make.FUN(i)
FUN[[1]](1)
If I check FUN assignment I get a reference to a nested function (as expected):
> FUN
[[1]]
function (n)
i + n
<environment: 0x03adfad0>
[[2]]
function (n)
i + n
<environment: 0x03ae0834>
[[3]]
function (n)
i + n
<environment: 0x03ae0604>
>
Problem is that if I check:
> FUN[[1]](1)
[1] 4
>
when I expect 2! (clearly it is overwriting the last value)
On the other hand, if I manually assign for each element of the list:
FUN[[1]]<-make.FUN(1)
FUN[[2]]<-make.FUN(2)
FUN[[3]]<-make.FUN(3)
I get the correct answer:
> FUN[[1]](1)
[1] 2
> FUN[[2]](3)
[1] 5
>
I could workaround using do.call, but I can't realize what the interpreter is assuming in the first loop, or why is do.call mandatory in this case.
When I try:
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-do.call('make.FUN',list(i))
I get (as expected):
> FUN[[1]](2)
[1] 3
Any clue? (it only happens when using lists)
Your question is almost a copy-paste of the force example from the doc. You need to do:
FUN <- list()
make.FUN <- function(i) { force(i); function(n) i+n }
for (i in 1:3) FUN[[i]] <- make.FUN(i)
FUN[[1]](1)
# [1] 2
Relevant details from ?force:
force forces the evaluation of a formal argument. This can be useful if the argument will be captured in a closure by the lexical scoping rules and will later be altered by an explicit assignment or an implicit assignment in a loop or an apply function.

Resources