2016-08-25 2 views
3

Rust 필자는 반복자를 작성하고 콜백 함수를 사용하는 코드에서 이터레이터를 변환하기 시작했습니다.다중 논리 분기를 지원하는 반복기를 작성하는 가장 좋은 방법은 무엇입니까?

함수의 여러 분기에서 콜백을 사용하는 코드가 녹 제거기로 완전히 변환되지 않은 문제가 발생했습니다.

의사 코드를 제공하십시오.

// function using callbacks where the caller can exit at any time, 
// can be used in a similar way to an iterator. 
fn do_stuff(args, callback_fn(cb_args)) { 
    // define a, b, c... args 
    if callback_fn(a, b, 0) == false { return; } 
    for i in 0..n { 
     if callback_fn(c, d, i) == false { return; } 
    } 
    if callback_fn(e, f, -1) == false { return; } 
} 

반복기로 변환하면 각 분기를 나타내는 상태를 저장해야하므로 다소 번거롭습니다. 위의 예에

impl Iterator for MyStruct { 
    fn next(&mut self) -> Option<MyResult> { 
     let out = match (self.state) { 
      0 => { 
       self.state += 1; 
       Some(MyResult(self.a, self.b, 0)) 
      }, 
      1 => { 
       self.i += 1; 
       if self.i == self.n { 
        self.state += 1; 
       } 
       Some(MyResult(self.c, self.d, self.i - 1)) 
      }, 
      2 => { 
       self.state += 1; 
       Some(MyResult(self.e, self.f, -1)) 
      }, 
      _ => { 
       None 
      }, 
     } 
     return out; 
    } 
// --- snip 

,이 (어색 경우) 틀림 수용. 루프를 여러 개 사용하는 경우와 변수 범위를 고려하여 상태를 추적하는 것이 훨씬 어렵습니다.


나는이 시도하지 않았지만, 나는 대부분의 경우에 덜 당시 이상적인 해결되는이 달성하기 위해 몇 가지 방법이 있습니다 상상하십시오 구축 콜백 버전을 사용

  • 는, 벡터, 그 다음 iterating ...
    (작동하지만 이터레이터를 사용하는 목적을 상실하고, 조기 종료 할 수없고 예를 들어 전체 데이터 세트를 작성하지 않아도 됨).
  • 콜백 버전과 비슷한 논리를 사용하는 스레드와 통신하는 반복기를 작성합니다.
    (가능한 경우 OS 스레드를 만드는 오버 헤드로 인해 많은 경우에 좋지 않은 선택이됩니다.)

    덜 복잡한 논리에 주어진 예와 같이 반복자를 작성하는 방법이있다 : 위의 해결 방법 또한

?
이상적으로 콜백을 사용하는 예제와 비슷합니다.
그렇지 않으면이 문제를 해결할 수있는 다른 방법이 있습니까?

아니면 단순히 Rust에서 지원되지 않습니까? (그들은 최고 수준의 기능을 가진 유비쿼터스에 있기 때문에 여기에 예로서 콜백을 사용하여 콜백 대신 수율을 사용하여)


주, 같은 논리는 파이썬 발전기에서 나오는 적용됩니다.

+0

if-else 대신 'match'를 사용하고'return'을 생략하면 [https : //gist.github.co.kr/LukasKalbertodt/9f2e73305880e586231b76ef4b6a948c) 이미 그렇지 않습니까? :) –

+0

@LukasKalbertodt, 일치를 사용하도록 수정했습니다. 그러나 문제의 근원을 다루지는 않습니다. 반복자에 콜백을 사용하는 복잡한 함수를 이동하는 것은 그리 간단하지 않으며 결과 코드는 종종 읽기 쉽거나 쉽지 않습니다. 유지 - 예 : https://gitlab.com/ideasman42/rust-simple-examples/blob/master/draw_poly_2d_callback/src/main.rs. – ideasman42

답변

5

C# 및 Python과 같은 언어는 yield 키워드를 사용하여 작성된 메소드에서 반복자를 생성하는 방법을 제공합니다. Rust 1.11 현재 언어에는 이러한 기능이 없습니다. 그러나 이러한 기능은 (see RFC) (실제로는 yield is a reserved keyword!)으로 계획되어 있으므로 C#에서와 같이 작동합니다 (즉, 컴파일러에서 Iterator에 필요한 상태 및 구현을 사용하여 구조체를 생성합니다).

그동안이 기능을 제공하려는 프로젝트 인 Stateful을 시도해 볼 수 있습니다. (This blog post은 Stateful 작품과 관련된 과제를 설명합니다.)

관련 문제