1

I have a difficulty in learning how to use eval() to evaluate a function,

suppose i have a function:

sq <- function(y){ y**2 }

u can evaluate this function like this:

call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- 0.2
call <- call[c(1,3)]
eval(call)

and it will give u 0.2^2 = 0.04

But if i want to calculate sth like sq(y), where y = sin(x), i may write:

call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- as.name('sin')
call$x <- 0.2
call <- call[c(1,3:4)]
eval(call)

it will give me this error:

Error in sq(y = sin, x = 0.2) : unused argument (x = 0.2)

Seems that R cannot recognize x as an argument of sin, but an argument of sq instead. how can we tell R that x is an argument of sin?

Also, it seems that R is the only language i have learned that uses eval() to evaluate a function (i know C++ and Python, but havent seen that syntax before), what is the different (or advantage) to evaluate a function in this way instead of calling sq(y=sin(x=0.2))?

Is there a good book or tutorial talking about its usage, and when to use between the two ways? Thanks!

PS: the example above is actually a simplified version of the code in mlogit package im studying, in which the log likelihood is returned by calling 'lnl.slogit' and is passed to 'mlogit.optim' and get optimized (Line 407 of https://github.com/cran/mlogit/blob/master/R/mlogit.R). I used the same method as the code in the package to call two functions, but i got the error above.

John
  • 309
  • 3
  • 12

1 Answers1

1

The code is trying to pass:

  • an argument x to sq but sq has no x argument
  • the function sin in argument y but a number is required, not a function.

Try this:

x <- 0.2
cl <- call("sq", y = quote(sin(x)))

cl
## sq(y = sin(x))

eval(cl)
## [1] 0.0394695

or maybe what you want is:

x <- 0.2
cl <- call("sq", y = sin(x))

cl
## sq(y = 0.198669330795061)

eval(cl)
## [1] 0.0394695

or

match.fun("sq")(sin(x))
## [1] 0.0394695

or just:

sq(sin(x))
## [1] 0.0394695

Note that ordinarily you do not have to use eval. Just listing the function with its arguments is enough to evaluate it as the in last line of code.

The regression functions in R internally use non-standard code due to considerations related to environments but ordinarily that would not be needed in other contexts.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • thanks for your answer, but in the mlogit package, it is calling the two functions 'lnl.slogit' and 'mlogit.optim' the same way as my example does, is there any different between the two? why is it working? 'R internally use non-standard code due to considerations related to environments' <-- is there any book that explains why it needs to do that? – John May 17 '18 at 08:24
  • I think you left out the key part in your example which is that it is not `eval(call)` but `eval(call, parent.frame())` so that any expressions that are evaluated take their free variables from the parent frame and not from mlogit's run time environment. – G. Grothendieck May 17 '18 at 08:39