Unpack tuple into another tuple
-
25-05-2021 - |
質問
Suppose I need to construct a tuple of length three:
(x , y, z)
And I have a function which returns a tuple of length two - exampleFunction
and the last two elements of the tuple to be constructed are from this tuple.
How can I do this without having to call the exampleFunction
two times:
(x, fst exampleFunction , snd exampleFunction)
I just want to do / achieve something like
(x, exampleFunction)
but it complains that the tuples have unmatched length ( of course )
Not looking at doing let y,z = exampleFunction()
解決
There may be a built in function, but a custom one would work just as well.
let repack (a,(b,c)) = (a,b,c)
repack (x,exampleFunction)
他のヒント
I'm not sure it if worth a separate answer, but both answers provided above are not optimal since both construct redundant Tuple<'a, Tuple<'b, 'c>>
upon invocation of the helper function. I would say a custom operator would be better for both readability and performance:
let inline ( +@ ) a (b,c) = a, b, c
let result = x +@ yz // result is ('x, 'y, 'z)
The problem you have is that the function return a*b
so the return type becomes 'a*('b*'c)
which is different to 'a*'b*'c
the best solution is a small helper function like
let inline flatten (a,(b,c)) = a,b,c
then you can do
(x,examplefunction) |> flatten
I have the following function in my common extension file. You may find this useful.
let inline squash12 ((a,(b,c) ):('a*('b*'c) )):('a*'b*'c ) = (a,b,c )
let inline squash21 (((a,b),c ):(('a*'b)*'c )):('a*'b*'c ) = (a,b,c )
let inline squash13 ((a,(b,c,d)):('a*('b*'c*'d))):('a*'b*'c*'d) = (a,b,c,d)
let seqsquash12 (sa:seq<'a*('b*'c) >) = sa |> Seq.map squash12
let seqsquash21 (sa:seq<('a*'b)*'c >) = sa |> Seq.map squash21
let seqsquash13 (sa:seq<'a*('b*'c*'d)>) = sa |> Seq.map squash13
let arrsquash12 (sa:('a*('b*'c) ) array) = sa |> Array.map squash12
let arrsquash21 (sa:(('a*'b)*'c ) array) = sa |> Array.map squash21
let arrsquash13 (sa:('a*('b*'c*'d)) array) = sa |> Array.map squash13