Road to Elm - Table of Contents
Destructuring is a handy tool, available in many functional languages (also in Javascript ES6).
It's a more succinct syntax to extract single values from collections of various types.
Extracting values from objects or arrays and assigning them to local variables is one of the little things you do in programming without even thinking about it.
There's not much of a choice: littering your code with object.property.property.property
or array[0]
is longer to write, has slower performance, and is untidy.
Less code
In pre-ES6 Javascript that was a line by line affair:
var r1 = [9, 8];
function area (rect){
var w = rect[0];
var h = rect[1];
return w * h;
}
In Elm, it would look like this:
r1 = (9, 8)
addAreas : (Int, Int) -> Int
area rect =
let
(w, h) = rect -- using destructuring
in
w * h
So we exchange two lines:
var w = rect[0];
var h = rect[1];
for one
(w, h) = rect
and we end up with the same result, w is 9, and h is 8.
If we had something longer, like:
var list = [2, 5, 6, 7, 8];
var x = list[0];
var y = list[1];
var z = list[2];
var a = list[3];
var b = list[4];
it would still be one line in Elm:
list = (2,5,6,7,8)
(x, y, z, a, b) = list
Skipping
or maybe you want only x
, a
, and b
:
list = (2,5,6,7,8)
(x, _, _, a, b) = list
_
will be ignored.
Objects/Records example
So we looked at tuples (Elm) and arrays (Javascript), now let's do the same for records (Elm) and objects (Javascript).
Objects and records are not the same, but they are similar enough for our purposes in this article, much like tuples and arrays.
var r1 = { x : 9, y : 8 };
function area (rect) {
var w = rect.x;
var h = rect.y;
return w * h;
}
the same in Elm:
type alias Rect
= { x : Int
, y : Int
}
area : Rect -> Int
area rect =
let
{ x, y } = rect -- using destructuring
in
x * y
you can also use it in place of the argument name:
area : Rect -> Int
area { x, y } =
x * y
this way you skipped even the let
, but notice that it was necessary to use x
and y
, matching the Rect
type definition, instead of being able to use different letters, as w
and h
in the let
above.
Some fancier examples
Nested destructuring
You can also extract values from a tuple inside a tuple:
tryNested ( x,( w, h ), g ) =
w
> tryNested (5, (6,7), 3)
6 : number
or a record inside a tuple:
tryNested ( x, { w, h }, g ) =
w
> tryNested ( 3, { w=3, h=5 }, 6)
3 : number
Use within case
You can destructure a record from the arguments and then use it in a case
...of
within a tuple:
tryCase { x, y } =
case (x, y) of
(5,5) -> "Correct"
(_,3) -> "Less correct"
_ -> "Wrong"
which we can try out in elm-repl
:
> tryCase {x = 5, y = 7}
"Wrong" : String
> tryCase {x = 5, y = 5}
"Correct" : String
> tryCase {x = 4, y = 3}
"Less correct" : String
Reminder
In a function always assign your variables within a let
!
Comments? Give me a shout at @lambda_cat.
To get the latest post updates subscribe to the LambdaCat newsletter.
You can support my writing on LambdaCat's Patreon.