[R] Environmental oddity.

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Sun Nov 7 19:11:10 CET 2021


I've submitted a bug report and patch:

  https://bugs.r-project.org/show_bug.cgi?id=18232

Duncan Murdoch

On 07/11/2021 12:20 p.m., Duncan Murdoch wrote:
> Here's how to construct a similar deparsing error:
> 
> # e1 and e2 are obviously different expressions
> e1 <- quote(5 * if (TRUE) 2 else 3/4)
> e2 <- quote(5 * (if (TRUE) 2 else 3)/4)
> # and they evaluate differently
> eval(e1)
> #> [1] 10
> eval(e2)
> #> [1] 2.5
> 
> # We can make an equivalent version of e2 by messing around in it
> e3 <- e2
> as.list(e3[[c(2,3)]])
> #> [[1]]
> #> `(`
> #>
> #> [[2]]
> #> if (TRUE) 2 else 3
> e3[[c(2,3)]] <- e3[[c(2,3,2)]]
> 
> # Now e3 looks like e1
> e1
> #> 5 * if (TRUE) 2 else 3/4
> e3
> #> 5 * if (TRUE) 2 else 3/4
> 
> # But it doesn't evaluate that way
> eval(e1)
> #> [1] 10
> eval(e3)
> #> [1] 2.5
> 
> Duncan Murdoch
> 
> On 07/11/2021 6:27 a.m., Duncan Murdoch wrote:
>> 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