2017-05-11 28 views
5

F # 'de açıkça boyutlandırma olmadan keyfi boyuttaki tuple'ları düzleştirmenin bir yolu var mı? F # iç içe yerleştirilmiş tuple

(fun ((((a0,a1),a2),b),c) -> (a0,a1,a2,b,c)) 

bir not olarak ben FParsec JOIN ile bu tür alıyorum ama genellikle mevcut olsaydı yeteneği uygun olacaktır.

sayesinde

+4

FParsec'te, daha fazla ayrıştırıcıyı birleştirmek için 'tuple3, tuple4, tuple5' veya' pipe3, pipe4, pipe5' işlevlerini kullanabilirsiniz; bu, böyle bir şeye olan ihtiyacınızı ortadan kaldırabilir. – TheInnerLight

+0

@TheInnerLight great point Teşekkürler –

cevap

3

Kolayca bunu yapamaz, ancak yansıma biraz mümkündür:

let isTuple tuple = 
    Microsoft.FSharp.Reflection.FSharpType.IsTuple(tuple.GetType()) 

let tupleValues (tuple : obj) = 
    Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields tuple |> Array.toList 

let rec flatten tupleFields = 
    tupleFields |> List.collect(fun value -> 
     match isTuple value with 
     | true -> flatten (tupleValues value) 
     | false -> [value] 
    ) 

let tupleToList (tuple : obj) = 
    if isTuple tuple 
     then Some (tupleValues tuple |> flatten) 
     else None 

Yani, örneğin:

let s = tupleToList ((100,101,102,103),1,2,3,(4,5)) 

size verecek :

[100; 101; 102; 103; 1; 2; 3; 4; 5] 

NOT: Bu CEV er kodu bulunan here dayanmaktadır.

+1

Yansıma kesinlikle mutlak bir son çare olmalı; Tip güvenliği ve performans açısından genellikle korkunç. @TheInnerLight'ın ne dediğini ve FParsec'in özel işlevlerini kullanmayı çok isterim. – Tarmil

+1

@Tarmil Sana katılıyorum Tarmill - sadece verilen cevapta Sean'ın cevabı doğruymuş. –

İlgili konular