[R] Environmental oddity.

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Sun Nov 7 12:27:25 CET 2021


On 06/11/2021 11:32 p.m., Deepayan Sarkar wrote:
> On Sun, Nov 7, 2021 at 6:05 AM Rolf Turner <r.turner using auckland.ac.nz> wrote:
>>
>>
>> I have two functions which appear to differ only in their environments.
>> They look like:
>>
>>> d1
>>> function (x, mean = 0, sd = 1, log = FALSE)
>>> (((x - mean)/sd)^2 - 1) * if (log) 1 else dnorm(x, mean, sd)/sd
>>> <environment: namespace:stats>
>>
>> and
>>
>>> d2
>>> function (x, mean = 0, sd = 1, log = FALSE)
>>> (((x - mean)/sd)^2 - 1) * if (log) 1 else dnorm(x, mean, sd)/sd
>>
>> Typing "environment(d1)" gives
>>
>>> <environment: namespace:stats>
>>
>> and typing "environment(d2)" gives
>>
>>> <environment: R_GlobalEnv>
>>
>> The d2() function however gives an incorrect result:
>>
>>> d1(1,0,3,TRUE)
>>> [1] -0.2962963
>>> d2(1,0,3,TRUE)
>>> [1] -0.8888889
> 
> It can't be as simple as that. I get the same result (as your d2) with
> the following:
> 
> d <- function (x, mean = 0, sd = 1, log = FALSE) {
>      (((x - mean)/sd)^2 - 1) * if (log) 1 else dnorm(x, mean, sd) / sd
> }
> d(1, 0, 3, TRUE)
> environment(d)
> environment(d) <- as.environment("package:stats")
> d(1, 0, 3, TRUE)
> 
>> In d2() the result of the if() statement does not get divided
>> by the final "sd" whereas in d1() it does (which is the desired/correct
>> result).
>>
>> Of course the code is ridiculously kludgy (it was produced by "symbolic
>> differentiation").  That's not the point.  I'm just curious (idly?) as
>> to *why* the association of the namespace:stats environment with d1()
>> causes it to "do the right thing".
> 
> This sounds like a difference in precedence. The expression
> 
> if (log) 1 else dnorm(x, mean, sd) / sd
> 
> is apparently being interpreted differently as
> 
> d1: (if (log) 1 else dnorm(x, mean, sd)) / sd
> d2: if (log) 1 else (dnorm(x, mean, sd)) / sd)
> 
> It's unclear how environments could affect this, so it would be very
> helpful to have a reproducible example.
> 

Rolf said these were automatically produced functions.  Those don't 
always deparse properly, because manipulating expressions can produce 
things that can never be produced by the parser.  I'm not sure this 
happened in this case.  You'd need to examine the parse trees of d1 and 
d2 to see.

There's also a possibility that the srcref attached to them is lying, 
and we're not seeing the deparsed versions of the functions.  Printing 
removeSource(d1) and removeSource(d2) should reveal that.

Duncan Murdoch



More information about the R-help mailing list