Closed zackw closed 10 months ago
I'm thinking about making some changes to or_else
so it's deprecated just in case. You can write something like this to fold a dynamic collection:
fn choose<T>(xs: Vec<Box<dyn Parser<T> + 'static>>) -> Box<dyn Parser<T>>
where
T: 'static,
{
let mut items = xs.into_iter();
let mut res = items.next().unwrap();
for next in items {
res = construct!([res, next]).boxed()
}
res
}
Some double boxing is required but it works fast in my experiments.
Please add a supported method for constructing a "parallel composition" of parsers from a slice or an iterator over impl Parser
.
Will look into that for the next version.
Thanks for the suggested workaround! Absolutely no hurry.
Absolutely no hurry.
Well, replacement is this, the only difference with suggested workaround is that it does not double box a few things.
fn choice<T: 'static>(xs: impl IntoIterator<Item = Box<dyn Parser<T>>>) -> impl Parser<T> {
let mut xs = xs.into_iter();
let mut parser = match xs.next() {
None => return fail("Invalid choice usage").boxed(),
Some(p) => p,
};
for next in xs {
parser = Box::new(ParseOrElse {
this: parser,
that: next.boxed(),
})
}
parser
}
Will release with the next version. Currently rewriting docs :)
that: next.boxed(),
Isn't this double-boxing, since the iterator is already yielding Box
es?
Isn't this double-boxing, since the iterator is already yielding Boxes?
Good catch. Indeed it's double boxing. Fixed :)
0.9.6 is out, choice
is available as a top level function.
I'm working on a tool that has a bunch of very similar subcommands, and so I would like to be able to do something like this:
But there is no
ParseAlternatives
, and the array form ofconstruct!
only takes an array literal all of whose elements are identifiers, so to useconstruct!
I would have to write this instead...which is unacceptably repetitive. (The documentation says you can use function calls in a
construct!([...])
list but when I tried that I got a macro expansion failure -- does it maybe only work for functions that take no arguments?)I did find a hack that works:
... but this requires use of the deprecated
.or_else
method, and also I think it might be double-boxing the parsers.Please add a supported method for constructing a "parallel composition" of parsers from a slice or an iterator over
impl Parser<T>
.(Note that the parallel composition example
a_or_b
on https://docs.rs/bpaf/latest/bpaf/macro.construct.html still talks about.or_else
as if it's OK to use. That's how I knew about it.)(In case you're wondering, this setup doesn't use
positional<TreeWalkMode>("MODE")
for two reasons: there's a second set of subcommands that take different arguments, and I want the mode argument to be accepted only before--
, which Just Works withcommand
but I don't see any way to do it withpositional
.)