From murdoch.duncan at gmail.com  Fri Jun 28 12:34:31 2013
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Fri, 28 Jun 2013 06:34:31 -0400
Subject: [Rd] problem with eval(...,
 parent.frame(1L)) when package is not loaded
In-Reply-To: <51CD07D9.7070201@ufl.edu>
References: <51CD07D9.7070201@ufl.edu>
Message-ID: <51CD66B7.60303@gmail.com>

On 13-06-27 11:49 PM, Ben Bolker wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
>    The lmer() function in the lme4 package has some code of the form
>
> mc <- match.call()
> mc[[1]] <- as.name("lFormula")
> lmod <- eval(mc, parent.frame(1L))
>
>    this is a fairly common idiom in R, found e.g. in lm(), used when
> one wants to pass all of the arguments of a function to a different
> function (in the case of lm() it's model.frame()).
>
>    This idiom fails ("error in eval(...) : could not find function
> 'lFormula'") when lme4 is not explicitly loaded, as will happen if one
> uses lme4::lmer(...) to call the function without loading the package,
> or when lmer() is called from within a function that Imports: but does
> not Depend: on lme4.
>
>    A simpler version suggested by Martin Maechler shows that this is a
> generic issue (except that it's unlikely to happen with base R
> functions because the relevant packages _will_ be loaded unless one
> bends over backwards):
>
> R_DEFAULT_PACKAGES=NULL R --vanilla
>> stats::lm(y~x,data=data.frame(1:5,1:5))
> Error in eval(expr, envir, enclos) :
>    could not find function "model.frame"
>
>    I wonder if anyone has encountered this and/or can think of a fix
> (something with setting the enclosing environment appropriately?)  The
> only workarounds we can think of at present are (1) telling
> dependent-package maintainers that they have to use Depends: instead
> of Imports: (which seems to subvert the whole dependency-minimization
> goal of Imports:) or (2) littering our code with lme4:: to make sure
> that the function gets looked for in the right place (ugh).
>
>    See also https://github.com/lme4/lme4/issues/50 .
>
>    Any ideas appreciated.

I believe

mc[[1]] <- lFormula

will mostly solve the problem.  Since your code is evaluating lFormula, 
it will be found.

This will likely lead to ugly error messages if errors occur during 
lFormula (because the call will no longer look like lFormula(...), it 
will look like (function(...) { ... })( ... ).  You can mitigate this by 
using call. = FALSE in your error messages.

If you're saving mc in any of the results of the function, you'll also 
see the ugly display.

The other choice is to use the explicit ::, i.e.

mc[[1]] <- quote(lmer::lFormula)

This would be the solution I'd prefer, but you seem to have some 
prejudice against :: :-).

Duncan Murdoch



[Rd] problem with eval(..., parent.frame(1L)) when package is not loaded
Duncan Murdoch