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 at petzel.at> Sent: Monday, January 9, 2023 9:18 PM To: akshay kulkarni <akshay_e4 at hotmail.com> Cc: R help Mailing list <r-help at 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 at 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 at 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]]
Returning the last value of { is the basis of functions not needing a return statement. Before R invokes a function (specifically a closure), it creates a new context. When R evaluates a call to return, it looks for a context to return from and finds the context of function, ending the context and the evaluation of the function body early. However, if you don't use return, R just returns the value from evaluating the function body, and if your function body starts with {, it will return the last expression from the function body, as desired. On Mon, Jan 9, 2023, 12:15 akshay kulkarni <akshay_e4 at hotmail.com> wrote:> 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 at petzel.at> > Sent: Monday, January 9, 2023 9:18 PM > To: akshay kulkarni <akshay_e4 at hotmail.com> > Cc: R help Mailing list <r-help at 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 at 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 at 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 at 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]]
Akshay, Your question seems a tad mysterious to me as you are complaining about NOTHING. R was designed to return single values. The last statement executed in a function body, for example, is the value returned even when not at the end. Scoping is another issue entirely. What is visible is another discussion. So, yes, if you can see ALL the variables, you might see the last one BUT there often is no variable at the end. There is an expression that evaluates to a value with no NAME attached. You cannot reference that unless the block in curly braces returns that value. You can design your own language any way you want. The people who designed R did it this way. Mind you, the most common use of curly braces is probably in function bodies, or if/else blocks and loops, not quite what you are looking at and complaining about. The design is what it is. Others require things like an explicit return() statement. R chose not to. And if the value is redundant for you, who cares? Did you know that when running a program in the interpreter the last value is stored in a variable like this:> x <- 6 > .Last.value[1] 6 Why would that duplicate be needed or useful? Consider a partial calculation you want to reuse in another context:> y = x*2 + 2*x -3 > z <- .Last.value/2 > z[1] 10.5 Yes, you could have used "y" ... -----Original Message----- From: R-help <r-help-bounces at r-project.org> On Behalf Of akshay kulkarni Sent: Monday, January 9, 2023 12:06 PM To: Valentin Petzel <valentin at petzel.at> Cc: R help Mailing list <r-help at r-project.org> Subject: Re: [R] return value of {....} 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 at petzel.at> Sent: Monday, January 9, 2023 9:18 PM To: akshay kulkarni <akshay_e4 at hotmail.com> Cc: R help Mailing list <r-help at 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 at 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 lastexpression 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 beadvantageous 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 at 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 at 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.
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 at 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 at petzel.at> > *Sent:* Monday, January 9, 2023 9:18 PM > *To:* akshay kulkarni <akshay_e4 at hotmail.com> > *Cc:* R help Mailing list <r-help at 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 at 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 at 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]]