# R 究竟如何解析 `->`，右赋值运算符？

```````->`
``````

``````getAnywhere("->")
``````

```````->`(3,x)
``````

``````(3 -> x) #assigns the value 3 to the name x
# [1] 3
``````

``````pryr::ast(3 -> y)
# \- ()
#   \- `<- #R interpreter clearly flipped things around
#   \- `y  #  (by the time it gets to `ast`, at least...)
#   \-  3  #  (note: this is because `substitute(3 -> y)`
#          #   already returns the reversed version)
``````

```````<-`
.Primitive("<-")

`<-`(x, 3) #assigns the value 3 to the name x, as expected
``````

`?"->"``?assignOps`R Language Definition都只是顺便提到它是正确的赋值运算符.

`->`的使用方式显然有其独特之处.它不是一个函数/运算符(正如对`getAnywhere`和直接对``->``的调用所显示的那样)，那么它是什么呢？它完全属于自己的一个类吗？

## 推荐答案

``````%token      LEFT_ASSIGN EQ_ASSIGN RIGHT_ASSIGN LBB
``````

``````case '-':
if (nextchar('>')) {
if (nextchar('>')) {
yylval = install_and_save2("<<-", "->>");
return RIGHT_ASSIGN;
}
else {
yylval = install_and_save2("<-", "->");
return RIGHT_ASSIGN;
}
}
``````

``````/* Get an R symbol, and set different yytext.  Used for translation of -> to <-. ->> to <<- */
static SEXP install_and_save2(char * text, char * savetext)
{
strcpy(yytext, savetext);
return install(text);
}
``````

``````|   expr LEFT_ASSIGN expr       { \$\$ = xxbinary(\$2,\$1,\$3);  setId( \$\$, @\$); }
|   expr RIGHT_ASSIGN expr      { \$\$ = xxbinary(\$2,\$3,\$1);  setId( \$\$, @\$); }
``````

`LEFT_ASSIGN`场景:`y <- x`

• `\$2`是上述表达式中解析器的第二个"参数"，即`<-`
• `\$1`是第一位；也就是`y`
• `\$3`是第三位；`x`

• `\$2``->`转为`<-`
• `\$1`等于`x`
• `\$3`等于`y`

``````static SEXP xxbinary(SEXP n1, SEXP n2, SEXP n3)
{
SEXP ans;
if (GenerateCode)
PROTECT(ans = lang3(n1, n2, n3));
else
PROTECT(ans = R_NilValue);
UNPROTECT_PTR(n2);
UNPROTECT_PTR(n3);
return ans;
}
``````

1) 这真的是R中唯一一个这样的对象吗？？(我已经

``````R> `->`
R> `**`
``````

``````case '*':
/* Replace ** by ^.  This has been here since 1998, but is
undocumented (at least in the obvious places).  It is in
the index of the Blue Book with a reference to p. 431, the
help for 'Deprecated'.  S-PLUS 6.2 still allowed this, so
presumably it was for compatibility with S. */
if (nextchar('*')) {
yylval = install_and_save2("^", "**");
return '^';
} else
yylval = install_and_save("*");
return c;
``````

2) When exactly does this happen? I've got in mind that substitute(3 -> y) has already flipped the expression; I couldn't figure out from the source what substitute does that would have pinged the YACC...

``````/* Language Related Constructs */

/* Primitives */
{"if",      do_if,      0,  200,    -1, {PP_IF,      PREC_FN,     1}},
{"while",   do_while,   0,  100,    2,  {PP_WHILE,   PREC_FN,     0}},
{"for",     do_for,     0,  100,    3,  {PP_FOR,     PREC_FN,     0}},
{"repeat",  do_repeat,  0,  100,    1,  {PP_REPEAT,  PREC_FN,     0}},
{"break",   do_break, CTXT_BREAK,   0,  0,  {PP_BREAK,   PREC_FN,     0}},
{"next",    do_break, CTXT_NEXT,    0,  0,  {PP_NEXT,    PREC_FN,     0}},
{"return",  do_return,  0,  0,  -1, {PP_RETURN,  PREC_FN,     0}},
{"function",    do_function,    0,  0,  -1, {PP_FUNCTION,PREC_FN,     0}},
{"<-",      do_set,     1,  100,    -1, {PP_ASSIGN,  PREC_LEFT,   1}},
{"=",       do_set,     3,  100,    -1, {PP_ASSIGN,  PREC_EQ,     1}},
{"<<-",     do_set,     2,  100,    -1, {PP_ASSIGN2, PREC_LEFT,   1}},
{"{",       do_begin,   0,  200,    -1, {PP_CURLY,   PREC_FN,     0}},
{"(",       do_paren,   0,  1,  1,  {PP_PAREN,   PREC_FN,     0}},
``````