17

My question is about parsing expressions in R language. Let me jump right into an example:

fun_text <- c("
0 -> var
f1 <- function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
}

(function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})->f2

f3 = function(x)
{
  0 -> sum_var
  sum_var2 = 0
  sum_var3 <- 0
}

")

fun_tree <- parse(text=fun_text)
fun_tree 
fun_tree[[1]]
fun_tree[[2]]
fun_tree[[3]]
fun_tree[[4]]

After that, we obtain those results:

expression(0 -> var, f1 <- function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
}, (function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})->f2, f3 = function(x)
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})

and

var <- 0

and

f1 <- function() {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
}

and

f2 <- (function() {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
})

and

f3 = function(x) {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
}

As you can see, all "->" assignment operators are changed to "<-", but not in the first example ("fun_tree" only). My question is: why is that? and can I be sure that I always get "<-" operator in syntax tree, so I can do not bother myself in implementing "->" case?

bartoszukm
  • 693
  • 3
  • 10
  • Have you tried asking the r-devel mailing list? They'll probably have much better idea of what is going on. – Scott Ritchie Apr 26 '14 at 10:42
  • Just out of interest, did you check `length(fun_tree)` to be sure there isn't more "hiding" there? – Carl Witthoft Apr 26 '14 at 11:17
  • 3
    @ScottRitchie I’m not too happy with this advice – it causes exactly the kind of balkanisation that StackOverflow wants to prevent. Why does it matter? Well for one thing, SO is much more searchable (or rather, findable) than mailing lists. – Konrad Rudolph Apr 26 '14 at 11:38
  • 1
    That's true, and I'm not in any way suggesting the question shouldn't be asked here. I meant it as a suggestion of another resource to also consult. – Scott Ritchie Apr 26 '14 at 12:01

2 Answers2

17

can I be sure that I always get "<-" operator in syntax tree

Let’s see …

> quote(b -> a)
a <- b
> identical(quote(b -> a), quote(a <- b))
[1] TRUE

So yes, the -> assignment is always parsed as <- (the same is not true when invoking -> as a function name!1).

Your first display is the other way round because of parse’s keep.source argument:

> parse(text = 'b -> a')
expression(b -> a)
> parse(text = 'b -> a', keep.source = FALSE)
expression(a <- b)

1 Invoking <- as a function is the same as using it as an operator:

> quote(`<-`(a, b))
a <- b
> identical(quote(a <- b), quote(`<-`(a, b)))
[1] TRUE

However, there is no -> function (although you can define one), and writing b -> a never calls a -> function, it always gets parsed as a <- b, which, in turn, invokes the <- function or primitive.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    So is there some history on why `->` even exists if it is just reversed during parsing? – Thomas Apr 26 '14 at 11:53
  • @Thomas I don’t know the reason. I use it sometimes in R’s REPL because I have written a long-ish expression iteratively (i.e. by building it up slowly) and now want to assign its result to a variable without having to retype it, or putting the cursor back to the beginning of the line. Lazy, true. There are a few languages (TI BASIC) which has an assignment from left to right (`42 → x`). – Konrad Rudolph Apr 26 '14 at 11:57
  • I agree with Konrad in that I think the reason -> exists is due to convenience. You shouldn't use it in a script but if you're on the command line it's easier to add `-> myvar` to the end of the line when you forgot to assign it to something and R does offer features that exist solely to make your life easier on the command line. – Dason Apr 26 '14 at 13:27
  • 2
    A rather off-topic curiosity: did you know that R used to allow `_` for assignment? This has been [removed](http://cran.rstudio.com/src/base/NEWS.1) in R 1.8.0. – gagolews Apr 27 '14 at 17:53
  • See also [this Q&A](http://stackoverflow.com/questions/34599027/how-exactly-does-r-parse-the-right-assignment-operator) about how `->` is parsed in more detail – MichaelChirico Jan 16 '17 at 16:27
0

This is slightly off topic, but I think that a left-to-right assignment operator can be used in cases beyond fast command-line typing. So, here's one way to define such an operator:

"%op%"<- function(a,b) eval(substitute(b<-a), parent.frame())

I am using this to avoid duplicating R-code when storing/loading a set of matrices and vectors to/from a vector (Error: object '->' not found in R).