1

According to the R manual,

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)

So I tried rm(list<-ls()) because <- operator can be used anywhere as said above, but R gave me an error saying "... must contain name or character strings".

rm(list=ls()) works without any problem. As far as I know, <- is a more universal assignment while = can be used under more strict circumstance. But why does using <- give an error when it comes to 'rm' function?

onlyphantom
  • 8,606
  • 4
  • 44
  • 58
Eiffelbear
  • 399
  • 1
  • 4
  • 23
  • 3
    They don't do the same when setting function arguments. When used in a call, `<-` assigns a variable in the calling environment, but doesn't set the parameter name, while `=` does the opposite. What's happening here is like how `alist(x <- 1)` returns an unnamed list of an expression, while `alist(x = 1)` returns a named list of a number. This matters here because names are required for all keyword arguments (those after `...`). – alistaire Oct 09 '18 at 00:03
  • @alistaire Thanks for your helpful comment. But what is the difference between a list of an expression and a list of a number? Since I cannot do the 'typeof' for the argument x in the function (i.e. alist(x=1) and alist(x<-1) ), I don't know exactly what the list of expressions and a list of numbers are! – Eiffelbear Oct 09 '18 at 01:18
  • If you call `str` on it or subset, you can see. An expression is an unevaluated language object. Assuming the argument you intend to pass to the parameter is a number, it will cause problems. – alistaire Oct 09 '18 at 01:38

3 Answers3

7

This is because rm() uses non-standard evaluation by default. It tries to remove what you literally type for the parameters that are not list= (or pos= or env= or inherits=).

So you can do

a <- 10
rm(a)

Note that a is just interpreted as a symbol. It's not evaluated to return a value. When you call rm(list<-ls()) you are expecting that expression to be evaluated, but it is not. It's trying to find a variable named "list<-ls()" but no such variable exists because no variable should have such a name. Additionally it has to be a "valid" variable name. From the ?make.names help page

A syntactically valid name consists of letters, numbers and the dot or underline characters and starts with a letter or the dot not followed by a number

This means that it will not parse unusual variable names like those you can make by escaping symbols with back ticks or single quotes. Technically you can also do

a <- 10
rm("a")

because the non-standard evaluation checks if the parameter is a literal character value. But it will still not evaluate any expressions even if they will ultimately return a character value. For example

a <- 10
b <- "a"
rm(b)

What happens above is that b is removed, not a.

If you want to pass in a function that returns names of variables as stirngs (as ls() does), you need to use the named list= parameter. The <- operator does not work as a substitute for = for named parameters.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • When you type ?rm on Rstudio, you can see that rm takes arguments including both **...(ellipsis)** and **list=chracter()**. Does this mean that unless it is specified specifically as list=ls(), rm() takes only symbol such as your varaible 'a' which has 10 as a value? – Eiffelbear Oct 09 '18 at 01:30
  • Another question! I created two variable like this : 'list<-ls()'=c(1,2,3,4,5), y='2'. typeof(list<-ls) and typeof(y) both returns 'characters'. However rm(list<-ls()) does not work while rm('list<-ls()') works. Why do I need to add single quotation marks while rm(y) and rm('y') both works regardless of quotation marks? – Eiffelbear Oct 09 '18 at 01:44
  • 1
    @Jinoo I tried to add some more details to the answer. The thing to note is that `typeof` does not use non-standard evaluation, so it evaluates the parameters you pass to it. A more apt comparison is `typeof(quote(list<-ls))` and `typeof(quote(y))` the former being "language" (which is not something that can be a variable name) and the latter being "symbol" which is what a variable name is. – MrFlick Oct 09 '18 at 02:45
3

You're reading the entry for assignment operations, whereas in the case of rm(list = ls(), the = is not used as an assignment operator, but to set an argument value in a function call (see the discussion in this Stack Overflow answer).

Let's take an example to illustrate:

formals(print)
#> $x
#> 
#> 
#> $...
# The first argument to print() is named x
print(x = "a")
#> [1] "a"
# We've only set the value of argument x, not assigned to x
x
#> Error in eval(expr, envir, enclos): object 'x' not found
print(x <- "a")
#> [1] "a"
# Now we've assigned to x, and passed x as the first argument to print
x
#> [1] "a"
print(y <- "b")
#> [1] "b"
# It works with any variable name, since R can take variables by name or order
y
#> [1] "b"

Created on 2018-10-08 by the reprex package (v0.2.1)

Update

alistaire posted an excellent comment to the question on this about the same time I answered that you should read also.

duckmayr
  • 16,303
  • 3
  • 35
  • 53
1

<- is not more universal. It only works for assignment. = has two uses: assignment and argument passing. Inside a function, = performs argument assigning, which is what you want to do here. With =, you are not creating a variable list which has the value ls(); you are assigning to the parameter list of the function rm() the argument ls().

The first argument to rm() is ..., which must be strings or the names of variables to be removed. You passed list <- ls() which is neither a string nor a name, which is why you got the error. If you want to pass ls() to the list parameter in rm(), you need to use =, not <-.

Noah
  • 3,437
  • 1
  • 11
  • 27