mulesoft-labs / data-weave-rfc

RFC for the data weave language
12 stars 5 forks source link

Object deconstruct #13

Open machaval opened 4 years ago

machaval commented 4 years ago

Object decomposition

It is very common to return objects and then trying to extract its parts.

For example the function splitAt of dw::core::Arrays returns a Pair that is basically an object with l and r properties So currently what we need to do is

var splits = splitAt([1,2,3], 2)
var left = splits.l
var right = splits.r
---
left[0] ++ right[0]

I think this verbose with no reason and that many modern language already solve this.

Proposal

Binding top level fields

We just allow to bind any part of the result.

var {l: left, r: right} = splitAt([1,2,3], 2)
---
left[0] ++ right[0]

Also not the entire object needs to be bind. For example if we want just to bind the r we can just

var {r: right} = splitAt([1,2,3], 2)
---
right[0]

Binding inner fields

var {error: {kind: kind}} = try(splitAt([1,2,3], 2))

This will bind the error.kind field

TomoDC commented 4 years ago

I'm not sure about this because:

I'm not sure if its usefulness is greater than the complexity that adds to read the script.

jerneyio commented 4 years ago

I'm also concerned about the usefulness relative to the readability. Something I see common in other languages is the ability to assign multiple variables with one statement. It'd be convenient to have something like this supported:

var splits = splitAt([1,2,3], 2)
var left, right = splits.l, splits.r
---
left[0] ++ right[0]

It makes the decomposition of objects less annoying, but has a syntax that more programmers would already be familiar with.

For what it's worth, clojure has a similar syntax, they call it "destructuring" - https://clojure.org/guides/destructuring

machaval commented 4 years ago

https://docs.microsoft.com/en-us/dotnet/csharp/deconstruct#deconstructing-a-tuple

https://users.rust-lang.org/t/tuples-destructuring-assignment/11028

https://docs.scala-lang.org/tour/tuples.html

They all have it for tuples but as we don't have tuples (because I still think we don't need them) I thought we can make it for objects

menduz commented 4 years ago

I'm going to show some examples mixed with arrays/tuples but those are the same for DW.

C++ also have it in this shape

Which is the same as JS/TS

let [x,y,z] = [1,2,3]

And JS/TS has the object destructuring in its simpler form

let {x,y,z} = vector

And with renames

let {x: horizontal,y: vertical,z: depth} = vector

// you can use horizontal now

Do not forget the rest operation:

let {x, ...resto} = vector3
// resto = {y,z}

Also for arrays:

let [first, ...resto] = [1,2,3,4]
// resto = [2,3,4]

Which in dataweave is the ~

Go, python and the WASM and the LLVM have multiple return values

func x() {
        return 1,2,3,4
}

a,b,c,d = x()