What are the differences between "=" and "<-" assignment operators?
Asked Answered
T

9

955

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?

Teetotum answered 16/11, 2009 at 12:14 Comment(1)
As noted here the origins of the <- symbol come from old APL keyboards that actually had a single <- key on them.Hershelhershell
C
265

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, ?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 ?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 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))

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 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 <- and = do the same thing. But either of them can be overridden separately to change its 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 but it can be used for some fun shenanigans.

Corkhill answered 27/7, 2018 at 19:17 Comment(10)
About the precedence, and errors in R's doc, the precedence of ? is actually right in between = and <-, which has important consequences when overriding ? , and virtually none otherwise.Leduc
@Moody_Mudskipper that’s bizarre! You seem to be right, but according to the source code (main/gram.y), the precedence of ? is correctly documented, and is lower than both = and <-.Corkhill
I like your explanation of R semantics... which I'd rephrase as follows. The "=" operator is overloaded. Its base semantics is to bind a formal name to an actual parameter in the arglist of a function call. In most (but not all!) contexts outside a function call, it has the same semantics as "<-": it binds a name to an existing object (or to a constant value), with copy-on-write semantics, with the side-effect of defining this name if it is currently undefined. In a few contexts, it is bound to stop() to warn naive or careless users who confuse it with the "==" operator.Teletypesetter
@ClarkThomborson I don't agree with calling one of the meanings the "base" semantics, because this implies a hierarchy that doesn't exist. And I think it's confusing to call = an overloaded operator, as well: the term "operator" in R has (until R 4.0, at least!) a specific meaning referring to a function call with special syntactic rules. This isn't what = is doing when used to bind a name to an parameter name inside a function call argument list. There's no call happening, so = in this context is just a syntactic token (like ;), not an operator.Corkhill
I'm a newbie to R... had used S for a project about 30 years ago... and I'm still trying to get my head around its semantics! I tell myself stories about them, then find errors in the stories. My current understanding is that R, like most scripting languages, and like all natural languages, has a very complex semantics which varies with the context and has developed over time. We can still interpret historic documents and dusty-deck R scripts pretty accurately if we interpret them in an appropriate (historic) context. A formal semantics is more likely to confuse than to explain....Teletypesetter
I don't find it helpful to think of = as sometimes being a token, and sometimes being a full-fledged assignment operator. To my way of thinking, <- is also a token... and it's the tokenization phase of parsing that makes "x<-3" problematic. The operation of binding a formal name to a value in a function call occurs at the time the function call is being interpreted. The name-value binding (and the possible name-definition) of x <- 3 occurs at the time this expression is being interpreted. There is a temporal distinction between = and <- but it has to do with operator precedence.Teletypesetter
@ClarkThomborson Regardless of whether you find it helpful, that's precisely what it is: the syntactic = token for named parameters completely vanishes after the parsing phase, it isn't represented in the parse tree at all, nor is it evaluated. Name binding in assignment and in function calling happens fundamentally differently in R (and, to varying extents, in other languages), it isn't merely a "temporal distinction", nor is it due to operator precedence.Corkhill
Oh wow that's very helpful. I had guessed -- apparently incorrectly -- that the binding of formal name to actual parameter happened at runtime in R. That'd be a significant gain in efficiency of interpretation, with some loss of semantic range compared to a scripting language which binds formal names to values at runtime. So... my new "story" about the semantics of = and <- is that, in some contexts, = denotes a name-value binding that is interpreted immediately after the script is parsed, and in other contexts its name-value binding is delayed.Teletypesetter
@Clark I am not really sure what you mean by that. Of course the binding happens at runtime. It just doesn't happen via an operator (which, in R, is a function call!), it doesn't happen differently whether or not an explicit parameter name is specified (i.e. whether or not = is present in the source code), and the = token for parameter name binding is not present in the parse tree (compare as.list(str2lang('x = 1')) and as.list(str2lang('f(x = 1)'))).Corkhill
Let us continue this discussion in chat.Corkhill
L
806

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 <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

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


There is a general preference among the R community for using <- for assignment (other than in function signatures) for compatibility with (very) old versions of S-Plus. Note that the spaces help to clarify situations like

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

Most R IDEs have keyboard shortcuts to make <- easier to type. Ctrl + = in Architect, Alt + - in RStudio (Option + - under macOS), Shift + - (underscore) in emacs+ESS.


If you prefer writing = to <- but want to use the more common assignment symbol for publicly released code (on CRAN, for example), then you can use one of the tidy_* functions in the formatR package to automatically replace = with <-.

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

