zeallot icon indicating copy to clipboard operation
zeallot copied to clipboard

Destructuring Assignment by Name

Open saurfang opened this issue 7 years ago • 10 comments

In Javascript we can do:

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
 
console.log(foo); // 42 
console.log(bar); // true

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10 
b; // 20 
rest; // { c: 30, d: 40 }

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring

I realize that in R, while named list resembles a hash map, it is indeed ordered.

Maybe something like this?

list(a, b) %<-% list(b = 2, a = 1)
# a = 1 
# b = 2

saurfang avatar Mar 22 '18 06:03 saurfang

Someone else recently posed this to me. I feel the feature is a powerful one and could be added.

I believe the syntax will prove trickiest. I have a couple initial ideas and welcome your thoughts.

  1. c(x: m, y: a) %<-% list(a = "ah", m = "yum")
  2. c(x <- m, y <- a) %<-% list(a = "ah", m = "yum")

nteetor avatar Mar 22 '18 13:03 nteetor

As much as I love var {p, q} = {p: 1, q: 2}; in JS, I agree it is pretty confusing to differentiate it from positional unpacking.

I like c(x <- m, y <- a) because it confuses me every now and then when I write var {p: foo, q: bar} = o; whether we are assigning values to p, q or foo, bar. It is similar to how rename(data, a = b) always confuses me whether I am renaming a to b, or b now is renamed to a. More typing though 🤷‍♂️

saurfang avatar Mar 22 '18 20:03 saurfang

The <- is certainly clearer. I also agree the single extra character may be off-putting. I will think over the syntax for a couple days, but I bet I can have a beta version by the end of the weekend (famous last words). Changing the character(s) used is straightforward once the logic is in place. Let me know if you have any further ideas in the meantime.

nteetor avatar Mar 22 '18 20:03 nteetor

After a conversation with @pteetor I am actually struggling to come up with a solid use case for this functionality. @saurfang, are there times when this feature is better than using . and ... given that we'll have to complicate the syntax with <-?

nteetor avatar Mar 25 '18 15:03 nteetor

Not yet. Funny that I use destructive assignments in Js and Scala day and night but this is not a feature that I miss often when it comes to R. I think mostly because list is not a big part of my R workflow.

I'm still discovering how positional destructive assignment fits in my day to day R flow. I'll let you know if I come across good use case for destructive assignment by name.

saurfang avatar Mar 25 '18 21:03 saurfang

This would be a pretty big help for multiple return values from Shiny modules. One of the things we strongly encourage people to do is use named lists to return reactives and other return values from Shiny module server functions. In these cases, the returned list usually has little inherent meaning; it's the elements of the list that you want to turn into variables.

Having destructuring assignment by name would make the coupling between caller and callee robust to reordering of the named lists returned by the modules.

I haven't thought much about the syntax but semantically I'm really looking for the equivalent of e.g.

let {a, b} = {a: 10, b: 20, c: 30, d: 40};

jcheng5 avatar Aug 26 '19 20:08 jcheng5

FWIW, this is the idiom I've been using to do this:

list2env(my_list[c('a', 'b', 'c')])

t-kalinowski avatar Oct 16 '19 12:10 t-kalinowski

c(a=, b=) %<-% list(b = 2, a = 1)

:heart_eyes:

jcheng5 avatar Mar 06 '20 18:03 jcheng5

Allow optional renaming by providing a value?

c(foo=a, b=) %<-% list(b = 2, a = 1)

jcheng5 avatar Mar 06 '20 19:03 jcheng5

That's an interesting approach I hadn't yet considered.

I was working on an idea borrowed from javascript, c(a: b, b: a) %<-% list(b = 2, a = 1). I wasn't particularly enthused with this syntax because : has a very different meaning for R users.

Right now = specifies a default value. If the default is a name I think it's reasonable to first check the RHS and then check the calling environment for the specified object. The var= syntax is more than : intuitive for R users. I'll give it a go. Thanks for the suggestion!

nteetor avatar Mar 06 '20 19:03 nteetor