Stream: wg-cli

Topic: match retrieval ergonomy


Leo Le Bouter (Jul 15 2020 at 04:01, on Zulip):

hello there!
I am always puzzled when I need to do:

matches.value_of("arg_name").unwrap()

when I could just do (if clap supported it)

matches["arg_name"]

I heard clap is going to make a release soon, if there's no opposition to this change, I'll try make a PR!

@pksunkara @CreepySkeleton

Leo Le Bouter (Jul 15 2020 at 04:10, on Zulip):

Since value_of can be used but also, values_of, which doesnt return the same type, I wonder if it's possible to generically return either of them

Leo Le Bouter (Jul 15 2020 at 04:12, on Zulip):

which would be either &str or an iterator on &str

Leo Le Bouter (Jul 15 2020 at 04:12, on Zulip):

Or we could just say that the ergonomic subscript access is always value_of

Josh Triplett (Jul 15 2020 at 06:12, on Zulip):

Generic return values tend to result in less ergonomic code, requiring either type signatures or turbofish.

Leo Le Bouter (Jul 15 2020 at 06:13, on Zulip):

too bad, would it be acceptable to assume value_of when using array indexing?

Josh Triplett (Jul 15 2020 at 06:21, on Zulip):

Ideally, if moving to a less stringly typed argument handling, the argument type would determine that.

Leo Le Bouter (Jul 15 2020 at 06:30, on Zulip):

@Josh Triplett I see you've got "deserialize into struct" thing now

CreepySkeleton (Jul 17 2020 at 15:22, on Zulip):

I think the biggest problem with the index operator is failability - lack thereof. value[s]_of can fail (return None) if the arg is not required and user (or default value) didn't provide it.

CreepySkeleton (Jul 17 2020 at 15:27, on Zulip):

