On 11/10/2015 10:36 PM, Duncan Murdoch wrote:> On 11/10/2015 8:05 PM, Ben Bolker wrote: >> >> 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? >> >> Example: >> >>> f1 <- formula() >>> f2 <- formula() >>> environment(f2) <- new.env() >>> identical(f1,f2) >> [1] FALSE >>> identical(f1,f2,ignore.environment=TRUE) >> [1] FALSE >> >> 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. > >> >> Maybe the problem *is* that I don't know the difference between a >> function and a closure ... ? > > In R, there is no difference. All functions are closures. > > Some people only use "closure" for functions returned as the value of > other functions. That may be correct usage in other languages, but not > in R.Sorry, I meant all user functions are closures. There are other kinds of function in R called "primitives" (e.g. c(), many low level math functions, the functions that implement flow control, etc.). Duncan Murdoch
Duncan Murdoch <murdoch.duncan <at> 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? In the R code base it's used in checkConflicts (to see if a function is re-exported) and in getAnywhere ...
On 12/10/2015 9:51 AM, Ben Bolker wrote:> Duncan Murdoch <murdoch.duncan <at> 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.> > 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