0

Given this:

vec1 = 1:10
varname = "vec1"

I know I can do this:

eval(parse(text=paste0(varname,"[5] = 20")))

I want to find something cleaner if possible. I tried this:

`<-`(`[`(as.name(varname), 5), 20)

But I get an error: "object of type 'symbol' is not subsettable".

Something very similar does work:

`<-`(`[`(vec1, 5), 20)

Why is vec1 being treated differently from as.name("vec1") when passed as the first argument to the [ function?

If I try this:

`<-`(`[`(as.name("vec1"), 5), 20)

I get a curiously different error: "target of assignment expands to non-language object".

Can someone explain the nuances involved here? And are there cleaner ways to do what I want, while keeping vec1 as a simple, standalone, top-level variable? The actual scenario in this case is more involved and I already have a workaround; I'm asking this more to understand the fundamentals of what's possible and what's not possible with R.

kartik_subbarao
  • 228
  • 3
  • 15
  • Does your actual code involved a large number of variables like `vec1` all defined separately? Maybe other things like `vec2`, `vec3`, etc? – joran May 03 '18 at 18:36
  • No, there are just two top-level variables -- they're dataframes with several columns of the same name. Here's an example of how I'd want to process them: for (dfstr in c("df1", "df2")) { df = as.name(dfstr); df$field1 = round(df$field1, 4); df$field2 = round(df$field2, 3) } – kartik_subbarao May 03 '18 at 18:49
  • For each `df`, do you want to apply the same function to _all_ variables, or to a selection of variables? – acylam May 03 '18 at 18:55
  • Ok, in that case, I'd just put those two data frames in a named list and index them by name. – joran May 03 '18 at 19:01
  • @useR To a selection of fields, with slightly different arguments each time. – kartik_subbarao May 03 '18 at 19:02
  • In that case, provide exactly what you are looking for in your question. It is very difficult to provide a solution without the input and expected datasets, as well as an explanation of what you're trying to do. – acylam May 03 '18 at 19:04
  • joran, @useR -- As I mentioned in the question, I already have a workaround. I'm asking this question more to understand why R treats vec1 differently from as.name("vec1"). This is puzzling to me. Why is it able to "subset" vec1 when it's typed in directly, and not when it's specified with as.name("vec1")? Isn't as.name("vec1") supposed to result in something that's identical to vec1? – kartik_subbarao May 03 '18 at 19:06
  • @joran I know I can do that, but for various reasons, I'd consider that to be less preferable in this case. As I mentioned in the question, I'm specifically trying to understand the nuances involved in modifying top-level variables by reference. – kartik_subbarao May 03 '18 at 19:11
  • 1
    Well, a `name/symbol` of `vec1` is not the actual `vec1` itself. Just as with `parse` you have to `eval` the parsed string, with `as.name`, you have evaluate it in order to use it. – acylam May 03 '18 at 19:13
  • @useR When I pass eval(as.name("vec1")), I still get the same error (target of assignment expands to non-language object). Am I missing something? What do I need to do to "vec1" to get to vec1? – kartik_subbarao May 03 '18 at 19:20
  • 1
    It's probably generally the same reason why this would fail with [get](https://stackoverflow.com/q/14464442/324364). You can't assign to the result of a function. The reason is (probably) that R can't be sure in a very general sense what is going to come out of the function. – joran May 03 '18 at 19:51
  • @joran Hmm, not sure I follow. Let's take `assign(paste0("vec", "2"), 1:10)`, which does work. In this case, isn't assignment happening to the result of a function call? – kartik_subbarao May 03 '18 at 20:19
  • Internally, yes, and only to a character object. That's why `assign` exists. In your case you're trying to assign R's typical tools. – joran May 03 '18 at 20:25
  • @joran I don't think I fully understand your explanation, but it doesn't sound too optimisic :-) If I try to read between the lines, are you suggesting that the internal R code for the `[` function looks at its first argument, distinguishes between `vec1` and `as.name("vec1")`, and expressly denies the latter case, leaving no way for any program to pass the equivalent of `vec1` from a string? it'd be great to get something more definitive on this (such as a pointer/explanation on the R internals where this happens), but I appreciate your response in any case. – kartik_subbarao May 03 '18 at 20:49
  • 1
    I'm not an expert on the C internals, but someone helpfully pointed out to me that the C function that throws this error (and does the complex expansion of the LHS) is literally annotated in the source with ["this is what nightmares are made of"](https://github.com/wch/r-source/blob/e0b847422074173f06f13eea8560d897afd26e52/src/main/eval.c#L2442). So that's what I mean by "you can't do this, because it's really complicated". – joran May 04 '18 at 14:12
  • Hahaha! :-) Fair enough, thanks for looking into this! – kartik_subbarao May 04 '18 at 15:31

0 Answers0