Skip to content

? patterns #2012

Open
Open
@devyn

Description

@devyn

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
}

Activity

burdges

burdges commented on Jun 1, 2017

@burdges

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

burdges commented on Jun 1, 2017

@burdges

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

eddyb commented on Jun 1, 2017

@eddyb
Member

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

burdges

burdges commented on Jun 1, 2017

@burdges

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

devyn commented on Jun 1, 2017

@devyn
Author

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

mgattozzi commented on Jun 1, 2017

@mgattozzi
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

jD91mZM2 commented on Jun 1, 2017

@jD91mZM2

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

mgattozzi commented on Jun 1, 2017

@mgattozzi
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

eddyb commented on Jun 1, 2017

@eddyb
Member

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

jD91mZM2

jD91mZM2 commented on Jun 1, 2017

@jD91mZM2

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

burdges commented on Jun 1, 2017

@burdges

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

Stebalien commented on Jun 1, 2017

@Stebalien
Contributor
nixpulvis

nixpulvis commented on Jun 29, 2017

@nixpulvis

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

joshtriplett commented on Jul 27, 2017

@joshtriplett
Member

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

added
T-langRelevant to the language team, which will review and decide on the RFC.
on Dec 6, 2017
Centril

Centril commented on Apr 26, 2018

@Centril
Contributor

Triage ping: Any updates on this?

scottmcm

scottmcm commented on Apr 26, 2018

@scottmcm
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

glaebhoerl commented on Apr 26, 2018

@glaebhoerl
Contributor

let try 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @devyn@eddyb@joshtriplett@Stebalien@burdges

        Issue actions

          ? patterns · Issue #2012 · rust-lang/rfcs