29

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?

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
Romain Jacotin
  • 311
  • 1
  • 3
  • 6

3 Answers3

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
James
  • 65,548
  • 14
  • 155
  • 193
  • 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 '<<-' – Romain Jacotin Sep 28 '15 at 08:47
  • @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. http://svn.r-project.org/R/trunk/doc/NEWS.1 – James Sep 28 '15 at 08:50
  • 4
    I think they simply forgot to remove it and then Matt came along with data.table and now they can't remove it anymore. – Roland Sep 28 '15 at 09:01
10

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.

ah bon
  • 9,293
  • 12
  • 65
  • 148
Colonel Beauvel
  • 30,423
  • 11
  • 47
  • 87
  • 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. – Roland Sep 28 '15 at 08:12
  • 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 ? – Romain Jacotin Sep 28 '15 at 08:30
  • @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. – Roland Sep 28 '15 at 08:33
  • 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 `<<-` – Colonel Beauvel Sep 28 '15 at 08:35
  • 2
    @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. – jangorecki Sep 28 '15 at 13:57
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.

Mingshu Huang
  • 171
  • 1
  • 5
  • 1
    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. – moodymudskipper Nov 13 '18 at 11:54
  • 3
    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? – seth127 Apr 01 '20 at 15:28
  • 2
    Oh wait, I think I found an answer: https://community.rstudio.com/t/undefined-global-functions-or-variables/10852/2 short version: `@importFrom rlang :=` – seth127 Apr 01 '20 at 15:33