Monday 30 October 2017

What are the differences between "=" and "

itemprop="text">

What are the differences between the
assignment operators = and <- in R?



I know that operators are slightly different,
as this example shows



x <- y
<- 5
x = y = 5

x = y <- 5
x <- y =
5
# Error in (x <- y) = 5 : could not find function
"<-<-"


But is
this the only difference?


itemprop="text">
class="normal">Answer





What are the
differences between the assignment operators = and
<- in
R?





As
your example shows, = and <- have
slightly different operator precedence (which determines the order of evaluation when
they are mixed in the same expression). In fact, href="https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/Syntax"
rel="noreferrer">?Syntax in R gives the following
operator precedence table, from highest to
lowest:





‘->
->>’ rightwards assignment
‘<- <<-’ assignment (right to
left)
‘=’ assignment (right to
left)





But
is this the only difference?



Since you were
asking about the assignment operators: yes, that is the only
difference. However, you would be forgiven for believing otherwise. Even the R
documentation of href="https://www.rdocumentation.org/packages/base/versions/3.5.0/topics/assignOps"
rel="noreferrer">?assignOps claims that there are
more differences:





The operator <- can be used anywhere,

whereas the operator = is only allowed at the top level
(e.g.,
in the complete expression typed at the command prompt) or as
one

of the subexpressions in a braced list of
expressions.




Let’s
not put too fine a point on it: the R documentation is (subtly)
wrong
[ href="http://developer.r-project.org/equalAssign.html"
rel="noreferrer">1]
. This is easy to show: we just need to find
a counter-example of the = operator that isn’t (a) at the top
level, nor (b) a subexpression in a braced list of expressions (i.e. {…;
…}
). — Without further
ado:



x
# Error: object
'x' not found
sum((x = 1), 2)
# [1]
3
x

# [1]
1


Clearly we’ve
performed an assignment, using =, outside of contexts (a) and
(b). So, why has the documentation of a core R language feature been wrong for
decades?



It’s because in R’s syntax the symbol
= has two distinct meanings that get routinely
conflated:




  1. The first
    meaning is as an assignment operator. This is all we’ve talked
    about so far.

  2. The second meaning isn’t an operator but
    rather a syntax token that signals named argument
    passing
    in a function call. Unlike the = operator it
    performs no action at runtime, it merely changes the way an expression is
    parsed.




Let’s
see.



In any piece of code of the general
form …



‹function_name›(‹argname›
= ‹value›,
…)
‹function_name›(‹args›,
‹argname› = ‹value›,
…)


… the
= is the token that defines named
argument passing: it is not the assignment operator. Furthermore,
= is entirely forbidden in some syntactic
contexts:




if
(‹var› =
‹value›) …
while (‹var›
= ‹value›) …
for
(‹var› = ‹value› in
‹value2›) …
for (‹var1› in
‹var2› =
‹value›) …


Any
of these will raise an error “unexpected '=' in
‹bla›”.



In any other context,
= refers to the assignment operator call. In particular, merely
putting parentheses around the subexpression makes any of the above (a) valid, and (b)
an assignment. For instance, the following performs
assignment:




median((x =
1 : 10))


But
also:



if (! (nf = length(from)))
return()


Now
you might object that such code is atrocious (and you may be right). But I took this
code from the base::file.copy function (replacing
<- with =) — it’s a pervasive
pattern in much of the core R
codebase.




The href="http://developer.r-project.org/equalAssign.html" rel="noreferrer">original
explanation by John Chambers, which the the R documentation is probably based
on, actually explains this
correctly:





[= assignment is] allowed in only two places in the
grammar: at the top level (as a complete program or user-typed expression); and when
isolated from surrounding logical structure, by braces or an extra pair of
parentheses.




/>

A confession: I lied earlier. There
is one additional difference between the =
and <- operators: they call distinct functions. By default
these functions do the same thing but you can override either of them separately to
change the behaviour. By contrast, <- and
-> (left-to-right assignment), though syntactically
distinct, always call the same function. Overriding one also
overrides the other. Knowing this is rarely practical href="https://github.com/klmr/functional#a-concise-lambda-syntax"
rel="noreferrer">but it can be used for some fun
shenanigans.


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...