Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In today’s blogpost, we take a look at one of the most questions about R: What’s the difference between <- and =? And as always, there’s a video version for you:
Similar assignment
Let’s first talk about the similarities of both operators. Obviously, both work as expected when you assign values to variable names.
a = 1 a ## [1] 1 a <- 2 a ## [1] 2
This even works in functions. Take this function, It always returns 5 whatever you stick into the argument a:
fct <- function(some_nmbr) {
print(glue::glue('I received {some_nmbr}.'))
5
}
fct(some_nmbr = 10)
## I received 10.
## [1] 5
fct(some_nmbr <- 10)
## I received 10.
## [1] 5
Boring function but have you seen how both = and <- worked the same? That’s why it’s easy to think that both operators are indeed the same. But that’s where different scoping comes in.
Scoping
The <- operator has a broader scope. It can create variables in the global environment when used inside functions, while = typically only assigns within the local function environment.
rm(some_nmbr) # make sure that some_nmbr doesn't currently
# exist in global env
fct(some_nmbr = 10)
## I received 10.
## [1] 5
Even though we assigned some_nmbr = inside the fct() the variable some_nmbr isn’t available once fct() completed.
some_nmbr ## Error in eval(expr, envir, enclos): object 'some_nmbr' not found
But watch what happens if we use <- instead of =:
fct(some_nmbr <- 10) ## I received 10. ## [1] 5 some_nmbr ## [1] 10
The function still tells us that it received 10 and returns 5. But this time the assignment some_nmbr <- also worked globally. That’s why we can access some_nmbr after fct() terminated.
Don’t believe me yet? Let’s try it again.
fct(some_nmbr <- 20) ## I received 20. ## [1] 5 some_nmbr ## [1] 20
See? Now, some_nmbr in the global environment is 20. Interestingly, this only takes effect, when the variable some_nmbr is actually used inside of fct(). Let’s create another function.
fct2 <- function(some_nmbr) {
5
}
This function doesn’t actually use some_nmbr in this function body at all. Now watch what happens when we use the <- assignment again.
fct2(some_nmbr <- 30) ## [1] 5 some_nmbr ## [1] 20
some_nmbr still has the value from before and not the new one. Funny, isn’t it? Anyway, due to these possible side effects you might want to use = inside of function calls.
Powerup of <-
Now that we have seen that <- is in a sense more powerful than =, let me also mention another power-up. You see, you can make the <- into <<- and get an even more powerful operator. You can use the inside a function to define a variable outside the function in the global environment.
Check out this example.
power_fct <- function() {
defined_inside <- 20
5
}
This function first used the regular <- operator to define a variable called defined_inside. This variable cannot be accessed once power_fct() terminates.
power_fct() ## [1] 5 defined_inside ## Error in eval(expr, envir, enclos): object 'defined_inside' not found
But watch what happens when we make change <- to <<- inside of power_fct().
power_fct <- function() {
defined_inside <<- 20
5
}
power_fct()
## [1] 5
defined_inside
## [1] 20
Magical, isn’t it? This trick can be really handy sometimes but also quite dangerous. Make sure you use this trick only when you know what you want to do.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
