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.tur...@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
______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.