The answer to the question "Why does x <- y = 5 throw an error but not x <- y <- 5?" is "It's down to the magic contained in the parser". R's syntax contains many ambiguous cases that have to be resolved one way or another. The parser chooses to resolve the bits of the expression in different orders depending on whether = or <- was used.

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 <- 2 + 3).

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

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

The parser interprets x <- y <- 5 as

`<-`(x, `<-`(y, 5))

We might expect that x <- y = 5 would then be

`<-`(x, `=`(y, 5))

but actually it gets interpreted as

`=`(`<-`(x, y), 5)

This is because = is lower precedence than <-, as shown on the ?Syntax help page.

Luik answered 16/11, 2009 at 14:36 Comment(11)
This is also mentioned in chapter 8.2.26 of The R Inferno by Patrick Burns (Not me but a recommendation anyway)Noeminoesis
I just realised that your explanation of how x <- x = 5 gets interpreted is slightly wrong: In reality, R interprets it as ​`<-<-`(x, y = 5, value = 5) (which itself is more or less equivalent to tmp <- x; x <- `<-<-`(tmp, y = 5, value = 5)). Yikes!Corkhill
… 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).Corkhill
It seems to me that the "=" operator in the arguments of function call has pretty-much the same semantics as it does outside the arglist. In both contexts, it is binding a name to an object. In both contexts, there's a copy-on-write semantics, whereby any change to the object under its "new" name will cause the object to be copied (except in the case of a data.table). In both cases, there's plenty of room for semantic confusion about whether the copy will be "deep" or "shallow". But... semantics in R is like grammar in English, in that it's a convenience rather than a formality.Teletypesetter
What output would you expect from this? f1 <- function(b = ifelse( ("b" %in% ls()), b, b<-0), x = x <- b + 100) { b <<- b + x + 1000 return(b) } f1() Hint: All assignment operators (AFAIK!) will bind the name on the LHS to a promise on the RHS, but ... depending on the particular operator and its context... the promise might be evaluated immediately or at some later date; the binding might be completed at parse-time (e.g. in a function call), or at runtime; and the name-lookup may occur in different environments. Yeah as if that answer will help anyone ;-)Teletypesetter
@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.Corkhill
@Konrad Rudolph I think we're differing on our definition of the boundary between "syntax" and "semantics". It's an unclear boundary in the case of any interpreted language, such as R, which allows a string of characters to be passed to the parser, at runtime, and then executed. R goes one step further than most interpreted languages, by allowing a running code to modify its own parse tree! Much of the wizardry in 'data.table' involves such modification. If R had a formal syntax, I think the argument list of a method-call would be a string whose final semantics is defined at runtime.Teletypesetter
@ClarkThomborson I don’t follow. R has a formal syntax. And while I agree that R’s ability to transform unevaluated expressions at runtime is pretty cool, it doesn’t come into play here. I merely borrowed the call syntax to format the R parse tree in a readable way for the comment, in order to illustrate that the = token in argument assignment does not lead to a function call action at runtime in the way that assignment does (see our previous discussion in chat).Corkhill
FYI the Jupyter notebook uses the same shortcut for <- as RStudio. (In Jupyter lab you need an extension or tweak the settings yourself.)Gaza
At least in R version 4.2.2, median(x = 1:10) doesn't produce an error anymore.Transubstantiate
@Transubstantiate Good catch! I tested, and even as far back as R 3.6 it didn’t. No idea whether it ever did (the NEWS files don’t contain any relevant change to the function as far back all the way back, and the error message shown here doesn’t match what would happen if median() didn’t have a formal argument named x). This answer is unfortunately riddled with small inaccuracies, and since it’s the highest-voted answer here it’s prone to misleading people.Corkhill
C
265

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, ?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 ?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 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))

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 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 <- and = do the same thing. But either of them can be overridden separately to change its 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 but it can be used for some fun shenanigans.

