Re: [Rd] identical(..., ignore.environment=TRUE)
> Duncan Murdoch > on Mon, 12 Oct 2015 19:31:11 -0400 writes: > On 12/10/2015 9:51 AM, Ben Bolker wrote: >> Duncan Murdoch gmail.com> writes: >> BB> > It seems odd/inconvenient to me that the > "ignore.environment" argument of identical() only > applies to closures (which I read as 'functions' -- > someone can enlighten me about the technical > differences between functions and closures if they > like -- see below for consequences of my confusion). > This is certainly not a bug, it's clearly documented, > but it seems like a design flaw. It would certainly > be convenient to be able to ignore differences in > environments when comparing complex objects with lots > of deeply nested formula and terms objects with > environments ... > > Can anyone suggest a reason for this design? > >> >> [snip] >> > Actually, maybe I don't understand how this is > supposed to work since I thought this would be TRUE: > > f1 <- function() {} > f2 <- function() {} > environment(f1) <- new.env() > environment(f2) <- new.env() > identical(f1,f2,ignore.environment=TRUE) ## FALSE Those two functions likely have different srcref attributes. If you created f2 using f2 <- f1, you'd get your expected result. >> >> [snip] >> >> Thanks for the clarification about closures >> vs. functions. >> >> [snip] >> >> You're right that the srcref attributes are different; >> although their bodies are the same, they have their own >> environments that differ. For me, this makes the >> intended use of ignore.environment= even more puzzling; >> given that environments are not ignored recursively >> (that's not exactly what I mean -- I mean ignoring all >> environments of components of an object), I have trouble >> understanding the use case for ignore.environnment ... >> maybe it was developed before srcrefs existed? > I think it simply means "ignore.environment.of.closures", > as the description says, but that's too long to be a > convenient arg name. > Closures have three parts: the formals, the body and the > environment. (Actually, 4 parts: like almost all R > objects, they may also have attributes.) > That arg just says to ignore the environment part when > comparing closures. It doesn't say to ignore environments > in general. For another beat on a dead horse, @ Ben: You could either use options(keep.source = FALSE) in your enviroment such that your functions should not have any 'srcref' attributes anymore, or probably more sensible, use all.equal(f1, f2) rather than identical(f1, f2, ..) which I think should really do what you want [even though it ends up using string comparison after deparse(.) .. about which one can debate... but I don't think we'd want to change all.equal.language() at this point in time]. Martin >> >> In the R code base it's used in checkConflicts (to see if >> a function is re-exported) and in getAnywhere ... >> > I'd say those uses are slightly bogus. You should > generally remember that closures have 3 (or 4) parts, and > not go around comparing only two (or 3) of them. > Duncan Murdoch > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] identical(..., ignore.environment=TRUE)
MM> but I don't think we'd want to MM> change all.equal.language() at this point in time Although it would be nice if all.equal looked at least at attributes of formulas so we did not get results like > form <- y ~ x1 %in% x2 > all.equal(form, terms(form)) [1] TRUE > all.equal(terms(y~x1+x2+Error(x3/x2), specials="Error"), terms(y~x1+x2+Error(x3/x2))) [1] TRUE Bill Dunlap TIBCO Software wdunlap tibco.com On Tue, Oct 13, 2015 at 8:39 AM, Martin Maechler wrote: > > Duncan Murdoch > > on Mon, 12 Oct 2015 19:31:11 -0400 writes: > > > On 12/10/2015 9:51 AM, Ben Bolker wrote: > >> Duncan Murdoch gmail.com> writes: > >> > BB> > > It seems odd/inconvenient to me that the > > "ignore.environment" argument of identical() only > > applies to closures (which I read as 'functions' -- > > someone can enlighten me about the technical > > differences between functions and closures if they > > like -- see below for consequences of my confusion). > > This is certainly not a bug, it's clearly documented, > > but it seems like a design flaw. It would certainly > > be convenient to be able to ignore differences in > > environments when comparing complex objects with lots > > of deeply nested formula and terms objects with > > environments ... > > > > Can anyone suggest a reason for this design? > > > >> > >> [snip] > >> > > Actually, maybe I don't understand how this is > > supposed to work since I thought this would be TRUE: > > > > f1 <- function() {} > > f2 <- function() {} > > environment(f1) <- new.env() > > environment(f2) <- new.env() > > identical(f1,f2,ignore.environment=TRUE) ## FALSE > > Those two functions likely have different srcref > attributes. If you created f2 using f2 <- f1, you'd > get your expected result. > > >> > >> [snip] > >> > >> Thanks for the clarification about closures > >> vs. functions. > >> > >> [snip] > >> > >> You're right that the srcref attributes are different; > >> although their bodies are the same, they have their own > >> environments that differ. For me, this makes the > >> intended use of ignore.environment= even more puzzling; > >> given that environments are not ignored recursively > >> (that's not exactly what I mean -- I mean ignoring all > >> environments of components of an object), I have trouble > >> understanding the use case for ignore.environnment ... > >> maybe it was developed before srcrefs existed? > > > I think it simply means "ignore.environment.of.closures", > > as the description says, but that's too long to be a > > convenient arg name. > > > Closures have three parts: the formals, the body and the > > environment. (Actually, 4 parts: like almost all R > > objects, they may also have attributes.) > > > That arg just says to ignore the environment part when > > comparing closures. It doesn't say to ignore environments > > in general. > > For another beat on a dead horse, @ Ben: > > You could either use options(keep.source = FALSE) in your > enviroment such that your functions should not have any 'srcref' > attributes anymore, > > or probably more sensible, use > > all.equal(f1, f2) rather than identical(f1, f2, ..) > > which I think should really do what you want > [even though it ends up using string comparison after deparse(.) > .. about which one can debate... but I don't think we'd want to > change all.equal.language() at this point in time]. > > Martin > > > >> > >> In the R code base it's used in checkConflicts (to see if > >> a function is re-exported) and in getAnywhere ... > >> > > > I'd say those uses are slightly bogus. You should > > generally remember that closures have 3 (or 4) parts, and > > not go around comparing only two (or 3) of them. > > > Duncan Murdoch > > > __ > > R-devel@r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > [[alternative HTML version deleted]] __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] identical(..., ignore.environment=TRUE)
> William Dunlap > on Tue, 13 Oct 2015 09:12:34 -0700 writes: > MM> but I don't think we'd want to > MM> change all.equal.language() at this point in time > Although it would be nice if all.equal looked at least at attributes of > formulas > so we did not get results like > > form <- y ~ x1 %in% x2 > > all.equal(form, terms(form)) > [1] TRUE > > all.equal(terms(y~x1+x2+Error(x3/x2), specials="Error"), > terms(y~x1+x2+Error(x3/x2))) > [1] TRUE Hmm... of course, you have a very good point So, let me say "Patches are welcome!" (If - they include changes to the *.Rd files [e.g., with an option to remain back-bug-compatible] - are well tested, e.g., run 'make check-all' ) [Yes, I think I know why they probably won't come from you, Bill, unfortunately ..] Martin > Bill Dunlap > TIBCO Software > wdunlap tibco.com > On Tue, Oct 13, 2015 at 8:39 AM, Martin Maechler > wrote: > > > Duncan Murdoch > > > on Mon, 12 Oct 2015 19:31:11 -0400 writes: > > > > > On 12/10/2015 9:51 AM, Ben Bolker wrote: > > >> Duncan Murdoch gmail.com> writes: > > >> > > BB> > > > It seems odd/inconvenient to me that the > > > "ignore.environment" argument of identical() only > > > applies to closures (which I read as 'functions' -- > > > someone can enlighten me about the technical > > > differences between functions and closures if they > > > like -- see below for consequences of my confusion). > > > This is certainly not a bug, it's clearly documented, > > > but it seems like a design flaw. It would certainly > > > be convenient to be able to ignore differences in > > > environments when comparing complex objects with lots > > > of deeply nested formula and terms objects with > > > environments ... > > > > > > Can anyone suggest a reason for this design? > > > > > >> > > >> [snip] > > >> > > > Actually, maybe I don't understand how this is > > > supposed to work since I thought this would be TRUE: > > > > > > f1 <- function() {} > > > f2 <- function() {} > > > environment(f1) <- new.env() > > > environment(f2) <- new.env() > > > identical(f1,f2,ignore.environment=TRUE) ## FALSE > > > > Those two functions likely have different srcref > > attributes. If you created f2 using f2 <- f1, you'd > > get your expected result. > > > > >> > > >> [snip] > > >> > > >> Thanks for the clarification about closures > > >> vs. functions. > > >> > > >> [snip] > > >> > > >> You're right that the srcref attributes are different; > > >> although their bodies are the same, they have their own > > >> environments that differ. For me, this makes the > > >> intended use of ignore.environment= even more puzzling; > > >> given that environments are not ignored recursively > > >> (that's not exactly what I mean -- I mean ignoring all > > >> environments of components of an object), I have trouble > > >> understanding the use case for ignore.environnment ... > > >> maybe it was developed before srcrefs existed? > > > > > I think it simply means "ignore.environment.of.closures", > > > as the description says, but that's too long to be a > > > convenient arg name. > > > > > Closures have three parts: the formals, the body and the > > > environment. (Actually, 4 parts: like almost all R > > > objects, they may also have attributes.) > > > > > That arg just says to ignore the environment part when > > > comparing closures. It doesn't say to ignore environments > > > in general. > > > > For another beat on a dead horse, @ Ben: > > > > You could either use options(keep.source = FALSE) in your > > enviroment such that your functions should not have any 'srcref' > > attributes anymore, > > > > or probably more sensible, use > > > > all.equal(f1, f2) rather than identical(f1, f2, ..) > > > > which I think should really do what you want > > [even though it ends up using string comparison after deparse(.) > > .. about which one can debate... but I don't think we'd want to > > change all.equal.language() at this point in time]. > > > > Martin > > > > > > >> > > >> In the R code base it's used in checkConflicts (to see if > > >> a function is re-exported) and in getAnywhere ... > > >> > > > > > I'd say those uses are slightly bogus. You should > > > generally remember that closures have 3 (or 4) parts, and > > > not go around comparing only two (or 3) of them. > > > > > Duncan Murdoch > > > > > __ > > > R-devel@r-project.org mailing list > > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > >
Re: [Rd] A where() functions that does what exists() does but return the environment when object lives?
On Sat, Oct 10, 2015 at 1:24 AM, Uwe Ligges wrote: > I'd start looking at getAnywhere(). Thanks Uwe, that does indeed provides "where" information. Unfortunately, I don't see how it will allow me to search environments similarly/in the same order as exists/get(..., envir, inherits=TRUE) does it. getAnywhere() will search everything in any order. It's a start though. Cheers, Henrik > > Best, > Uwe > > > On 10.10.2015 01:18, Henrik Bengtsson wrote: >> >> Hi, >> >> exists("foo", inherits=TRUE) check whether an object named "foo" >> exists, and get("foo", inherits=TRUE) retrieves it. I'm looking for a >> similar function to exists() that returns the environment where the >> object "foo" exists, iff at all. If not found, NULL is returned. >> Does that exist? >> >> EXAMPLE #1: >> >>> sample2 <- base::sample >>> env <- where("sample2", inherits=TRUE) >>> env >> >> >> >> Note the difference to: >> >>> obj <- get("sample2", inherits=TRUE) >>> environment(obj) >> >> >> >> >> EXAMPLE #2: >> >>> a <- 1 >>> foo <- function() { b <- 2; list(a=where("a", inherits=TRUE), >>> b=where("b", inherits=TRUE)) } >>> foo() >> >> $a >> >> $b >> >> >>> foo() >> >> $a >> >> $b >> >> >> >> I do understand that I can implement such a function myself, but I >> prefer not to. >> >> Thanks, >> >> Henrik >> >> __ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> > > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] A where() functions that does what exists() does but return the environment when object lives?
Seems easy enough to write yourself: where <- function(x, env = parent.frame()) { if (identical(env, emptyenv())) return(NULL) if (exists(x, envir = env, inherits = FALSE)) return(env) where(x, parent.env(env)) } sample2 <- base::sample where("sample2") #> where("sample") #> where("blah") #> NULL Hadley On Fri, Oct 9, 2015 at 6:18 PM, Henrik Bengtsson wrote: > Hi, > > exists("foo", inherits=TRUE) check whether an object named "foo" > exists, and get("foo", inherits=TRUE) retrieves it. I'm looking for a > similar function to exists() that returns the environment where the > object "foo" exists, iff at all. If not found, NULL is returned. > Does that exist? > > EXAMPLE #1: > >> sample2 <- base::sample >> env <- where("sample2", inherits=TRUE) >> env > > > Note the difference to: > >> obj <- get("sample2", inherits=TRUE) >> environment(obj) > > > > EXAMPLE #2: > >> a <- 1 >> foo <- function() { b <- 2; list(a=where("a", inherits=TRUE), b=where("b", >> inherits=TRUE)) } >> foo() > $a > > $b > > >> foo() > $a > > $b > > > > I do understand that I can implement such a function myself, but I > prefer not to. > > Thanks, > > Henrik > > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel -- http://had.co.nz/ __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] A where() functions that does what exists() does but return the environment when object lives?
On Tue, Oct 13, 2015 at 4:43 PM, Hadley Wickham wrote: > Seems easy enough to write yourself: > > where <- function(x, env = parent.frame()) { > if (identical(env, emptyenv())) > return(NULL) > if (exists(x, envir = env, inherits = FALSE)) > return(env) > where(x, parent.env(env)) > } > > sample2 <- base::sample > where("sample2") > #> And that returns a random environment because I ran it with reprex::reprex(). In interactive use it will return Hadley -- http://had.co.nz/ __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] A where() functions that does what exists() does but return the environment when object lives?
On 13.10.2015 22:39, Henrik Bengtsson wrote: On Sat, Oct 10, 2015 at 1:24 AM, Uwe Ligges wrote: I'd start looking at getAnywhere(). Thanks Uwe, that does indeed provides "where" information. Unfortunately, I don't see how it will allow me to search environments similarly/in the same order as exists/get(..., envir, inherits=TRUE) does it. getAnywhere() will search everything in any order. It's a start though. Ah, in the same order Then you probably need to write some code, but sources of the existing functions should allow for a good start, I believe. Good luck, Uwe Cheers, Henrik Best, Uwe On 10.10.2015 01:18, Henrik Bengtsson wrote: Hi, exists("foo", inherits=TRUE) check whether an object named "foo" exists, and get("foo", inherits=TRUE) retrieves it. I'm looking for a similar function to exists() that returns the environment where the object "foo" exists, iff at all. If not found, NULL is returned. Does that exist? EXAMPLE #1: sample2 <- base::sample env <- where("sample2", inherits=TRUE) env Note the difference to: obj <- get("sample2", inherits=TRUE) environment(obj) EXAMPLE #2: a <- 1 foo <- function() { b <- 2; list(a=where("a", inherits=TRUE), b=where("b", inherits=TRUE)) } foo() $a $b foo() $a $b I do understand that I can implement such a function myself, but I prefer not to. Thanks, Henrik __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] A where() functions that does what exists() does but return the environment when object lives?
Thanks Uwe and thanks Hadley. I ended up implementing: ## Emulates R internal findVar1mode() function ## https://svn.r-project.org/R/trunk/src/main/envir.c where <- function(x, where=-1, envir=if (missing(frame)) { if (where < 0) parent.frame(-where) else as.environment(where) } else sys.frame(frame), frame, mode="any", inherits=TRUE) { tt <- 1 ## Validate arguments stopifnot(is.environment(envir)) stopifnot(is.character(mode), length(mode) == 1L) inherits <- as.logical(inherits) stopifnot(inherits %in% c(FALSE, TRUE)) ## Search while (!identical(envir, emptyenv())) { if (exists(x, envir=envir, mode=mode, inherits=FALSE)) return(envir) if (!inherits) return(NULL) envir <- parent.env(envir) } NULL } Here where() provides the same arguments as exists() and get(). It turns out one needs to tweak the default value for 'envir' argument in order work the same. One could argue that where() should always return an environment, i.e. it should return emptyenv() instead of NULL if the object was not found. On the other hand, it's easier to test for is.null(env) than identical(env, emptyenv()). /Henrik On Tue, Oct 13, 2015 at 2:44 PM, Hadley Wickham wrote: > On Tue, Oct 13, 2015 at 4:43 PM, Hadley Wickham wrote: >> Seems easy enough to write yourself: >> >> where <- function(x, env = parent.frame()) { >> if (identical(env, emptyenv())) >> return(NULL) >> if (exists(x, envir = env, inherits = FALSE)) >> return(env) >> where(x, parent.env(env)) >> } >> >> sample2 <- base::sample >> where("sample2") >> #> > > And that returns a random environment because I ran it with > reprex::reprex(). In interactive use it will return R_GlobalEnv> > > Hadley > > -- > http://had.co.nz/ __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel