6
> within( list(a="a",b="b"), c="c" )
Error in eval(expr, envir, enclos) : argument is missing, with no default
> within( list(a="a",b="b"), c<-"c" )
$a
[1] "a"

$b
[1] "b"

$c
[1] "c"

I'm not sure exactly why these two shouldn't be equivalent. It seems like the the = version getting interpreted as an argument named c to within because of the .... Is there any way to disable this behavior? I tried,

within( list(a="a",b="b"), `c`="c" )

but that fails too.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • 1
    For the same reason that `system.time(x = rnorm(1e300))` doesn't work. – Joshua Ulrich May 13 '13 at 18:43
  • 7
    If `=` is the top function call in expression passed to a function, then `=` is understood to be argument assignment. Compare with `within( list(a="a",b="b"), {c="c"})` – Matthew Plourde May 13 '13 at 18:43
  • the = sign as an assignment is funky inside functions, R gets confused whether it is an assignment or an argument. – Green Demon May 13 '13 at 18:46
  • 1
    This also seems to work...`within( list(a="a",b="b"), "="(c,"c") )`, in case you really hate the `<-` assignment. :) – Frank May 13 '13 at 18:50
  • 1
    Frank I love the shameless exploitation of R's operators-are-really-just-functions concept. But I think @MatthewPlourde wins for ease of implementation. :-) – Ari B. Friedman May 13 '13 at 19:16
  • @GreenDemon, I wouldnt say that `R` gets confused, but rather is quite clear and on the matter and has documented the behavior well – Ricardo Saporta May 13 '13 at 19:41
  • Also see: http://stackoverflow.com/questions/1741820/assignment-operators-in-r-and and http://stackoverflow.com/questions/14089066/what-is-the-difference-meaning-between-and-in-data-frame – Ricardo Saporta May 13 '13 at 19:44
  • 1
    @MatthewPlourde and Frank, care to make your comments answers? – Ari B. Friedman May 14 '13 at 00:18

2 Answers2

8

You are correct that c="c" (or any clause of that form) is getting interpreted as a supplied argument. And no, there's no way to disable that -- it's presumably handled down at the level of the R parser.

This difference between = and <- is documented ?"<-"

The operators ‘<-’ and ‘=’ assign into the environment in which they are evaluated. 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 prime example of a "braced list of expressions" is a function body, which you can verify by typing, e.g. is(body(plot.default)), length(body(plot.default)).

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
  • Thanks for the explanation. Every time I encounter something like this I think I learn a little more about how the R parser works. Now if only I had a free summer or two or three to go wade through the C source and figure out how it *really* works :-) – Ari B. Friedman May 13 '13 at 19:17
  • @AriB.Friedman -- Hey, don't tempt me to go have a look for myself! I was just happy to finally figure out what that reference to "braced subexpressions" was really getting at, and will count it an accomplishment to have stopped there ;) – Josh O'Brien May 13 '13 at 21:51
  • Combining @MatthewPlourde 's suggestion with yours, `is(quote({5^2})` returns `[1] "{" "language"` just like `is(body(plot.default))` does. – Ari B. Friedman May 14 '13 at 00:12
3

Josh has answered the "why", but at the OP's suggestion, here is another "how":

within( list(a="a",b="b"), "="(c,"c") )
# $a
# [1] "a"
#
# $b
# [1] "b"
#
# $c
# [1] "c"
Frank
  • 66,179
  • 8
  • 96
  • 180