Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

? patterns #2012

Open
devyn opened this issue May 31, 2017 · 17 comments
Open

? patterns #2012

devyn opened this issue May 31, 2017 · 17 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@devyn
Copy link

devyn commented May 31, 2017

I've written a lot of code like this for libraries that use Iterators where the Item is a Result:

for line_r in stdin.lock().lines() {
    let line = line_r?;

    // do something with line
}

I think it would be awesome if we could just relocate the ? to the pattern, like this:

for line? in stdin.lock().lines() {
    // do something with line
}
@burdges
Copy link

burdges commented Jun 1, 2017

You can do this using while let already, so you should be asking for for let which seemingly does not appear in the while let RFC.

@burdges
Copy link

burdges commented Jun 1, 2017

Oh you actually want an ? type error to propagate if that part does not unwrap. That makes sense. I'd still think you'd need an actual pattern match first, meaning for let.

@eddyb
Copy link
Member

eddyb commented Jun 1, 2017

@burdges What do you mean? for takes a pattern, e.g. for &(a, b) in slice_of_pairs is valid.

@burdges
Copy link

burdges commented Jun 1, 2017

I see, for needs an irrefutable pattern, which this pat? proposal is. There is no need for for let as just sugar for let _iter = ..; while let Some(pat) = _iter.next() { .. }.

@devyn
Copy link
Author

devyn commented Jun 1, 2017

Yeah, exactly, I think it would make sense just as a general pattern too:

let foo? = bar();

would be allowed to be equivalent to:

let foo = bar()?;

@mgattozzi
Copy link
Contributor

That seems a bit confusing. It makes it seem like the ? in let foo? is part of the identifier here. I think it would make more sense to have it like this in your original example:

for line in stdin.lock().lines()? { // Where each new item has the question mark operator work on it
    // do something with line
}

@jD91mZM2
Copy link

jD91mZM2 commented Jun 1, 2017

Doing ? at the end like in @mgattozzi probably isn't a good idea, since that's currently how you would unwrap the return value from lines() - not each item.

@mgattozzi
Copy link
Contributor

Right. I wasn't clear, I should have said an iterator after in with a question mark would do the unwrapping of the value returned while iterated through. lines by itself doesn't return a result so this wouldn't work as is today anyways.

@eddyb
Copy link
Member

eddyb commented Jun 1, 2017

The only syntax I could see being added, that's not in the pattern, is for x in? xs.

@jD91mZM2
Copy link

jD91mZM2 commented Jun 1, 2017

for? x? in? xs??!?!?!?!

EDIT: Actually, that isn't an absolutely horrible idea. Maybe we could have like for line in stdin.lock().lines()?!... But yeah, probably not.

@burdges
Copy link

burdges commented Jun 1, 2017

I think it should extend pattern matching in general, not be special syntax for for.

Ideas around coroutines, futures, etc. could perhaps be used to generalize for to support early return, so maybe :

for line in stdin.lock().lines().as_future() { .. } 

I despise that idea though because if for loops can return early then a crate changing a type could wreak havoc in the logic of its users. I guess that's why folks are discussing for? .. in? .. etc.

As an aside, I'd write the original code to avoid introducing another name. I might insert context not allowed by From<io:Result> too. It looks more reasonable then :

for line in stdin.lock().lines() {
    let line = line.map_err( |e| MyError::LineBarfed("context",e) )?;
    ...

I'm dubious about incorporating map_err like that :

let e = |e| MyError::LineBarfed("context",e);
for (line?e) in stdin.lock().lines() { ...

@Stebalien
Copy link
Contributor

@nixpulvis
Copy link

I'm still biased against the addition of the ? operator in general... That said I'd strongly avoid putting it near the identifier, seeing as it would read more like "this thing IS an option" instead of "this thing unwraps an option".

@joshtriplett
Copy link
Member

I've wanted something like this for a while, and I'd like to see some reasonable syntax for it.

@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Dec 6, 2017
@Centril
Copy link
Contributor

Centril commented Apr 26, 2018

Triage ping: Any updates on this?

@scottmcm
Copy link
Member

That for loop example is compelling, but having this in the pattern scares me.

It reminds me too much of ref and &, and the confusion caused by having both

let x = &y;
let ref x = y;

So I wouldn't want to end up with debates about which of the following to use:

let x = y?:
let x? = y;

Not that I have a good solution to propose...

@glaebhoerl
Copy link
Contributor

let try 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests