What are the differences between "=" and "

As noted here the origins of the Commented Dec 12, 2014 at 17:35

9 Answers 9

The difference in assignment operators is clearer when you use them to set an argument value in a function call. For example:

median(x = 1:10) x ## Error: object 'x' not found 

In this case, x is declared within the scope of the function, so it does not exist in the user workspace.

median(x  

In this case, x is declared in the user workspace, so you can use it after the function call has been completed.

library(formatR) tidy_source(text = "x=1:5", arrow = TRUE) ## x  

To understand what is happening, you need to know that assignment silently returns the value that was assigned. You can see that more clearly by explicitly printing, for example print(x

Secondly, it's clearer if we use prefix notation for assignment. So

The parser interprets x

We might expect that x

but actually it gets interpreted as

This is because = is lower precedence than answered Nov 16, 2009 at 14:36 Richie Cotton Richie Cotton 121k 47 47 gold badges 250 250 silver badges 365 365 bronze badges

This is also mentioned in chapter 8.2.26 of The R Inferno by Patrick Burns (Not me but a recommendation anyway)

Commented Jun 14, 2016 at 9:17

I just realised that your explanation of how x Commented Jul 27, 2018 at 11:25

… And I just realised that the very first part of this answer is incorrect and, unfortunately, quite misleading because it perpetuates a common misconception: The way you use = in a function call does not perform assignment, and isn’t an assignment operator. It’s an entirely distinct parsed R expression, which just happens to use the same character. Further, the code you show does not “declare” x in the scope of the function. The function declaration performs said declaration. The function call doesn’t (it gets a bit more complicated with named . arguments).

Commented Apr 12, 2019 at 10:33

@ClarkThomborson The semantics are fundamentally different because in R assignment is a regular operation which is performed via a function call to an assignment function. However, this is not the case for = in an argument list. In an argument list, = is an arbitrary separator token which is no longer present after parsing. After parsing f(x = 1) , R sees (essentially) call("f", 1) . Whereas for x = 1 R sees call("=", "x", 1) . It's true that in both cases name binding also happens but, for the assignment operator, it happens after calling the assignment operator function.

Commented Jan 12, 2023 at 15:35

@JAQuent, the intention wasn't that the expression median(x = 1:10) errors. It is to contrast it to side-effect of median(x Commented Jun 28 at 20:56

Answer recommended by R Language Collective

What are the differences between the assignment operators = and

… ‘-> ->>’ rightwards assignment ‘ 

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 ?assignOps claims that there are more differences:

Let’s not put too fine a point on it: the R documentation is wrong. 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 (even by experts, including in the documentation cited above):

  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.

So how does R decide whether a given usage of = refers to the operator or to named argument passing? 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)) 
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

The 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.

In sum, by default the operators overridden separately to change its behaviour. By contrast, (left-to-right assignment), though syntactically distinct, always call the same function. Overriding one also overrides the other. Knowing this is rarely practical but it can be used for some fun shenanigans.