Распакуйте кортеж в другой кортеж - PullRequest
1 голос
/ 22 марта 2012

Предположим, мне нужно построить кортеж длины три:

(x , y, z)

И у меня есть функция, которая возвращает кортеж длины два - exampleFunction и два последних элемента кортежа, которые будут построеныиз этого кортежа.

Как я могу сделать это без необходимости вызывать exampleFunction два раза:

(x, fst exampleFunction , snd exampleFunction)

Я просто хочу сделать / достичь чего-то вроде

(x, exampleFunction)

но он жалуется, что кортежи имеют непревзойденную длину (конечно)

Не смотря на то, что let y,z = exampleFunction()

Ответы [ 4 ]

3 голосов
/ 22 марта 2012

Может быть встроенная функция, но пользовательская будет работать так же хорошо.

let repack (a,(b,c)) = (a,b,c)
repack (x,exampleFunction)
2 голосов
/ 22 марта 2012

Я не уверен, стоит ли отдельный ответ, но оба приведенных выше ответа не являются оптимальными, поскольку оба создают избыточный Tuple<'a, Tuple<'b, 'c>> при вызове вспомогательной функции.Я бы сказал, что пользовательский оператор будет лучше как для удобочитаемости, так и для производительности:

let inline ( +@ ) a (b,c) = a, b, c
let result = x +@ yz // result is ('x, 'y, 'z)
1 голос
/ 22 марта 2012

Проблема в том, что функция возвращает a*b, поэтому тип возвращаемого значения становится 'a*('b*'c), что отличается от 'a*'b*'c. Лучшим решением является небольшая вспомогательная функция, такая как

let inline flatten (a,(b,c)) = a,b,c

тогда вы можете сделать

(x,examplefunction) |> flatten
0 голосов
/ 22 марта 2012

У меня есть следующая функция в моем общем файле расширения.Вы можете найти это полезным.

   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
...