10

現在、Rust で単純なパーサー コンビネーター ライブラリを実装しようとしています。mapそのために、パーサーの結果を変換する汎用関数が必要です。

問題は、クロージャーを保持する構造体をコピーする方法がわからないことです。例はMap、次の例の構造体です。mapFunction前のパーサーの結果を受け取り、新しい結果を返す関数を格納するフィールドがあります。Mapそれ自体がパーサーであり、他のパーサーとさらに組み合わせることができます。

ただし、パーサーを組み合わせるには、それらをコピー可能にする (Clone特性をバインドする) 必要がありますが、これをどのように提供すればよいMapでしょうか?

例: (疑似コードのみ、コンパイルされない可能性が高い)

trait Parser<A> { // Cannot have the ": Clone" bound because of `Map`.
    // Every parser needs to have a `run` function that takes the input as argument
    // and optionally produces a result and the remaining input.
    fn run(&self, input: ~str) -> Option<(A, ~str)>
}

struct Char {
    chr: char
}

impl Parser<char> for Char {
    // The char parser returns Some(char) if the first 
    fn run(&self, input: ~str) -> Option<(char, ~str)> {
        if input.len() > 0 && input[0] == self.chr {
            Some((self.chr, input.slice(1, input.len())))
        } else {
            None
        }
    }
}

struct Map<'a, A, B, PA> {
    parser: PA,
    mapFunction: 'a |result: A| -> B,
}

impl<'a, A, B, PA: Parser<A>> Parser<B> for Map<'a, A, B, PA> {
    fn run(&self, input: ~str) -> Option<(B, ~str)> {
        ...
    }
}

fn main() {
    let parser = Char{ chr: 'a' };
    let result = parser.run(~"abc");

    // let mapParser = parser.map(|c: char| atoi(c));

    assert!(result == Some('a'));
}
4

1 に答える 1