Rust/combine choice combinator + array/vec

#1
  1. Here is the code. It compiles:
use combine_language::LanguageEnv;
use combine::stream::easy;
use combine::choice;

#[test]
fn test_00() {

    let env: LanguageEnv<easy::Stream<&str>> = unimplemented!();

    let rops = "1 2 3 4 5 6 7 8"
        .split_whitespace()
        .map(|s: &str| env.reserved_op(s))
        .collect::<Vec<_>>();


    let a = env.reserved_op("a");
    let b = env.reserved_op("b");

    let t = choice([a, b]);

    // this fails to compile
    // let t1 = choice(&[a, b]);
    // let t2 = choice(rops);
    // let t3 = choice(rops.as_slice());
}

  1. I need to figure out how to make either t2 or t3 compile.

t2:

   |
23 |     let t2 = choice(rops);
   |              ^^^^^^ the trait `combine::parser::choice::ChoiceParser` is not implemented for `std::vec::Vec<combine_language::Lex<'_, '_, combine_language::Reserved<'_, '_, combine::stream::easy::Stream<&str>>>>`
   |
   = note: required by `combine::parser::choice::choice`

error: aborting due to previous error

t3:

   |
24 |     let t3 = choice(rops.as_slice());
   |              ^^^^^^ the trait `combine::parser::choice::ChoiceParser` is not implemented for `&[combine_language::Lex<'_, '_, combine_language::Reserved<'_, '_, combine::stream::easy::Stream<&str>>>]`
   |
   = help: the following implementations were found:
             <[P; 15] as combine::parser::choice::ChoiceParser>
             <[P; 1] as combine::parser::choice::ChoiceParser>
             <[P; 21] as combine::parser::choice::ChoiceParser>
             <[P; 31] as combine::parser::choice::ChoiceParser>
           and 30 others
   = note: required by `combine::parser::choice::choice`

error: aborting due to previous error

this is surprising as the docs, https://docs.rs/combine/3.6.7/combine/parser/choice/fn.choice.html , claims it works on “a slice or an array”

Thanks!i

#2

It looks like it requires a mutable slice. Try choice(&mut rops[..]) or choice(rops.as_mut_slice()).

1 Like
#3
  1. Thanks. Adding a mut fixed it.

  2. How did you know to try adding a mut ?

#4

The argument to choice must implement ChoiceParser. In the list of implementations there is an impl for mutable references:

impl<'a, P> ChoiceParser for &'a mut P
where P: ?Sized + ChoiceParser

and one for slices:

impl<I, O, P> ChoiceParser for [P]
where
    I: Stream,
    P: Parser<Input = I, Output = O>,

Since a slice is dynamically-sized, it can’t be passed by value. But it can be passed by reference, and the first of these impls allows us to pass &mut [P].