Corkhill answered 27/7, 2018 at 19:17 Comment(10)
About the precedence, and errors in R's doc, the precedence of ? is actually right in between = and <-, which has important consequences when overriding ? , and virtually none otherwise.Leduc
@Moody_Mudskipper that’s bizarre! You seem to be right, but according to the source code (main/gram.y), the precedence of ? is correctly documented, and is lower than both = and <-.Corkhill
I like your explanation of R semantics... which I'd rephrase as follows. The "=" operator is overloaded. Its base semantics is to bind a formal name to an actual parameter in the arglist of a function call. In most (but not all!) contexts outside a function call, it has the same semantics as "<-": it binds a name to an existing object (or to a constant value), with copy-on-write semantics, with the side-effect of defining this name if it is currently undefined. In a few contexts, it is bound to stop() to warn naive or careless users who confuse it with the "==" operator.Teletypesetter
@ClarkThomborson I don't agree with calling one of the meanings the "base" semantics, because this implies a hierarchy that doesn't exist. And I think it's confusing to call = an overloaded operator, as well: the term "operator" in R has (until R 4.0, at least!) a specific meaning referring to a function call with special syntactic rules. This isn't what = is doing when used to bind a name to an parameter name inside a function call argument list. There's no call happening, so = in this context is just a syntactic token (like ;), not an operator.Corkhill
I'm a newbie to R... had used S for a project about 30 years ago... and I'm still trying to get my head around its semantics! I tell myself stories about them, then find errors in the stories. My current understanding is that R, like most scripting languages, and like all natural languages, has a very complex semantics which varies with the context and has developed over time. We can still interpret historic documents and dusty-deck R scripts pretty accurately if we interpret them in an appropriate (historic) context. A formal semantics is more likely to confuse than to explain....Teletypesetter
I don't find it helpful to think of = as sometimes being a token, and sometimes being a full-fledged assignment operator. To my way of thinking, <- is also a token... and it's the tokenization phase of parsing that makes "x<-3" problematic. The operation of binding a formal name to a value in a function call occurs at the time the function call is being interpreted. The name-value binding (and the possible name-definition) of x <- 3 occurs at the time this expression is being interpreted. There is a temporal distinction between = and <- but it has to do with operator precedence.Teletypesetter
@ClarkThomborson Regardless of whether you find it helpful, that's precisely what it is: the syntactic = token for named parameters completely vanishes after the parsing phase, it isn't represented in the parse tree at all, nor is it evaluated. Name binding in assignment and in function calling happens fundamentally differently in R (and, to varying extents, in other languages), it isn't merely a "temporal distinction", nor is it due to operator precedence.Corkhill
Oh wow that's very helpful. I had guessed -- apparently incorrectly -- that the binding of formal name to actual parameter happened at runtime in R. That'd be a significant gain in efficiency of interpretation, with some loss of semantic range compared to a scripting language which binds formal names to values at runtime. So... my new "story" about the semantics of = and <- is that, in some contexts, = denotes a name-value binding that is interpreted immediately after the script is parsed, and in other contexts its name-value binding is delayed.Teletypesetter
@Clark I am not really sure what you mean by that. Of course the binding happens at runtime. It just doesn't happen via an operator (which, in R, is a function call!), it doesn't happen differently whether or not an explicit parameter name is specified (i.e. whether or not = is present in the source code), and the = token for parameter name binding is not present in the parse tree (compare as.list(str2lang('x = 1')) and as.list(str2lang('f(x = 1)'))).Corkhill
Let us continue this discussion in chat.Corkhill
B
112

Google's R style guide simplifies the issue by prohibiting the "=" for assignment. Not a bad choice.

https://google.github.io/styleguide/Rguide.xml

The R manual goes into nice detail on all 5 assignment operators.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html

Bastinado answered 16/11, 2009 at 14:44 Comment(3)
Note that any non-0 is considered TRUE by R. So if you intend to test if x is less than -y, you might write if (x<-y) which will not warn or error, and appear to work fine. It'll only be FALSE when y=0, though.Bedstead
Why hurt your eyes and finger with <- if you can use =? In 99.99% of times = is fine. Sometimes you need <<- though, which is a different history.Hornblende
Besides the 0.01% which it won't work is just bad unreadable, hacky shortcut code for anyone who is not R only. It is just like doing bitshift to do a half division just to look smart (but you are not). My opinion is that R should deprecate the <- operator.Lifelong
S
52

x = y = 5 is equivalent to x = (y = 5), because the assignment operators "group" right to left, which works. Meaning: assign 5 to y, leaving the number 5; and then assign that 5 to x.

This is not the same as (x = y) = 5, which doesn't work! Meaning: assign the value of y to x, leaving the value of y; and then assign 5 to, umm..., what exactly?

When you mix the different kinds of assignment operators, <- binds tighter than =. So x = y <- 5 is interpreted as x = (y <- 5), which is the case that makes sense.

Unfortunately, x <- y = 5 is interpreted as (x <- y) = 5, which is the case that doesn't work!

See ?Syntax and ?assignOps for the precedence (binding) and grouping rules.

