Sebastian Martin Krantz
2023-Mar-11 21:42 UTC
[Rd] Multiple Assignment built into the R Interpreter?
Thanks Duncan and Ivan for the careful thoughts. I'm not sure I can follow all aspects you raised, but to give my limited take on a few:> your proposal violates a very basic property of the language, i.e. that all statements are expressions and have a value. > What's the value of 1 + (A, C = init_matrices()).I'm not sure I see the point here. I evaluated 1 + (d = dim(mtcars); nr = d[1]; nc = d[2]; rm(d)), which simply gives a syntax error, as the above expression should. `%=%` assigns to environments, so 1 + (c("A", "C") %=% init_matrices()) returns numeric(0), with A and C having their values assigned.> suppose f() returns list(A = 1, B = 2) and I do > B, A <- f() > Should assignment be by position or by name?In other languages this is by position. The feature is not meant to replace list2env(), and being able to rename objects in the assignment is a vital feature of codes using multi input and output functions e.g. in Matlab or Julia.> Honestly, given that this is simply syntactic sugar, I don't think I would support it.You can call it that, but it would be used by almost every R user almost every day. Simple things like nr, nc = dim(x); values, vectors = eigen(x) etc. where the creation of intermediate objects is cumbersome and redundant.> I see you've already mentioned it ("JavaScript-like"). I think it would fulfil Sebastian's requirements too, as long as it is considered "true assignment" by the rest of the language.I don't have strong opinions about how the issue is phrased or implemented. Something like [t, n] = dim(x) might even be more clear. It's important though that assignment remains by position, so even if some output gets thrown away that should also be positional.> A <- 0 > [A, B = A + 10] <- list(1, A = 2)I also fail to see the use of allowing this. something like this is an error.> A = 2 > (B = A + 1) <- 1Error in (B = A + 1) <- 1 : could not find function "(<-" Regarding the practical implementation, I think `collapse::%=%` is a good starting point. It could be introduced in R as a separate function, or `=` could be modified to accommodate its capability. It should be clear that with more than one LHS variables the assignment is an environment level operation and the results can only be used in computations once assigned to the environment, e.g. as in 1 + (c("A", "C") %=% init_matrices()), A and C are not available for the addition in this statement. The interpretor then needs to be modified to read something like nr, nc dim(x) or [nr, nc] = dim(x). as an environment-level multiple assignment operation with no immediate value. Appears very feasible to my limited understanding, but I guess there are other things to consider still. Definitely appreciate the responses so far though. Best regards, Sebastian On Sat, 11 Mar 2023 at 20:38, Duncan Murdoch <murdoch.duncan at gmail.com> wrote:> On 11/03/2023 11:57 a.m., Ivan Krylov wrote: > > On Sat, 11 Mar 2023 11:11:06 -0500 > > Duncan Murdoch <murdoch.duncan at gmail.com> wrote: > > > >> That's clear, but your proposal violates a very basic property of the > >> language, i.e. that all statements are expressions and have a value. > > > > How about reframing this feature request from multiple assignment > > (which does go contrary to "everything has only one value, even if it's > > sometimes invisible(NULL)") to "structured binding" / "destructuring > > assignment" [*], which takes this single single value returned by the > > expression and subsets it subject to certain rules? It may be easier to > > make a decision on the semantics for destructuring assignment (e.g. > > languages which have this feature typically allow throwing unneeded > > parts of the return value away), and it doesn't seem to break as much > > of the rest of the language if implemented. > > > > I see you've already mentioned it ("JavaScript-like"). I think it would > > fulfil Sebastian's requirements too, as long as it is considered "true > > assignment" by the rest of the language. > > > > The hard part is to propose the actual grammar of the new feature (in > > terms of src/main/gram.y, preferably without introducing conflicts) and > > its semantics (including the corner cases, some of which you have > > already mentioned). I'm not sure I'm up to the task. > > > > If I were doing it, here's what I'd propose: > > '[' formlist ']' LEFT_ASSIGN expr > '[' formlist ']' EQ_ASSIGN expr > expr RIGHT_ASSIGN '[' formlist ']' > > where `formlist` has the syntax of the formals list for a function > definition. This would have the following semantics: > > { > *tmp* <- expr > > # For arguments with no "default" expression, > > argname1 <- *tmp*[[1]] > argname2 <- *tmp*[[2]] > ... > > # For arguments with a default listed > > argname3 <- with(*tmp*, default3) > } > > > The value of the whole thing would therefore be (invisibly) the value of > the last item in the assignment. > > Two examples: > > [A, B, C] <- expr # assign the first three elements of expr to A, > B, and C > > [A, B, C = a + b] <- expr # assign the first two elements of expr > # to A and B, > # assign with(expr, a + b) to C. > > Unfortunately, I don't think this could be done entirely by transforming > the expression (which is the way |> was done), and that makes it a lot > harder to write and to reason about. E.g. what does this do? > > A <- 0 > [A, B = A + 10] <- list(1, A = 2) > > According to the recipe above, I think it sets A to 1 and B to 12, but > maybe a user would expect B to be 10 or 11. And according to that > recipe this is an error: > > [A, B = A + 10] <- c(1, A = 2) > > which probably isn't what a user would expect, given that this is fine: > > [A, B] <- c(1, 2) > > Duncan Murdoch >[[alternative HTML version deleted]]
Duncan Murdoch
2023-Mar-11 22:42 UTC
[Rd] Multiple Assignment built into the R Interpreter?
On 11/03/2023 4:42 p.m., Sebastian Martin Krantz wrote:> Thanks Duncan and Ivan for the careful thoughts. I'm not sure I can > follow all aspects you raised, but to give my limited take on a few: > >> your proposal violates a very basic property of the language, i.e. that all statements are expressions and have a value. > What's the value of 1 + (A, C = init_matrices()). > > I'm not sure I see the point here. I evaluated 1 + (d = dim(mtcars); nr > = d[1]; nc = d[2]; rm(d)), which simply gives a syntax error, as the > above expression should. `%=%` assigns to > environments, so 1 + (c("A", "C") %=% init_matrices()) returns > numeric(0), with A and C having their values assigned. > >> suppose f() returns list(A = 1, B = 2) and I do > B, A <- f() > Should assignment be by position or by name? > > In other languages this is by position. The feature is not meant to > replace list2env(), and being able to rename objects in the assignment > is a vital feature of codes > using multi input and output functions e.g. in Matlab or Julia. > >> Honestly, given that this is simply syntactic sugar, I don't think I would support it. > > You can call it that, but it would be used by almost every R user almost > every day. Simple things like nr, nc = dim(x); values, vectors = > eigen(x) etc. where the creation of intermediate objects > is cumbersome and redundant. > >> I see you've already mentioned it ("JavaScript-like"). I think it would fulfil Sebastian's requirements too, as long as it is considered "true assignment" by the rest of the language. > > I don't have strong opinions about how the issue is phrased or > implemented. Something like [t, n] = dim(x) might even be more clear. > It's important though that assignment remains by position, > so even if some output gets thrown away that should also be positional. > >> A <- 0 > [A, B = A + 10] <- list(1, A = 2) > > I also fail to see the use of allowing this. something like this is an > error. > >> A = 2 >> (B = A + 1) <- 1 > Error in (B = A + 1) <- 1 : could not find function "(<-" > > Regarding the practical implementation, I think `collapse::%=%` is a > good starting point. It could be introduced in R as a separate function, > or `=` could be modified to accommodate its capability. It should be > clear that > with more than one LHS variables the assignment is an environment level > operation and the results can only be used in computations once assigned > to the environment, e.g. as in 1 + (c("A", "C") %=% init_matrices()), > A and C are not available for the addition in this statement. The > interpretor then needs to be modified to read something like nr, nc = > dim(x) or [nr, nc] = dim(x). as an environment-level multiple assignment > operation with no > immediate value. Appears very feasible to my limited understanding, but > I guess there are other things to consider still. Definitely appreciate > the responses so far though.Show me. Duncan Murdoch> > Best regards, > > Sebastian > > > > > > On Sat, 11 Mar 2023 at 20:38, Duncan Murdoch <murdoch.duncan at gmail.com > <mailto:murdoch.duncan at gmail.com>> wrote: > > On 11/03/2023 11:57 a.m., Ivan Krylov wrote: > > On Sat, 11 Mar 2023 11:11:06 -0500 > > Duncan Murdoch <murdoch.duncan at gmail.com > <mailto:murdoch.duncan at gmail.com>> wrote: > > > >> That's clear, but your proposal violates a very basic property > of the > >> language, i.e. that all statements are expressions and have a value. > > > > How about reframing this feature request from multiple assignment > > (which does go contrary to "everything has only one value, even > if it's > > sometimes invisible(NULL)") to "structured binding" / "destructuring > > assignment" [*], which takes this single single value returned by the > > expression and subsets it subject to certain rules? It may be > easier to > > make a decision on the semantics for destructuring assignment (e.g. > > languages which have this feature typically allow throwing unneeded > > parts of the return value away), and it doesn't seem to break as much > > of the rest of the language if implemented. > > > > I see you've already mentioned it ("JavaScript-like"). I think it > would > > fulfil Sebastian's requirements too, as long as it is considered > "true > > assignment" by the rest of the language. > > > > The hard part is to propose the actual grammar of the new feature (in > > terms of src/main/gram.y, preferably without introducing > conflicts) and > > its semantics (including the corner cases, some of which you have > > already mentioned). I'm not sure I'm up to the task. > > > > If I were doing it, here's what I'd propose: > > ? ?'[' formlist ']' LEFT_ASSIGN expr > ? ?'[' formlist ']' EQ_ASSIGN expr > ? ?expr RIGHT_ASSIGN? '[' formlist ']' > > where `formlist` has the syntax of the formals list for a function > definition.? This would have the following semantics: > > ? ? { > ? ? ? *tmp* <- expr > > ? ? ? # For arguments with no "default" expression, > > ? ? ? argname1 <- *tmp*[[1]] > ? ? ? argname2 <- *tmp*[[2]] > ? ? ? ... > > ? ? ? # For arguments with a default listed > > ? ? ? argname3 <- with(*tmp*, default3) > ? ? } > > > The value of the whole thing would therefore be (invisibly) the > value of > the last item in the assignment. > > Two examples: > > ? ?[A, B, C] <- expr? ?# assign the first three elements of expr to A, > B, and C > > ? ?[A, B, C = a + b] <- expr? # assign the first two elements of expr > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # to A and B, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # assign with(expr, a + b) to C. > > Unfortunately, I don't think this could be done entirely by > transforming > the expression (which is the way |> was done), and that makes it a lot > harder to write and to reason about.? E.g. what does this do? > > ? ?A <- 0 > ? ?[A, B = A + 10] <- list(1, A = 2) > > According to the recipe above, I think it sets A to 1 and B to 12, but > maybe a user would expect B to be 10 or 11.? And according to that > recipe this is an error: > > ? ?[A, B = A + 10] <- c(1, A = 2) > > which probably isn't what a user would expect, given that this is fine: > > ? ?[A, B] <- c(1, 2) > > Duncan Murdoch >
Duncan Murdoch
2023-Mar-11 22:44 UTC
[Rd] Multiple Assignment built into the R Interpreter?
On 11/03/2023 4:42 p.m., Sebastian Martin Krantz wrote:> Thanks Duncan and Ivan for the careful thoughts. I'm not sure I can > follow all aspects you raised, but to give my limited take on a few: > >> your proposal violates a very basic property of the language, i.e. that all statements are expressions and have a value. > What's the value of 1 + (A, C = init_matrices()). > > I'm not sure I see the point here. I evaluated 1 + (d = dim(mtcars); nr > = d[1]; nc = d[2]; rm(d)), which simply gives a syntax error,d = dim(mtcars); nr = d[1]; nc = d[2]; rm(d) is not a statement, it is a sequence of 4 statements. Duncan Murdoch as the> above expression should. `%=%` assigns to > environments, so 1 + (c("A", "C") %=% init_matrices()) returns > numeric(0), with A and C having their values assigned. > >> suppose f() returns list(A = 1, B = 2) and I do > B, A <- f() > Should assignment be by position or by name? > > In other languages this is by position. The feature is not meant to > replace list2env(), and being able to rename objects in the assignment > is a vital feature of codes > using multi input and output functions e.g. in Matlab or Julia. > >> Honestly, given that this is simply syntactic sugar, I don't think I would support it. > > You can call it that, but it would be used by almost every R user almost > every day. Simple things like nr, nc = dim(x); values, vectors = > eigen(x) etc. where the creation of intermediate objects > is cumbersome and redundant. > >> I see you've already mentioned it ("JavaScript-like"). I think it would fulfil Sebastian's requirements too, as long as it is considered "true assignment" by the rest of the language. > > I don't have strong opinions about how the issue is phrased or > implemented. Something like [t, n] = dim(x) might even be more clear. > It's important though that assignment remains by position, > so even if some output gets thrown away that should also be positional. > >> A <- 0 > [A, B = A + 10] <- list(1, A = 2) > > I also fail to see the use of allowing this. something like this is an > error. > >> A = 2 >> (B = A + 1) <- 1 > Error in (B = A + 1) <- 1 : could not find function "(<-" > > Regarding the practical implementation, I think `collapse::%=%` is a > good starting point. It could be introduced in R as a separate function, > or `=` could be modified to accommodate its capability. It should be > clear that > with more than one LHS variables the assignment is an environment level > operation and the results can only be used in computations once assigned > to the environment, e.g. as in 1 + (c("A", "C") %=% init_matrices()), > A and C are not available for the addition in this statement. The > interpretor then needs to be modified to read something like nr, nc = > dim(x) or [nr, nc] = dim(x). as an environment-level multiple assignment > operation with no > immediate value. Appears very feasible to my limited understanding, but > I guess there are other things to consider still. Definitely appreciate > the responses so far though. > > Best regards, > > Sebastian > > > > > > On Sat, 11 Mar 2023 at 20:38, Duncan Murdoch <murdoch.duncan at gmail.com > <mailto:murdoch.duncan at gmail.com>> wrote: > > On 11/03/2023 11:57 a.m., Ivan Krylov wrote: > > On Sat, 11 Mar 2023 11:11:06 -0500 > > Duncan Murdoch <murdoch.duncan at gmail.com > <mailto:murdoch.duncan at gmail.com>> wrote: > > > >> That's clear, but your proposal violates a very basic property > of the > >> language, i.e. that all statements are expressions and have a value. > > > > How about reframing this feature request from multiple assignment > > (which does go contrary to "everything has only one value, even > if it's > > sometimes invisible(NULL)") to "structured binding" / "destructuring > > assignment" [*], which takes this single single value returned by the > > expression and subsets it subject to certain rules? It may be > easier to > > make a decision on the semantics for destructuring assignment (e.g. > > languages which have this feature typically allow throwing unneeded > > parts of the return value away), and it doesn't seem to break as much > > of the rest of the language if implemented. > > > > I see you've already mentioned it ("JavaScript-like"). I think it > would > > fulfil Sebastian's requirements too, as long as it is considered > "true > > assignment" by the rest of the language. > > > > The hard part is to propose the actual grammar of the new feature (in > > terms of src/main/gram.y, preferably without introducing > conflicts) and > > its semantics (including the corner cases, some of which you have > > already mentioned). I'm not sure I'm up to the task. > > > > If I were doing it, here's what I'd propose: > > ? ?'[' formlist ']' LEFT_ASSIGN expr > ? ?'[' formlist ']' EQ_ASSIGN expr > ? ?expr RIGHT_ASSIGN? '[' formlist ']' > > where `formlist` has the syntax of the formals list for a function > definition.? This would have the following semantics: > > ? ? { > ? ? ? *tmp* <- expr > > ? ? ? # For arguments with no "default" expression, > > ? ? ? argname1 <- *tmp*[[1]] > ? ? ? argname2 <- *tmp*[[2]] > ? ? ? ... > > ? ? ? # For arguments with a default listed > > ? ? ? argname3 <- with(*tmp*, default3) > ? ? } > > > The value of the whole thing would therefore be (invisibly) the > value of > the last item in the assignment. > > Two examples: > > ? ?[A, B, C] <- expr? ?# assign the first three elements of expr to A, > B, and C > > ? ?[A, B, C = a + b] <- expr? # assign the first two elements of expr > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # to A and B, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # assign with(expr, a + b) to C. > > Unfortunately, I don't think this could be done entirely by > transforming > the expression (which is the way |> was done), and that makes it a lot > harder to write and to reason about.? E.g. what does this do? > > ? ?A <- 0 > ? ?[A, B = A + 10] <- list(1, A = 2) > > According to the recipe above, I think it sets A to 1 and B to 12, but > maybe a user would expect B to be 10 or 11.? And according to that > recipe this is an error: > > ? ?[A, B = A + 10] <- c(1, A = 2) > > which probably isn't what a user would expect, given that this is fine: > > ? ?[A, B] <- c(1, 2) > > Duncan Murdoch >
Gabriel Becker
2023-Mar-11 22:54 UTC
[Rd] Multiple Assignment built into the R Interpreter?
There are some other considerations too (apologies if these were mentioned above and I missed them). Also below are initial thoughts, so apologies for any mistakes or oversights. For example, if [a, b] <- my2valuefun() works the same as local({ tmp <- my2valuefun() stopifnot(is.list(tmp) && length(tmp) == 2) a <<- tmp[[1]] b <<- tmp[[2]] }) Do we expect [a[1], b[3]] <- my2valuefun() to also work? That doesn't sound very fun to me, personally, but obviously the "single value return" versions of these do work and have for a long time, i.e. a[1] <- my2valuefun()[[1]] b[3] <- my2valuefun()[[2]] is perfectly valid R code (though it does call the function twice which is "silly" in some sense). Another thing which arises from the Julia API specifically which I think is problematic is the ambiguity of's atomic "types" being vectors. Consider the following coolest_function <- function() c(a = 15, b = 65, c = 275) a <- coolest_function() That obviously makes a vector of length 3. Anything else would break *like all the R code* But now, what does [a] <- coolest_function() do? Does it assign 15 to a, because b and c arent' being assigned to? Does this mean variables being assigned to actually need to *match the names within the return object*? I don't think that would work at all in general... Alternatively, is the second one an error, because the function isn't returning a list? This doesn't really fix the problem either though Because a single list of length > 1 *is a valid thing to return from an R function*. I think, like in Julia, you'd need to declare the set of things being returned, and perhaps map them to the variables you want assigned crazy_notworking_fun <- function() { return(a = 5, b = 65, c = 275) } [a_val = a, b_val = b] <- crazy_notworking_fun() Or even, [a_val <- a, b_val <-b] <- crazy_notworking_fun() In that case, however, it becomes somewhat unclear (to me at least) what only_val <- crazy_notworking_fun() would do. Throw an error because multivalued functions are fundamentally different and we can't pretend they aren't? This would disallow all of the things you think "most r users would use every day" (a claim I'm somewhat skeptical of, to be honest). If thats not it, though, what? I don't think it can/should return the full list of results, because that introduces the ambiguity this is trying to avoid right back in. Perhaps just the first thing returned? That is internally consistent, but somewhat strange behavior... Best, ~G On Sat, Mar 11, 2023 at 2:15?PM Sebastian Martin Krantz < sebastian.krantz at graduateinstitute.ch> wrote:> Thanks Duncan and Ivan for the careful thoughts. I'm not sure I can follow > all aspects you raised, but to give my limited take on a few: > > > your proposal violates a very basic property of the language, i.e. that > all statements are expressions and have a value. > > What's the value of 1 + (A, C = init_matrices()). > > I'm not sure I see the point here. I evaluated 1 + (d = dim(mtcars); > nr = d[1]; nc = d[2]; rm(d)), which simply gives a syntax error, as > the above expression should. `%=%` assigns to > environments, so 1 + (c("A", "C") %=% init_matrices()) returns > numeric(0), with A and C having their values assigned. > > > suppose f() returns list(A = 1, B = 2) and I do > > B, A <- f() > > Should assignment be by position or by name? > > In other languages this is by position. The feature is not meant to > replace list2env(), and being able to rename objects in the assignment > is a vital feature of codes > using multi input and output functions e.g. in Matlab or Julia. > > > Honestly, given that this is simply syntactic sugar, I don't think I > would support it. > > You can call it that, but it would be used by almost every R user > almost every day. Simple things like nr, nc = dim(x); values, vectors > = eigen(x) etc. where the creation of intermediate objects > is cumbersome and redundant. > > > I see you've already mentioned it ("JavaScript-like"). I think it would > fulfil Sebastian's requirements too, as long as it is considered "true > assignment" by the rest of the language. > > I don't have strong opinions about how the issue is phrased or > implemented. Something like [t, n] = dim(x) might even be more clear. > It's important though that assignment remains by position, > so even if some output gets thrown away that should also be positional. > > > A <- 0 > > [A, B = A + 10] <- list(1, A = 2) > > I also fail to see the use of allowing this. something like this is an > error. > > > A = 2 > > (B = A + 1) <- 1 > Error in (B = A + 1) <- 1 : could not find function "(<-" > > Regarding the practical implementation, I think `collapse::%=%` is a > good starting point. It could be introduced in R as a separate > function, or `=` could be modified to accommodate its capability. It > should be clear that > with more than one LHS variables the assignment is an environment > level operation and the results can only be used in computations once > assigned to the environment, e.g. as in 1 + (c("A", "C") %=% > init_matrices()), > A and C are not available for the addition in this statement. The > interpretor then needs to be modified to read something like nr, nc > dim(x) or [nr, nc] = dim(x). as an environment-level multiple > assignment operation with no > immediate value. Appears very feasible to my limited understanding, > but I guess there are other things to consider still. Definitely > appreciate the responses so far though. > > Best regards, > > Sebastian > > > > > > On Sat, 11 Mar 2023 at 20:38, Duncan Murdoch <murdoch.duncan at gmail.com> > wrote: > > > On 11/03/2023 11:57 a.m., Ivan Krylov wrote: > > > On Sat, 11 Mar 2023 11:11:06 -0500 > > > Duncan Murdoch <murdoch.duncan at gmail.com> wrote: > > > > > >> That's clear, but your proposal violates a very basic property of the > > >> language, i.e. that all statements are expressions and have a value. > > > > > > How about reframing this feature request from multiple assignment > > > (which does go contrary to "everything has only one value, even if it's > > > sometimes invisible(NULL)") to "structured binding" / "destructuring > > > assignment" [*], which takes this single single value returned by the > > > expression and subsets it subject to certain rules? It may be easier to > > > make a decision on the semantics for destructuring assignment (e.g. > > > languages which have this feature typically allow throwing unneeded > > > parts of the return value away), and it doesn't seem to break as much > > > of the rest of the language if implemented. > > > > > > I see you've already mentioned it ("JavaScript-like"). I think it would > > > fulfil Sebastian's requirements too, as long as it is considered "true > > > assignment" by the rest of the language. > > > > > > The hard part is to propose the actual grammar of the new feature (in > > > terms of src/main/gram.y, preferably without introducing conflicts) and > > > its semantics (including the corner cases, some of which you have > > > already mentioned). I'm not sure I'm up to the task. > > > > > > > If I were doing it, here's what I'd propose: > > > > '[' formlist ']' LEFT_ASSIGN expr > > '[' formlist ']' EQ_ASSIGN expr > > expr RIGHT_ASSIGN '[' formlist ']' > > > > where `formlist` has the syntax of the formals list for a function > > definition. This would have the following semantics: > > > > { > > *tmp* <- expr > > > > # For arguments with no "default" expression, > > > > argname1 <- *tmp*[[1]] > > argname2 <- *tmp*[[2]] > > ... > > > > # For arguments with a default listed > > > > argname3 <- with(*tmp*, default3) > > } > > > > > > The value of the whole thing would therefore be (invisibly) the value of > > the last item in the assignment. > > > > Two examples: > > > > [A, B, C] <- expr # assign the first three elements of expr to A, > > B, and C > > > > [A, B, C = a + b] <- expr # assign the first two elements of expr > > # to A and B, > > # assign with(expr, a + b) to C. > > > > Unfortunately, I don't think this could be done entirely by transforming > > the expression (which is the way |> was done), and that makes it a lot > > harder to write and to reason about. E.g. what does this do? > > > > A <- 0 > > [A, B = A + 10] <- list(1, A = 2) > > > > According to the recipe above, I think it sets A to 1 and B to 12, but > > maybe a user would expect B to be 10 or 11. And according to that > > recipe this is an error: > > > > [A, B = A + 10] <- c(1, A = 2) > > > > which probably isn't what a user would expect, given that this is fine: > > > > [A, B] <- c(1, 2) > > > > Duncan Murdoch > > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]