Parsing "->" assignment operator in R
Asked Answered
A

2

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?

Acoustic answered 26/4, 2014 at 10:38 Comment(4)
Have you tried asking the r-devel mailing list? They'll probably have much better idea of what is going on.Unclothe
Just out of interest, did you check length(fun_tree) to be sure there isn't more "hiding" there?Inquisitive
@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.Cherin
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.Unclothe
C
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.

Cherin answered 26/4, 2014 at 11:44 Comment(5)
So is there some history on why -> even exists if it is just reversed during parsing?Curtal
@Curtal 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).Cherin
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.Canoness
A rather off-topic curiosity: did you know that R used to allow _ for assignment? This has been removed in R 1.8.0.Mcalister
See also this Q&A about how -> is parsed in more detailFerry
M
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).

Mauceri answered 7/3, 2018 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.