Come to think of it, a generic returning value might be `Box<dyn Iterator<Item = &str>, I guess.

CreepySkeleton (Jul 17 2020 at 15:27, on Zulip):

Although it won't help you much

CreepySkeleton (Jul 17 2020 at 15:29, on Zulip):

moving to a less stringly typed argument handling

This topic pops up every so often, but nobody was able to even remotely guess something that could possibly work.

CreepySkeleton (Jul 17 2020 at 15:30, on Zulip):

What we're talking about here is heterogeneous container

CreepySkeleton (Jul 17 2020 at 15:31, on Zulip):

Clap is, simply speaking, a dictionary (map)

CreepySkeleton (Jul 17 2020 at 15:32, on Zulip):

It maps _argument identifier_ to a list of _values_ (&[Os]str)

CreepySkeleton (Jul 17 2020 at 15:32, on Zulip):

Identifier is also &str

CreepySkeleton (Jul 17 2020 at 15:34, on Zulip):

What users want is to convert the values to the respective types, but types can be anything

CreepySkeleton (Jul 17 2020 at 15:35, on Zulip):

There's already value_of_t that encapsulates this logic

CreepySkeleton (Jul 17 2020 at 15:36, on Zulip):

I think this is about as far as we can go without any sort of macros. You can't just have a methods with the signature of &self -> SomeType because SomeType will be different for different arguments.

Leo Le Bouter (Jul 17 2020 at 16:25, on Zulip):

@CreepySkeleton most of the time, I provide default values for my arguments, so in that case, index is fine, but of course, that's the inconvenient of it

Leo Le Bouter (Jul 17 2020 at 16:30, on Zulip):

I see it's not written in the README, but can't clap also serve as a configuration management library? wouldnt there be interest in also allowing something like yaml configurations to be passed and the yaml config fills the command line arguments?

Leo Le Bouter (Jul 17 2020 at 16:32, on Zulip):

like a special switch, e.g. --file-arguments /etc/example/example.yaml

pksunkara (Jul 19 2020 at 10:40, on Zulip):

There were some discussions about it, but it's not a high priority for us. You could take a look around and contribute to the discussions.

CreepySkeleton (Jul 19 2020 at 17:43, on Zulip):

@Leo Le Bouter ArgMatches doesn't know whether "cfg"for example has default value or not. Most importantly, we would need this kind in information to be encoded in type system so the index op could distinguish and return either option or the value itself, depending.

CreepySkeleton (Jul 19 2020 at 17:44, on Zulip):

But identifiers don't have this kind of type system info attached, it's just &str

CreepySkeleton (Jul 19 2020 at 17:44, on Zulip):

Yes, we could add such an impl in addition to value_of

CreepySkeleton (Jul 19 2020 at 17:45, on Zulip):

But how to encode the difference between value_of and value_of_os in it?

CreepySkeleton (Jul 19 2020 at 17:45, on Zulip):

It's vital when it comes to file paths

CreepySkeleton (Jul 19 2020 at 18:04, on Zulip):

Actually, when trait impl specialization finally lands, we could do something like:

// The traits are mutually exclusive

trait ClapFromStr: !ClapFromOsStr {
    fn from_str(&str) -> Self;
}

trait ClapFromOsStr: !ClapFromStr {
    fn from_os_str(&OsStr) -> Self;
}

// everything that requires the argument to be valid utf-8
impl ClapFromStr for &str, String, i64, ...

// everything that doesn't have to be valid UTF-8
impl ClapFromOsStr for Path, PathBuf, ...

// impl that uses value_of
impl<R: ClapFromStr> Index<&str> for R;

// impl that uses value_of_os
impl<R: ClapFromOsStr> Index<&str> for R;

But we need to be able to mark the traits as mutually exclusive.

Leo Le Bouter (Jul 19 2020 at 20:30, on Zulip):

@CreepySkeleton Cool! Glad to know it's trait impl specialization that helps it!

CreepySkeleton (Jul 19 2020 at 20:31, on Zulip):

No wait, we don't need it!

Leo Le Bouter (Jul 19 2020 at 20:32, on Zulip):

o.o!

CreepySkeleton (Jul 19 2020 at 20:32, on Zulip):

ALl we ned is to impl it for the interesting types one by one

CreepySkeleton (Jul 19 2020 at 20:32, on Zulip):

like impl for String, u64, Path, etc

CreepySkeleton (Jul 19 2020 at 20:32, on Zulip):

But there's another problem

CreepySkeleton (Jul 19 2020 at 20:32, on Zulip):

Guess what?

Leo Le Bouter (Jul 19 2020 at 20:33, on Zulip):

and then matches["test"] returns what?

CreepySkeleton (Jul 19 2020 at 20:33, on Zulip):

It returns R

CreepySkeleton (Jul 19 2020 at 20:33, on Zulip):

Which should be inferred from context in most cases

Leo Le Bouter (Jul 19 2020 at 20:33, on Zulip):

okay, interesting

CreepySkeleton (Jul 19 2020 at 20:33, on Zulip):

The real problem is that conversion themself can fail

Leo Le Bouter (Jul 19 2020 at 20:34, on Zulip):

didnt know you could actually return generics from indexing

CreepySkeleton (Jul 19 2020 at 20:34, on Zulip):

For example, what if you're trying to convert it to u64 but the value is "foo"?

Leo Le Bouter (Jul 19 2020 at 20:34, on Zulip):

@CreepySkeleton then macro to the rescue?

CreepySkeleton (Jul 19 2020 at 20:35, on Zulip):

???

Leo Le Bouter (Jul 19 2020 at 20:35, on Zulip):

@CreepySkeleton I mean no indexing, just a macro

CreepySkeleton (Jul 19 2020 at 20:35, on Zulip):

We already have that

CreepySkeleton (Jul 19 2020 at 20:35, on Zulip):

it's called value_of_t

CreepySkeleton (Jul 19 2020 at 20:35, on Zulip):

and it's not a macro

CreepySkeleton (Jul 19 2020 at 20:35, on Zulip):

*Will have in 3.0

CreepySkeleton (Jul 19 2020 at 20:36, on Zulip):

I... I actually feel enlighten

CreepySkeleton (Jul 19 2020 at 20:37, on Zulip):

What if App::arg took not Arg but some generic R that implements ArgTrait

Leo Le Bouter (Jul 19 2020 at 20:38, on Zulip):

@CreepySkeleton Is it possible to check all accesses of the indexing and do checks at the start of the program for correct types?

Leo Le Bouter (Jul 19 2020 at 20:38, on Zulip):

with the type system?

Leo Le Bouter (Jul 19 2020 at 20:38, on Zulip):

or encode the type in the declaration of arguments

CreepySkeleton (Jul 19 2020 at 20:39, on Zulip):

I think it might be possible for some number of select types, but not in general

CreepySkeleton (Jul 19 2020 at 20:39, on Zulip):

or encode the type in the declaration of arguments

That's what I'm thinking

CreepySkeleton (Jul 19 2020 at 20:40, on Zulip):

I need to fork clap and publish my clap-killer arg parser at this point, muhaha!

Leo Le Bouter (Jul 19 2020 at 20:40, on Zulip):

aha I'm glad!

Leo Le Bouter (Jul 19 2020 at 20:44, on Zulip):

@CreepySkeleton I would really like a shorthand for .unwrap() on Option

Leo Le Bouter (Jul 19 2020 at 20:46, on Zulip):

could the * operator be used as such?

Leo Le Bouter (Jul 19 2020 at 20:46, on Zulip):

*matches.value_of("test")?

Leo Le Bouter (Jul 19 2020 at 20:46, on Zulip):

panics if invalid?

Leo Le Bouter (Jul 19 2020 at 20:47, on Zulip):

value_of is too long too

Leo Le Bouter (Jul 19 2020 at 20:48, on Zulip):

val could be ok

Leo Le Bouter (Jul 19 2020 at 20:48, on Zulip):

or get

CreepySkeleton (Jul 19 2020 at 21:00, on Zulip):

The problem is that it can fail because of two unrelated reasons - the argument wasn't provided and the argument couldn't be parsed as the resulted type.

CreepySkeleton (Jul 19 2020 at 21:01, on Zulip):

Should it panic in both cases?

CreepySkeleton (Jul 19 2020 at 21:01, on Zulip):

The problem with get is that the famous slice::get return Option

CreepySkeleton (Jul 19 2020 at 21:02, on Zulip):

I would prefer to follow the example

Last update: Apr 15 2021 at 01:30UTC