[Rd] Unexpected behaviour when comparing (==) long quoted expressions

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Tue Jul 16 10:35:36 CEST 2019


>>>>> Daniel Chen 
>>>>>     on Fri, 12 Jul 2019 13:53:21 -0500 writes:

    > Hi everyone:
    > I’m one of the interns at RStudio this summer working on a project that 
    > helps teachers grade student code. I found an unexpected behaviour with 
    > the |==| operator when comparing |quote|d expressions.

    > Example 1:

    > |u <- quote(tidyr::gather(key = key, value = value, 
    > new_sp_m014:newrel_f65, na.rm = TRUE)) s <- quote(tidyr::gather(key = 
    > key, value = value, new_sp_m014:newrel_f65, na.rm = FALSE)) u == s # 
    > TRUE u <- quote(tidyr::gather(key = key, value = value, na.rm = TRUE)) s 
    > <- quote(tidyr::gather(key = key, value = value, na.rm = FALSE)) u == s 
    > # FALSE |

Unfortunately the above is almost unreadable, as you "forgot" to
click (in the lower right corner of your Gmail interface with
the three vertical dots) "plain text mode".

    > Example 2:

    > |u <- 
    > quote(f(x123456789012345678901234567890123456789012345678901234567890, 
    > 1)) s <- 
    > quote(f(x123456789012345678901234567890123456789012345678901234567890, 
    > 2)) u == s #> [1] TRUE |

this is even readable after html - de-html mangling

    > Winston Chang pointed out in the help page for |==|:

    > Language objects such as symbols and calls are deparsed to character
    > strings before comparison.

    > and in the source code that does the comparison [1] shows that It 
    > deparses each language object and then only extracts the first element 
    > from the resulting character vector:

    > |SET_STRING_ELT(tmp, 0, (iS) ? PRINTNAME(x) : STRING_ELT(deparse1(x, 0, 
    > DEFAULTDEPARSE), 0)); |

    > Is this a fix that needs to happen within the |==| documentation? or an 
    > actual bug with the operator?

This a good question.

Thank you, Daniel, for providing the link to the source code in
<R>/src/main/relop.c .

Looking at that and its context, I think we (R core) should
reconsider that implementation of '=='  which indeed does about
the same thing as deparse {which also truncates at some point by
default; something very very reasonable for error messages, but
undesirable in other cases}.

But I think it's fair expectation that comparing  calls  ["language"]
with '==' should compare the full call's syntax even if that may
occasionally be very long.

Martin

    > For more context the original issue we had is here: 
    > https://github.com/rstudio-education/grader/issues/28

    > Workaround:

    > You can get around this issue by using |all.equal| or |identical|

    > |u <- quote(tidyr::gather(key = key, value = value, 
    > new_sp_m014:newrel_f65, na.rm = TRUE)) s <- quote(tidyr::gather(key = 
    > key, value = value, new_sp_m014:newrel_f65, na.rm = FALSE)) u == s # 
    > TRUE all.equal(u, s) # "target, current do not match when deparsed" 
    > identical(u, s) # FALSE |

    > Thanks,

    > Dan

    > [1] https://github.com/wch/r-source/blob/e647f78cb85282263f88ea30c6337b77a30743d9/src/main/relop.c#L140-L155



More information about the R-devel mailing list