[See below for full email trail-- Outlook has beaten me into submission] > I ran into this and found the result very surprising:
> identical( quote({ a }), quote({ a }) ) # FALSE > <<...>> > -Winston > > Yes, looks like srcrefs are to blame: > > > > x <- quote({ a }) > > y <- quote({ a }) > > > > identical(x, y) > > # [1] FALSE > <<...>> > > Maybe identical() needs an ignore.srcref option? Normally when > > comparing expressions or functions, you want to compare the code, not > > it's textual representation. > > > > Hadley What a great gotcha! Seems to me it would be better to leave 'identical' alone and have a wrapper that you can call to strip any srcrefs. There is already 'utils::removeSource' but it doesn't work as-is with non-functions. The 5-minute hack below solves the particular example, but may well fall over with other cases--- not tested. (This sort of thing reinforces my own feelings about 'srcref' as opposed to nice simple 'source'...) Mark Bravington CSIRO/Marine Lab/Hobart/Tas 7000/Australia rmsrc <- function (fn) { # based on utils::removeSource is.fun <- is.function( fn) if( (!is.fun && !is.language(fn)) || is.primitive(fn)) { return(fn) } attr(fn, "source") <- NULL attr(fn, "srcref") <- NULL if( !is.fun) { fn <- as.function( list( fn)) } attr(body(fn), "wholeSrcref") <- NULL attr(body(fn), "srcfile") <- NULL recurse <- function(part) { attr(part, "srcref") <- NULL if (is.language(part) && is.recursive(part)) { for (i in seq_along(part)) part[[i]] <- recurse(part[[i]]) } part } body(fn) <- recurse(body(fn)) if( !is.fun) { return( body( fn)) } else { return( fn) } } #> identical( rmsrc( quote({a})), rmsrc( quote({a}))) #[1] TRUE > -----Original Message----- > From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org] > On Behalf Of Winston Chang > Sent: Thursday, 30 October 2014 7:59 AM > To: Hadley Wickham > Cc: R Devel List > Subject: Re: [Rd] Unexpected behavior of identical() with language objects > > Ah, I was using identical() to compare two function bodies. It returns > FALSE even when you remove srcrefs from the body: > > f1 <- function(x) { > if (TRUE) { x } > } > f2 <- function(x) { > if (TRUE) { x } > } > f1b <- body(f1) > f2b <- body(f2) > attributes(f1b) <- NULL > attributes(f2b) <- NULL > > # The bodies look the same with str() > str(f1b) > # language { if (TRUE) {; x; } } > str(f2b) > # language { if (TRUE) {; x; } } > > identical(f1b, f2b) > # FALSE > > > > What I didn't realize was that the curly brace inside the body also > independently captures srcrefs, but this isn't printed with str(f1b). > However, str() on a more targeted part of the object reveals them: > str(f1b[[2]][[3]]) > # length 2 { x } > # - attr(*, "srcref")=List of 2 > # ..$ :Class 'srcref' atomic [1:8] 2 13 2 13 13 13 2 2 > # .. .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' > <environment: 0x452b2c0> > # ..$ :Class 'srcref' atomic [1:8] 2 15 2 15 15 15 2 2 > # .. .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' > <environment: 0x452b2c0> > # - attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: > 0x452b2c0> > # - attr(*, "wholeSrcref")=Class 'srcref' atomic [1:8] 1 0 2 17 0 17 1 2 > # .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' > <environment: 0x452b2c0> > > -Winston > > On Wed, Oct 29, 2014 at 3:46 PM, Hadley Wickham <h.wick...@gmail.com> > wrote: > >>> Is this expected behavior? I can't seem to find anything in the help > >>> for identical that relates to this. > >>> > >> It's not in ?identical, but ?Paren gives you some pointers. > >> str(quote((a))) and str(quote({a})) are also informative. > > > > Yes, looks like srcrefs are to blame: > > > > x <- quote({ a }) > > y <- quote({ a }) > > > > identical(x, y) > > # [1] FALSE > > > > attr(x, "srcref") <- NULL > > attr(x, "srcfile") <- NULL > > attr(x, "wholeSrcref") <- NULL > > > > attr(y, "srcref") <- NULL > > attr(y, "srcfile") <- NULL > > attr(y, "wholeSrcref") <- NULL > > identical(x, y) > > # [1] TRUE > > > > Maybe identical() needs an ignore.srcref option? Normally when > > comparing expressions or functions, you want to compare the code, not > > it's textual representation. > > > > Hadley > > > > -- > > http://had.co.nz/ > > ______________________________________________ > 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