I understand why the following happens ($.proto delegates to get, which ascends the parent hierarchy up to globalenv()), but I still find it anti-intuitive: > z <- 1 > y <- proto(a=2) > y$z [1] 1 Although this is well-documented behavior; wouldn't it uphold the principle of least surprise to inherit instead from baseenv() or emptyenv()? (See attached patch.) Spurious parent definitions have already been the source of bizarre bugs, prompting me to use proto like this: > z <- 1 > y <- proto(baseenv(), a=2) > y$z Error in get(x, env = this, inherits = inh) : object 'z' not found It's cumbersome, but it ensures that parent definitions don't pollute my object space; I would rather that be the default behaviour, though.
Wow, thanks for the heads-up. That is horrible behavior. But using baseenv() doesn't seem like the solution either. I'm new to proto, but it seems like this is also a big drawback:> z <- 1 > proto(baseenv(), expr={a=z})$aError in eval(expr, envir, enclos) : object "z" not found -- Ben ----------------- Original message ----------------- From: Peter Danenberg <pcd at roxygen.org> To: r-devel at r-project.org Date: Wed, 24 Feb 2010 22:38:54 -0600 I understand why the following happens ($.proto delegates to get, which ascends the parent hierarchy up to globalenv()), but I still find it anti-intuitive: > z <- 1 > y <- proto(a=2) > y$z [1] 1 Although this is well-documented behavior; wouldn't it uphold the principle of least surprise to inherit instead from baseenv() or emptyenv()? (See attached patch.) Spurious parent definitions have already been the source of bizarre bugs, prompting me to use proto like this: > z <- 1 > y <- proto(baseenv(), a=2) > y$z Error in get(x, env = this, inherits = inh) : object 'z' not found It's cumbersome, but it ensures that parent definitions don't pollute my object space; I would rather that be the default behaviour, though. ______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Quoth Ben Escoto on Sweetmorn, the 56th of Chaos:> I'm new to proto, but it seems like this is also a big drawback: > > > z <- 1 > > proto(baseenv(), expr={a=z})$a > Error in eval(expr, envir, enclos) : object "z" not foundOuch, good point; it may be that parent pollution is the lesser of two evils, then. It's a little bit of a catch 22, it seems; because even if you ascend up the parent hierarchy until you hit a non-prototype, the first environment that has `a' also has `z': > library(proto) > get.proto <- function(x, env) { + print(list(env=env, + ls=ls(env, all.names=TRUE))) + if (is.proto(env)) + tryCatch(get(x, env=env, inherits=FALSE), + error=function(e) get.proto(x, env$.super)) + else + stop(sprintf('object \'%s\' not found', x)) + + } > > (function() { z <- 1; get.proto('a', proto(eval={a=z})) })() $env <environment: 0x1d12180> attr(,"class") [1] "proto" "environment" $ls [1] ".super" ".that" "eval" $env <environment: 0x1d12918> $ls [1] "a" "z" Error in get.proto(x, env$.super) : object 'a' not found > So, even if the $ environment diverged, say, from the eval environment; the first relevant environment is already polluted. It almost seems like you have to choose between eval and parent pollution (unless I'm missing something).