2

I am a beginner so I'd appreciate any thoughts, and I understand that this question might be too basic for some of you.

Also, this question is not about the difference between <- and =, but about the way they get evaluated when they are part of the function argument. I read this thread, Assignment operators in R: '=' and '<-' and several others, but I couldn't understand the difference.

Here's the first line of code:

My objective is to get rid of variables in the environment. From reading the above thread, I would believe that <- would exist in the user workspace, so there shouldn't be any issue with deleting all variables.

Here is my code and two questions:

Question 1

First off, this code doesn't work.

rm(ls()) #throws an error

I believe this happens because ls() returns a character vector, and rm() expects an object name. Am I correct? If so, I would appreciate if someone could guide me how to get object names from character array.

Question 2 I googled this topic and found that this code below deletes all variables.

rm(list = ls()) 

While this does help me, I am unsure why = is used instead of <-. If I run the following code, I get an error Error in rm(list <- ls()) : ... must contain names or character strings

rm(list <- ls())  

Why is this? Can someone please guide me? I'd appreciate any help/guidance.

Community
  • 1
  • 1
watchtower
  • 4,140
  • 14
  • 50
  • 92
  • @jenesaisquoi - Thanks. This helps. If you can post an answer, I can accept it. This might help others who might be interested in knowing the answer. – watchtower Jan 30 '17 at 05:52
  • @jenesaisquoi Technically, using `<-` to specify a function argument value is not necessarily a syntax error. However, it is unusual and probably inadvisable unless you know what you're doing. There was a specific problem in this case because `list` is not the first argument to `rm`. – joran Jan 30 '17 at 17:51
  • @Joran - Thanks for your comment. Could you please explain "There was a specific problem in this case because list is not the first argument to `rm`."? I didn't quite follow what the problem is. I believe I am missing some major concept here. I'd appreciate your thoughts. – watchtower Jan 31 '17 at 05:20
  • @watchtower See my answer for a short example. – joran Jan 31 '17 at 15:06
  • In addition, `<-` is, still, a function call that assigns an object to a symbol and has as a returned value this specific object. So `rm` is, only passed the returned value of `<-` (here, the value `ls()`) as its argument. – alexis_laz Jan 31 '17 at 16:36

3 Answers3

4

I read this thread, Assignment operators in R: '=' and '<-' and several others, but I couldn't understand the difference.

No wonder, since the answers there are actually quite confusing, and some are outright wrong. Since that’s the case, let’s first establish the difference between them before diving into your actual question (which, it turns out, is mostly unrelated):

<- is an assignment operator

In R, <- is an operator that performs assignment from right to left, in the current scope. That’s it.

= is either an assignment operator or a distinct syntactic token

=, by contrast, has several meanings: its semantics change depending on the syntactic context it is used in:

  • If = is used inside a parameter list, immediately to the right of a parameter name, then its meaning is: “associate the value on the right with the parameter name on the left”.

  • Otherwise (i.e. in all other situations), = is also an operator, and by default has the same meaning as <-: i.e. it performs assignment in the current scope.

As a consequence of this, the operators <- and = can be used interchangeably1. However, = has an additional syntactic role in an argument list of a function definition or a function call. In this context it’s not an operator and cannot be replaced by <-.

So all these statements are equivalent:

x <- 1
x = 1

x[5] <- 1
x[5] = 1

(x <- 1)
(x = 1)

f((x <- 5))
f((x = 5))

Note the extra parentheses in the last example: if we omitted these, then f(x = 5) would be interpreted as a parameter association rather than an assignment.


With that out of the way, let’s turn to your first question:

When calling rm(ls()), you are passing ls() to rm as the ... parameter. Ronak’s answer explains this in more detail.

Your second question should be answered by my explanation above: <- and = behave differently in this context because the syntactic usage dictates that rm(list = ls()) associates ls() with the named parameter list, whereas <- is (as always) an assignment operator. The result of that assignment is then once again passed as the ... parameter.


1 Unless somebody changed their meaning: operators, like all other functions in R, can be overwritten with new definitions.

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
3

To expand on my comment slightly, consider this example:

> foo <- function(a,b) b+1
> foo(1,b <- 2) # Works
[1] 3
> ls()
[1] "b"   "foo"
> foo(b <- 3) # Doesn't work
Error in foo(b <- 3) : argument "b" is missing, with no default

The ... argument has some special stuff going on that restricts things a little further in the OP's case, but this illustrates the issue with how R is parsing the function arguments.

Specifically, when R looks for named arguments, it looks specifically for arg = val, with an equals sign. Otherwise, it is parsing the arguments positionally. So when you omit the first argument, a, and just do b <- 1, it thinks the expression b <- 1 is what you are passing for the argument a.

joran
  • 169,992
  • 32
  • 429
  • 468
  • @joran - Thanks. This helps a lot. I'm curious--you have mentioned that "...otherwise, it parses arguments positionally." So, if `list` is the first argument, then `list <- val` should work because as in your case with `foo(b<-3)`, we would be assigning the character vector to `list` in `rm()`. This didn't work in your example because R thought that we are assigning `b<-3` to `a`, which is not the case with `rm(list <- ls())`. Right? Am I missing something? I'd appreciate your thoughts. – watchtower Jan 31 '17 at 18:46
  • Not sure whether you saw my note...do you think you could help me? Thanks in advance...I don't want to create a duplicate thread... – watchtower Feb 07 '17 at 03:14
2

If you check ?rm

rm(..., list = character(),pos = -1,envir = as.environment(pos), inherits = FALSE)

where ,

... - the objects to be removed, as names (unquoted) or character strings (quoted).

and

list - a character vector naming objects to be removed.

So, if you do

a <- 5

and then

rm(a) 

it will remove the a from the global environment.

Further , if there are multiple objects you want to remove,

a <- 5
b <- 10
rm(a, b)

This can also be written as

rm(... = a, b)

where we are specifying that the ... part in syntax takes the arguments a and b

Similarly, when we want to specify the list part of the syntax, it has to be given by

rm(list = ls())

doing list <- ls() will store all the variables from ls() in the variable named list

list <- ls()

list
#[1] "a"    "b"    "list"

I hope this is helpful.

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213