What is the R assignment operator := for?
Asked Answered
K

3

31

By digging into R source code (file R-3.2.2/src/main/gram.y lines 2836 to 2852) I found that the R parser/tokenizer considers that := is a LEFT_ASSIGNMENT token.

But when trying to use it as an assignment operator in R.3.2.2,
I have an error (impossible to find function for := ...) but as you can see R considers it as an assignment like <- :

> myVar := 42
Erreur : impossible de trouver la fonction ":="
> :=
Erreur : unexpected assignment in ":="
> <-
Erreur : unexpected assignment in "<-"

Is it a bug, or does the token := need to be removed from the tokenizer source code?

Is there a past story about := operator in R?

Kyle answered 28/9, 2015 at 7:31 Comment(3)
:= is a very handy operator inside of data.table, but not (yet?) in R as far as I know.Pubes
Unrelated - why is half of the R error output in English? I'm assuming you have the locale set to French.Outlive
Related: stackoverflow.com/questions/7033106 stackoverflow.com/questions/26269423Jonson
Y
20

It was a previously allowed assignment operator, see this article from John Chambers in 2001.

The development version of R now allows some assignments to be written C- or Java-style, using the = operator. This increases compatibility with S-Plus (as well as with C, Java, and many other languages).

All the previously allowed assignment operators (<-, :=, _, and <<-) remain fully in effect.

It seems the := function is no longer present, but you can "re-enable it" like this:

`:=` <- `<-`
x:=3
x
[1] 3
Yet answered 28/9, 2015 at 8:19 Comment(3)
James, FYI it seems '_' is currently not see as an assignment by the R-3.2.2 parser/tokenizer (just type it alone on the prompt and you will have an 'unexpected input' and not a 'unexpected assignment' as you will have by typing alone '<-' or ':=' or '<<-'Kyle
@RomainJacotin Yes, the underscore was removed as an assignment operator in version 1.8.0, I don't find any mention in the news files regarding := though. svn.r-project.org/R/trunk/doc/NEWS.1Yet
I think they simply forgot to remove it and then Matt came along with data.table and now they can't remove it anymore.Stasny
D
12

To clarify, the R assignment operators are <- and =.

To get information about them type:

 ?`<-` 

Instead of <- in your command line. There also exists an operator <<- affecting the variable in the parent environment.

Regarding := , this operator is the j operator in data.table package. It can be read defined as and is only usable in a data.table object. To illustrate this we modify the second column to b (define col2 with value b) when values in the first col are equal to 1:

library(data.table)

dt <- data.table(col1=c(1,2,1,2,3), col2 = letters[1:5])

dt[col1==1, col2:='b']

For detail explanation:

?`:=`

Hope it clarifies.

Designate answered 28/9, 2015 at 8:8 Comment(5)
I guess those lines in the parser's code are why := could be defined. I remember reading something like this, but forgot where. Maybe Matt or Arun could clarify.Stasny
Effectively the data.table packages defines a custom ':=' function that take advantages of the ':=' assignment operator that is defined in the R parser/tokenizer but it is unofficially described/written nowhere in R Language ... Next question: is it really safe and future proof for everyone (and for data.table maintainers ...) to use this ':=' token ??? Is the data.table devs ask the R core team to add this ':=' assignment token ?Kyle
@RomainJacotin It is extremely unlikely that R-core would change the parser in a way that breaks the widely used data.table package. They are very careful about backwards compatibility.Stasny
it is usefull to define this operator as such since it acts by reference to modify a data.table object. No confusion will be made with the traditional base R operator <-, = and to a lesser extend <<-Designate
@RomainJacotin CRAN is a massive test-suite for R itself - such change for R would result in hundreds of packages to fail, direct dependencies + more which depends indirectly. IMO the unused := operator in R is a feature, in fact there could be even few more operators like that. Besides, R does not provide functionality which could substitute that data.table's valuable feature so I don't know what rationale would justify the scenario mentioned by you.Everick
D
9

(Note: This is not a direct answer to the original question. Since I don't have enough reputation to comment and I think the piece of information below is useful, I put it as an answer anyway. Please let me know if there is a better way to do so!)

Although you can't directly use := as = or <-, the := operator is very useful in programming with domain specific language (DSL) that use nonstandard evaluation (NSE), such as dplyr and data.table. Below is an example:

library(dplyr)
df <- tibble(
  g1 = c(1, 1, 2, 2, 2),
  g2 = c(1, 2, 1, 2, 1),
  a = sample(5),
  b = sample(5)
)

my_mutate <- function(df, expr) {
  expr <- enquo(expr)
  mean_name <- paste0("mean_", quo_name(expr))
  sum_name <- paste0("sum_", quo_name(expr))

  mutate(df,
    !! mean_name := mean(!! expr),
    !! sum_name := sum(!! expr)
  )
}

my_mutate(df, a)
#> # A tibble: 5 x 6
#>      g1    g2     a     b mean_a sum_a
#>   <dbl> <dbl> <int> <int>  <dbl> <int>
#> 1    1.    1.     1     3     3.    15
#> 2    1.    2.     4     2     3.    15
#> 3    2.    1.     2     1     3.    15
#> 4    2.    2.     5     4     3.    15
#> # ... with 1 more row

In the example above, replacing := within the my_mutate function with = won't work, because !! mean_name = mean(!! expr) isn't valid R code.

You can read more about NSE and programming with dplyr here. It does a great job explaining how to handle NSE when using dplyr functions to write your own function. My example above is directly copied from the website.

Daradarach answered 22/3, 2018 at 17:16 Comment(3)
I think it's a proper answer as most will know := only from data.table and tidyverse. I would add that none of these package actually execute the code contained in their definition of :=, they just use it because it has convenient and operator precedence and parse the expression that contain it when it's used in a compatible argument.Backpack
Question: do you have to import the := from somewhere? I am building a package with a function that has very similar syntax to your my_mutate() above and R CMD CHECK is giving me no visible global function definition for ‘:=’ error. Thoughts?Dolt
Oh wait, I think I found an answer: community.rstudio.com/t/undefined-global-functions-or-variables/… short version: @importFrom rlang :=Dolt

© 2022 - 2024 — McMap. All rights reserved.