[R] 'with' usage question
Thomas Lumley
tlumley at u.washington.edu
Thu Oct 7 22:06:39 CEST 2004
On Thu, 7 Oct 2004, RenE J.V. Bertin wrote:
> On Thu, 07 Oct 2004 13:17:02 -0400, "Roger D. Peng" <rpeng at jhsph.edu> wrote regarding "Re: [R]
> 'with' usage question"
>
> 8-) I think what's happening is that the function aov.SS1 will look up
> 8-) variables in the environment in which it was *defined*, which in your
> 8-) case (I'm guessing) is the global environment/workspace. Therefore,
> 8-) if `speed' and `Subject' are not defined in the global environment,
> 8-) they will not be found.
>
>
> If you take that to the letter, doesn't it mean that attach() and
> detach() couldn't have the effect they have? Which is, in fact and if
> memory serves me well, much like the Pascal 'with' operator.
No. attach() attaches the data frame to the search path after the global
environment. So variables in an attached data frame are always available
(but may be overridden by variables in the global environment). attach()
is superficially like with(), but not exactly the same. If you define
with_attach <-function(data, expr){
attach(data)
on.exit(detach(data))
eval(substitute(expr), parent.frame())
}
it would behave more as you expected in this case. Inside a function this
is not as good as with() because variables in the data frame can be
overriden by local variables.
> A
> (possible) counter argument: aov.SS1() used T and F as the usual
> abbreviations for TRUE and FALSE: these are defined in the global
> environment. Now my dataframes also contain a variable T: it took me
> quite a while to realise that this variable (which I in fact never use
> directly) would override the T constant/operator and cause hard-to-trace
> error messages.
and that's why R CMD check tells you not to use T/F for TRUE/FALSE
> I'm trying to find some analogy. with() extends the current environment
> with the variables in the given dataframe, but does not create a C-like
> scope. Rather, it functions more or less like a Bourne shell script: the
> new variables are not 'exported' to be available to code evoked from
> within that new environment, unless they were specifically passed as
> arguments.
It does create a new scope, as in C. The variables are not available
inside functions called from that scope, because variables are never
exported to functions called from a given scope. The same is true in C:
variables will not be exported to functions *called from* a given block
unless they are explicitly passed as arguments.
The reason many people expect variables to be available in functions
called from a given scope ("dynamic scoping") is that variables in the
global workspace are available in functions called from the global
workspace. But this is just a coincidence: the variables are available
because the function is *defined* in the global workspace (or in an
environment that includes the global workspace). Where it is called from
is irrelevant.
It is also initially confusing that having a default argument value is
different from giving exactly the same expression as the actual argument
value. This is also for a good reason: it is important for default
arguments to be able to depend on other argument values. This means they
have to be evaluated in an environment where the other formal arguments
are available -- inside the function
So in your example
with( data, aov.SS1( y=Obs, indep=speed, fSnr=Subject ) )
works, because actual arguments are evaluated in the calling environment,
which is inside with(), where speed and Subject are available.
with( data, aov.SS1( y=Obs))
doesn't work because indep=speed and fSnr=Subject are evaluated inside
aov.SS1, where speed and Subject aren't available.
> Which still doesn't explain why ls() sees everything when
> called within a with() statement...
>
Yes, it does. If ls() is used inside with() it sees the scope defined by
with(), but if it is called inside a function called from with() it sees
the environment inside that function: eg
> with(trees, ls())
[1] "Girth" "Height" "Volume"
> f<-function() ls()
> with(trees, f())
character(0)
-thomas
More information about the R-help
mailing list