[R] return value of {....}
Richard O'Keefe
r@oknz @end|ng |rom gm@||@com
Mon Jan 16 00:39:07 CET 2023
I wonder if the real confusino is not R's scope rules?
(begin .) is not Lisp, it's Scheme (a major Lisp dialect),
and in Scheme, (begin (define x ...) (define y ...) ...)
declares variables x and y that are local to the (begin ...)
form, just like Algol 68. That's weirdness 1. Javascript
had a similar weirdness, when the ECMAscript process eventually
addressed. But the real weirdness in R is not just that the
existence of variables is indifferent to the presence of curly
braces, it's that it's *dynamic*. In
f <- function (...) {
... use x ...
x <- ...
... use x ...
}
the two occurrences of "use x" refer to DIFFERENT variables.
The first occurrence refers to the x that exists outside the
function. It has to: the local variable does not exist yet.
The assignment *creates* the variable, so the second
occurrence of "use x" refers to the inner variable.
Here's an actual example.
> x <- 137
> f <- function () {
+ a <- x
+ x <- 42
+ b <- x
+ list(a=a, b=b)
+ }
> f()
$a
[1] 137
$b
[1] 42
Many years ago I set out to write a compiler for R, and this was
the issue that finally sank my attempt. It's not whether the
occurrence of "use x" is *lexically* before the creation of x.
It's when the assignment is *executed* that makes the difference.
Different paths of execution through a function may result in it
arriving at its return point with different sets of local variables.
R is the only language I routinely use that does this.
So rule 1: whether an identifier in an R function refers to an
outer variable or a local variable depends on whether an assignment
creating that local variable has been executed yet.
And rule 2: the scope of a local variable is the whole function.
If the following transcript not only makes sense to you, but is
exactly what you expect, congratulations, you understand local
variables in R.
> x <- 0
> g <- function () {
+ n <- 10
+ r <- numeric(n)
+ for (i in 1:n) {
+ if (i == 6) x <- 100
+ r[i] <- x + i
+ }
+ r
+ }
> g()
[1] 1 2 3 4 5 106 107 108 109 110
On Fri, 13 Jan 2023 at 23:28, Valentin Petzel <valentin using petzel.at> wrote:
> Hello Akshay,
>
> R is quite inspired by LISP, where this is a common thing. It is not in
> fact that {...} returned something, rather any expression evalulates to
> some value, and for a compound statement that is the last evaluated
> expression.
>
> {...} might be seen as similar to LISPs (begin ...).
>
> Now this is a very different thing compared to {...} in something like C,
> even if it looks or behaves similarly. But in R {...} is in fact an
> expression and thus has evaluate to some value. This also comes with some
> nice benefits.
>
> You do not need to use {...} for anything that is a single statement. But
> you can in each possible place use {...} to turn multiple statements into
> one.
>
> Now think about a statement like this
>
> f <- function(n) {
> x <- runif(n)
> x**2
> }
>
> Then we can do
>
> y <- f(10)
>
> Now, you suggested way would look like this:
>
> f <- function(n) {
> x <- runif(n)
> y <- x**2
> }
>
> And we'd need to do something like:
>
> f(10)
> y <- somehow_get_last_env_of_f$y
>
> So having a compound statement evaluate to a value clearly has a benefit.
>
> Best Regards,
> Valentin
>
> 09.01.2023 18:05:58 akshay kulkarni <akshay_e4 using hotmail.com>:
>
> > Dear Valentin,
> > But why should {....} "return" a value? It
> could just as well evaluate all the expressions and store the resulting
> objects in whatever environment the interpreter chooses, and then it would
> be left to the user to manipulate any object he chooses. Don't you think
> returning the last, or any value, is redundant? We are living in the
> 21st century world, and the R-core team might,I suppose, have a definite
> reason for"returning" the last value. Any comments?
> >
> > Thanking you,
> > Yours sincerely,
> > AKSHAY M KULKARNI
> >
> > ----------------------------------------
> > *From:* Valentin Petzel <valentin using petzel.at>
> > *Sent:* Monday, January 9, 2023 9:18 PM
> > *To:* akshay kulkarni <akshay_e4 using hotmail.com>
> > *Cc:* R help Mailing list <r-help using r-project.org>
> > *Subject:* Re: [R] return value of {....}
> >
> > Hello Akshai,
> >
> > I think you are confusing {...} with local({...}). This one will
> evaluate the expression in a separate environment, returning the last
> expression.
> >
> > {...} simply evaluates multiple expressions as one and returns the
> result of the last line, but it still evaluates each expression.
> >
> > Assignment returns the assigned value, so we can chain assignments like
> this
> >
> > a <- 1 + (b <- 2)
> >
> > conveniently.
> >
> > So when is {...} useful? Well, anyplace where you want to execute
> complex stuff in a function argument. E.g. you might do:
> >
> > data %>% group_by(x) %>% summarise(y = {if(x[1] > 10) sum(y) else
> mean(y)})
> >
> > Regards,
> > Valentin Petzel
> >
> > 09.01.2023 15:47:53 akshay kulkarni <akshay_e4 using hotmail.com>:
> >
> >> Dear members,
> >> I have the following code:
> >>
> >>> TB <- {x <- 3;y <- 5}
> >>> TB
> >> [1] 5
> >>
> >> It is consistent with the documentation: For {, the result of the last
> expression evaluated. This has the visibility of the last evaluation.
> >>
> >> But both x AND y are created, but the "return value" is y. How can this
> be advantageous for solving practical problems? Specifically, consider the
> following code:
> >>
> >> F <- function(X) { expr; expr2; { expr5; expr7}; expr8;expr10}
> >>
> >> Both expr5 and expr7 are created, and are accessible by the code
> outside of the nested braces right? But the "return value" of the nested
> braces is expr7. So doesn't this mean that only expr7 should be accessible?
> Please help me entangle this (of course the return value of F is expr10,
> and all the other objects created by the preceding expressions are deleted.
> But expr5 is not, after the control passes outside of the nested braces!)
> >>
> >> Thanking you,
> >> Yours sincerely,
> >> AKSHAY M KULKARNI
> >>
> >> [[alternative HTML version deleted]]
> >>
> >> ______________________________________________
> >> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> >> https://stat.ethz.ch/mailman/listinfo/r-help
> >> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> >> and provide commented, minimal, self-contained, reproducible code.
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
[[alternative HTML version deleted]]
More information about the R-help
mailing list