2016-10-21 4 views
2

녹에서,및 impl s를 (재귀 적으로) 병합 튜플에 사용할 수있는 방법이 있습니까? N 중첩 된 쌍으로 작동재귀 적으로 튜플을 병합하는 방법이 있습니까?

도움이된다면, 뭔가가 중첩 된 튜플 어떤 종류의 일을 연장 할 수 있다면 그것은 더 나은 것

trait FlattenTuple { 
    fn into_flattened(self) -> /* ??? */ 
} 

// such that 
assert_eq!((1, (2, 3)).into_flattened(), (1, 2, 3)) 

좋은 출발을되도록 :

assert_eq!(((1, 2), 2, (3, (4, 5))).into_flattened(), (1, 2, 2, 3, 4, 5)) 

답변

3

"평평한"작은 정의에 대해서는 일 수도 있지만 실제로는 그렇지 않습니다. 가장 구체적인 구현

시작 :

trait FlattenTuple { 
    type Output; 
    fn into_flattened(self) -> Self::Output; 
} 

impl<A, B, C> FlattenTuple for (A, (B, C)) { 
    type Output = (A, B, C); 

    fn into_flattened(self) -> Self::Output { 
     (self.0, (self.1).0, (self.1).1) 
    } 
} 

을 그리고 에 대한 모든 가능한 순열 반복 :

trait FlattenTuple { 
    fn into_flattened(self) -> (u8, u8, u8); 
} 

impl FlattenTuple for (u8, (u8, u8)) { 
    fn into_flattened(self) -> (u8, u8, u8) { 
     (self.0, (self.1).0, (self.1).1) 
    } 
} 

는 그 다음 조금 더 일반적인 만들

impl<A, B, C, D, E, F> FlattenTuple for ((A, B), C, (D, (E, F))) { 
    type Output = (A, B, C, D, E, F); 

    fn into_flattened(self) -> Self::Output { 
     ((self.0).0, (self.0).1, self.1, (self.2).0, ((self.2).1).0, ((self.2).1).1) 
    } 
} 

을 이 두 가지 구현은 당신의 두 c를 커버합니다. ases.

그러나 코드 생성을 통해 원하는 모든 입력 유형을 나열해야합니다. 입력 유형을 "검사"한 다음 출력 유형에 "결합"하는 방법은 없습니다.

당신은 다소 재귀 뭔가를 작성하려고 할 수 있습니다

impl<A, B, C, D, E, F> FlattenTuple for (A, B) 
    where A: FlattenTuple<Output = (C, D)>, 
      B: FlattenTuple<Output = (E, F)>, 
{ 
    type Output = (C, D, E, F); 

    fn into_flattened(self) -> Self::Output { 
     let (a, b) = self; 
     let (c, d) = a.into_flattened(); 
     let (e, f) = b.into_flattened(); 

     (c, d, e, f) 
    } 
} 

을하지만이 빠르게베이스의 경우의 문제로 실행됩니다 : 터미널 42FlattenTuple를 구현하지 않고, 당신이 impl<T> FlattenTuple for T하려고하면 명중합니다 상충되는 형질 구현.

+1

감사 인 경우에만 구현되는이 때문에

where (A, B): Flatten 

rustc가 원하는 추가해야합니다. 내 질문을 게시하기 전에 몇 가지 방법을 시도했지만 상충되는 구현 문제가 계속 발생했습니다.예를 들어'for (A, B)'를 구현하면'(A, (B, C))'와'(A, (B, (C, D)))'등을 구현할 수 없다는 것을 의미합니다. 'N' 중첩 된 쌍의 경우를 해결하기 위해, 그리고 어디에서 절이 바뀌는 지 잘 모르겠습니다. – lloydmeta

+0

@lloydmeta : 예,이 상충되는 구현은 정말 성가신 일입니다. ( –

+0

@MatthieuM. 코드가 모호하지 않아야한다는 것을 알고 있습니다. 아마도 전문화로이 문제를 해결할 수도 있고, 그렇지 않을 수도 있습니다 ... – Shepmaster

0

특수화 및 자동 특성으로 구현했습니다.

github repo


사용

docs.rs

그것은 (파이썬 등) 모든 빈 단위 튜플 ()을 제거 기본적으로

assert_eq!((1, (2, ((3,) (4, 5)),(), 6).flatten(), (1, 2, 3, 4, 5, 6)); 

입니다. 당신은 일반적인 코드를 작성하는 경우


, 당신은 평평하게 출력 튜플의 길이보다 작은 13

관련 문제