I ran into this and found the result very surprising:
identical( quote({ a }), quote({ a }) )
# FALSE
It seems related to curly braces. For example, parens work fine:
identical( quote(( a )), quote(( a )) )
# TRUE
Is this expected behavior? I can't seem to find anything in the help
for identical that relates to this.
-Winston
Unexpected behavior of identical() with language objects
7 messages · Winston Chang, Joshua Ulrich, Lorenz, David +3 more
On Wed, Oct 29, 2014 at 3:26 PM, Winston Chang <winstonchang1 at gmail.com> wrote:
I ran into this and found the result very surprising:
identical( quote({ a }), quote({ a }) )
# FALSE
It seems related to curly braces. For example, parens work fine:
identical( quote(( a )), quote(( a )) )
# TRUE
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.
-Winston
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Joshua Ulrich | about.me/joshuaulrich FOSS Trading | www.fosstrading.com
Fascinating! I tried the comparisons with all.equal(), expecting a description of the difference, but TRUE was returned in both cases. Dave On Wed, Oct 29, 2014 at 3:26 PM, Winston Chang <winstonchang1 at gmail.com> wrote:
I ran into this and found the result very surprising:
identical( quote({ a }), quote({ a }) )
# FALSE
It seems related to curly braces. For example, parens work fine:
identical( quote(( a )), quote(( a )) )
# TRUE
Is this expected behavior? I can't seem to find anything in the help
for identical that relates to this.
-Winston
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
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
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.wickham at 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/
[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-bounces at r-project.org [mailto:r-devel-bounces at 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.wickham at 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 at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
On 29/10/2014, 6:22 PM, Mark.Bravington at csiro.au wrote:
[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.
Sounds like utils::removeSource may need to be fixed, but until today I'd never heard any complaints about it.
(This sort of thing reinforces my own feelings about 'srcref' as opposed to nice simple 'source'...)
Nice simple 'source' can't do what srcrefs can do, for example report on locations during debugging, or when run-time errors occur. Duncan Murdoch
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-bounces at r-project.org [mailto:r-devel-bounces at 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.wickham at 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 at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel