8

The manual states:

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.

The question here mention the difference when used in the function call. But in the function definition, it seems to work normally:

a = function () 
{
    b = 2
    x <- 3
    y <<- 4
}

a()
# (b and x are undefined here)

So why the manual mentions that the operator ‘=’ is only allowed at the top level??

There is nothing about it in the language definition (there is no = operator listed, what a shame!)

Community
  • 1
  • 1
Tomas
  • 57,621
  • 49
  • 238
  • 373
  • It's mentioned in R-lang in [section 10.4.2 Infix and prefix operators](http://cran.r-project.org/doc/manuals/R-lang.html#Infix-and-prefix-operators), but doesn't say much more than what's in the help entry you mentioned. – Joshua Ulrich Jun 08 '12 at 13:20
  • 5
    The text you quote says "at the top level **OR** in a braced list of subexpressions". You are using it in a braced list of subexpressions. Which is allowed. – Andrie Jun 08 '12 at 13:25
  • 5
    You have to go to great lengths to find an expression which is neither toplevel nor within braces. Here is one. You sometimes want to wrap an assignment inside a `try` block: `try( x <- f() )` is fine, but `try( x = f(x) )` is not -- you need to either change the assignment operator or add braces. – Vincent Zoonekynd Jun 08 '12 at 13:27
  • @VincentZoonekynd: can you post that as an answer? – Joshua Ulrich Jun 08 '12 at 13:33
  • 3
    Another example is when you wrap an expression in a `system.time` call: `system.time(a <- runif(10000))`. I almost exclusively use = assignment and I haven't run into many problems. – Paul Hiemstra Jun 08 '12 at 13:50
  • 1
    system.time(notanargumentofsystem.time = 1) Oh, bugger <- woulda been good – mdsumner Jun 08 '12 at 14:15
  • 1
    I use `=` exclusively too, and I actually oppose the use of `<-` (explained in https://github.com/yihui/formatR/wiki; search for `fun(a = 1)` in the page) – Yihui Xie Jun 08 '12 at 15:08
  • I have an additional question for this: Why can't R have just one assignment operator, which works everywhere? The current system feels unnecessarily complicated. I would use only `=`, because it is shorter. Why not to build the language so that `=` would work everywhere? – Mikko Jun 08 '12 at 15:45
  • @Largh Because of history; there was a key on the terminals in use at Bell Labs (where S was written) that bore the symbol `<-`. That symbol *does* work everywhere. – Gavin Simpson Jun 08 '12 at 16:43
  • @Yihui but the point is you **can't** do the assignment to `a` in `fun(a = 1)` if you use `=`, but you can with `<-`. There are places when coding where it often if useful to do things like this, admittedly they can be done with two separate statements, but if the R Gods (R Core) use this idiom a lot then there must be some worthyness to it! ;-) Each to their own is probably all we can take from these stylistic debates, as fun as they are :-) – Gavin Simpson Jun 08 '12 at 16:47
  • @Gavin Simpson: --- but if the R Gods (R Core) use this idiom--- Dieter: Gods grow old. – Dieter Menne Jun 08 '12 at 16:56
  • 2
    @GavinSimpson I believe the confusion of `fun(a <- 1)` is greater than the benefit over `a <- 1; fun(a)`. It is rare to see assignment in the place of function arguments in other languages. R is a bizarre but anyway great language. `<-` working everywhere is dangerous, and the other danger I have seen in the past is when people mean `x smaller than negative 1`, they forget the space and end up with `x<-1` (you may laugh at it, but it did happen) – Yihui Xie Jun 08 '12 at 17:46
  • @Yihui I raise you `system.time(a <- foo(....))`, try that with `system.time(a = foo(....))`. There are valid and perfectly acceptable reasons for doing this. Sticking to `=` means one has to work around the system. As you say, there are issues the other way too. Both sides can be worked around; so any advice to use one system over the other should be taken with a pinch of salt. The individual has to find a way of working that they are comfortable with. I personally don't like `=` but I use ESS so `<-` is also one key press away. – Gavin Simpson Jun 08 '12 at 18:01
  • 1
    @GavinSimpson ESS needs two keys `Shift` and `-` in order to type an underscore :) I use `_` in my variable names, so I often turn off the automatic replacement of `_` to `<-` in ESS, otherwise I have to type `_` twice to get the real `_`. I do use `<-` occasionally when I want to be lazy to assign values in place of function arguments like `system.time(a <- foo(....))`, but in most cases I stick to `=` (I do not want to type `system.time({a = foo(....)})` in this case). Hiding assignments in function arguments may save a few key strokes, but it also hides the structure of code somehow. – Yihui Xie Jun 08 '12 at 18:20
  • @Andrie, thank you for your comment, that makes it clear! – Tomas Jun 11 '12 at 10:48
  • @JoshuaUlrich, thanks. I was looking at [R-Lang chapter 3.1.4](http://cran.r-project.org/doc/manuals/R-lang.html#Operators) and `=` is not there, surprisingly. – Tomas Jun 11 '12 at 10:52

3 Answers3

12

The text you quote says at the top level OR in a braced list of subexpressions. You are using it in a braced list of subexpressions. Which is allowed.

You have to go to great lengths to find an expression which is neither toplevel nor within braces. Here is one. You sometimes want to wrap an assignment inside a try block: try( x <- f() ) is fine, but try( x = f(x) ) is not -- you need to either change the assignment operator or add braces.

Andrie
  • 176,377
  • 47
  • 447
  • 496
Vincent Zoonekynd
  • 31,893
  • 5
  • 69
  • 78
  • Vincent, thank you but how does this answer my question about `b = 2` being wrong in my example? Maybe I miss something so then please explain in more obvious way :) – Tomas Jun 11 '12 at 10:42
  • @Tomas I added my comment which you found helpful. I think this answers the question. – Andrie Jun 11 '12 at 10:51
  • However, `try((x = f()))` works fine. The R documentation is simply wrong in claiming otherwise. – Konrad Rudolph Jan 24 '20 at 15:02
7

Expressions not at the top level include usage in control structures like if. For example, the following programming error is illegal.

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

As mentioned here: https://stackoverflow.com/a/4831793/210673

Also see http://developer.r-project.org/equalAssign.html

Community
  • 1
  • 1
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
  • thank you for the [second link](http://developer.r-project.org/equalAssign.html)! The most important information there is: *"Where it is allowed, the `=` operator is semantically equivalent to all of the earlier assignments (i.e. `<-` and others)."* – Tomas Jun 11 '12 at 11:04
4

Other than some examples such as system.time as others have shown where <- and = have different results, the main difference is more philisophical. Larry Wall, the creater of Perl, said something along the lines of "similar things should look similar, different things should look different", I have found it interesting in different languages to see what things are considered "similar" and which are considered "different". Now for R assignment let's compare 2 commands:

myfun( a <- 1:10 )

myfun( a = 1:10 )

Some would argue that in both cases we are assigning 1:10 to a so what we are doing is similar.

The other argument is that in the first call we are assigning to a variable a that is in the same environment from which myfun is being called and in the second call we are assigning to a variable a that is in the environment created when the function is called and is local to the function and those two a variables are different.

So which to use depends on whether you consider the assignments "similar" or "different".

Personally, I prefer <-, but I don't think it is worth fighting a holy war over.

Greg Snow
  • 48,497
  • 6
  • 83
  • 110