Silici answered 9/9, 2014 at 21:21 Comment(1)
This was a succinct answer that hit the nail on the head!Beverlee
B
39

According to John Chambers, the operator = is only allowed at "the top level," which means it is not allowed in control structures like if, making the following programming error illegal.

> if(x = 0) 1 else x
Error: syntax error

As he writes, "Disallowing the new assignment form [=] in control expressions avoids programming errors (such as the example above) that are more likely with the equal operator than with other S assignments."

You can manage to do this if it's "isolated from surrounding logical structure, by braces or an extra pair of parentheses," so if ((x = 0)) 1 else x would work.

See http://developer.r-project.org/equalAssign.html

Bryce answered 28/1, 2011 at 18:34 Comment(0)
R
28

From the official R documentation:

The operators <- and = assign into the environment in which they are evaluated. 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.

Rapture answered 16/11, 2009 at 12:21 Comment(5)
I think "top level" means at the statement level, rather than the expression level. So x <- 42 on its own is a statement; in if (x <- 42) {} it would be an expression, and isn't valid. To be clear, this has nothing to do with whether you are in the global environment or not.Silici
This: “the operator = is only allowed at the top level” is a widely held misunderstanding and completely wrong.Corkhill
This is not true - for example, this works, even though assignment is not a complete expression: 1 + (x = 2)Lewert
To clarify the comments by KonradRudolph and PavelMinaev, I think it's too strong to say that it's completely wrong, but there is an exception, which is when it's "isolated from surrounding logical structure, by braces or an extra pair of parentheses."Bryce
Or in function() x = 1, repeat x = 1, if (TRUE) x = 1....Leduc
L
8

This may also add to understanding of the difference between those two operators:

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

For the first element R has assigned values and proper name, while the name of the second element looks a bit strange.

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

R version 3.3.2 (2016-10-31); macOS Sierra 10.12.1

Lamanna answered 10/12, 2016 at 21:32 Comment(0)
B
2

I am not sure if Patrick Burns book R inferno has been cited here where in 8.2.26 = is not a synonym of <- Patrick states "You clearly do not want to use '<-' when you want to set an argument of a function.". The book is available at https://www.burns-stat.com/documents/books/the-r-inferno/

Biscay answered 6/9, 2021 at 16:57 Comment(1)
Yup, it has been mentioned. But the question is about the assignment operator, whereas your excerpt concerns the syntax for passing arguments. It should be made clear (because there’s substantial confusion surrounding this point) that this is not the assignment operator.Corkhill
M
-1

There are some differences between <- and = in the past version of R or even the predecessor language of R (S language). But currently, it seems using = only like any other modern language (python, java) won't cause any problem. You can achieve some more functionality by using <- when passing a value to some augments while also creating a global variable at the same time but it may have weird/unwanted behavior like in

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)
str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

Highly recommended! Try to read this article which is the best article that tries to explain the difference between those two: Check https://colinfay.me/r-assignment/

Also, think about <- as a function that invisibly returns a value.

a <- 2
(a <- 2)
#> [1] 2

See: https://adv-r.hadley.nz/functions.html

Mcalpin answered 13/1, 2023 at 17:55 Comment(3)
Unfortuantely Colin Fay’s article (and now your answer) repeats the common misconception about the alleged difference between = and <-. The explanation is therefore incorrect. See my answer for an exhaustive correction of this pernicious falsehood. To make it explicit: you can rewrite your first code to use = instead of <- without changing its meaning: df <- data.frame(a = rnorm(10), (b = rnorm(10))). And just like <-, =` is a function that invisibly returns a value.Corkhill
@Konrad Rudolph R uses some rules/principles when designing the language and code interpretation for efficiency and usability that not saw in other languages. I believe most people who ask the difference between = and <- is curious about why R has more than one assignment operator compared with other popular Science/math language such as Python. And whether I can safely just only use one = like in other languages. Besides, ( is also a function in R so technically (b = rnorm(10)) is not the same as b <- rnorm(10) since you can override the meaning of ( function in codes.Mcalpin
Yes that’s all true but what does this have to do with my comment? The answer to “why” is: “purely historical”, and the answer to “can I just use =” is “yes”. Everything else, in particular your claim that = can’t be used in some cases, is incorrect. Yes, of course you can override (, just like you can override = and <- so, yes, technically you can redefine them so that they are no longer identical. But surely you agree that this is a pure distraction.Corkhill

© 2022 - 2024 — McMap. All rights reserved.