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

syntax: destructuring structs, tuple structs and tuples should be consistent #5830

Closed
thestinger opened this issue Apr 11, 2013 · 17 comments
Closed
Labels
A-grammar Area: The grammar of Rust P-low Low priority

Comments

@thestinger
Copy link
Contributor

These are minor nitpicks, but they might as well be fixed before it's too late.

struct Foo(int, int, int, int);
struct Bar{a: int, b: int, c: int, d: int};

Ignoring all the fields is inconsistent:

let Foo(*) = Foo(5, 5, 5, 5);
let Bar(_) = Bar{a: 5, b: 5, c: 5, d: 5};

It doesn't seem like it's currently possible to ignore all fields of a regular tuple.

I think this would be nicer:

let Foo(*) = Foo(5, 5, 5, 5);
let Bar(*) = Bar{a: 5, b: 5, c: 5, d: 5};
let (*) = (5, 5, 5, 5);

With a struct, you can ignore "the rest", but you can't with a tuple struct or tuple:

let Bar{b: b, _} = Bar{a: 5, b: 5, c: 5, d: 5};

This would be more consistent, and similar to destructuring fixed-size vectors:

let Foo(a, b, *) = Foo(5, 5, 5, 5);
let Foo(*, d) = Foo(5, 5, 5, 5);
let (a, b, *) = (5, 5, 5, 5);
let (*, c, d) = (5, 5, 5, 5);
let Bar{b: b, *} = Bar{a: 5, b: 5, c: 5, d: 5};

An underscore would mean ignoring one field.

@sethfowler
Copy link

Thanks for opening this issue, @thestinger!

@catamorphism
Copy link
Contributor

Nominating for milestone 2, backwards-compatible

@bblum
Copy link
Contributor

bblum commented Jun 20, 2013

this is a great issue; i endorse it

@graydon
Copy link
Contributor

graydon commented Aug 22, 2013

accepted for backwards-compatible milestone

@glaebhoerl
Copy link
Contributor

How about .. instead of *? Already has the matches multiple fields connotation.

@brson
Copy link
Contributor

brson commented Nov 1, 2013

Here's a more complete test case. The stuff that's not commented out works (and probably shouldn't), and the stuff that's commented out should.

struct Foo(int, int, int, int);
struct Bar{a: int, b: int, c: int, d: int}

fn main() {
    let Foo(*) = Foo(5, 5, 5, 5);
    //let Bar(*) = Bar{a: 5, b: 5, c: 5, d: 5};                                                                                                                                  
    let Bar{_} = Bar{a: 5, b: 5, c: 5, d: 5};
    //let (*) = (5, 5, 5, 5);                                                                                                                                                    
    //let Foo(a, b, *) = Foo(5, 5, 5, 5);                                                                                                                                        
    //let Foo(*, d) = Foo(5, 5, 5, 5);                                                                                                                                           
    //let (a, b, *) = (5, 5, 5, 5);                                                                                                                                              
    //let (*, c, d) = (5, 5, 5, 5);                                                                                                                                              
    //let Bar{b: b, *} = Bar{a: 5, b: 5, c: 5, d: 5};                                                                                                                            
    let Bar{b: b, _} = Bar{a: 5, b: 5, c: 5, d: 5};
    /*match [5, 5, 5, 5] {                                                                                                                                                       
        [a, *] => { }                                                                                                                                                            
    }*/
    /*match [5, 5, 5, 5] {                                                                                                                                                       
        [*, b] => { }                                                                                                                                                            
    }*/
    /*match [5, 5, 5, 5] {                                                                                                                                                       
        [a, *, b] => { }                                                                                                                                                         
    }*/
    match [5, 5, 5] {
        [a, .._] => { }
    }
    match [5, 5, 5] {
        [.._, a] => { }
    }
    match [5, 5, 5] {
        [a, .._, b] => { }
    }
}

@brendanzab
Copy link
Member

Tuples:

let Tup(.._) = Tup(1, false);
let (first, second, ..middle, last) = (1, "hi", false, 2, 3.0);
assert_eq!(first, 1);
assert_eq!(second, "hi");
assert_eq!(middle, (false, 2));
assert_eq!(last, 3.0)

Structs:

let Struct { .._ } = Struct { b: true, s: "hi", i: 23, f: 2.0 };

// Error, 'rest' cannot be named in structs
let Struct { x, ..end } = Struct { b: true, s: "hi", i: 23, f: 2.0 };

let Struct { s: s, i: i, .._ } = Struct { b: true, s: "hi", i: 23, f: 2.0 };
assert_eq!(s, "hi");
assert_eq!(i, 2.0);

let Struct { b, s, .._, f } = Struct { b: true, s: "hi", i: 23, f: 2.0 };
assert_eq!(b, true);
assert_eq!(s, "hi");
assert_eq!(f, 2.0);

@brson
Copy link
Contributor

brson commented Nov 1, 2013

If we wanted to use * as a generic pointer deref pattern it would make the parser simpler to use ...

@brson
Copy link
Contributor

brson commented Nov 1, 2013

The semantics of using .. for pulling out tuples is complicated. With vectors it's (surely) just a slice.

@brendanzab
Copy link
Member

I would also add that for structs its a little ugly, so yeah - not sure. Just an idea.

@brson
Copy link
Contributor

brson commented Nov 1, 2013

If we did go with .. then I would want just .. to mean 'everything else', not .._.

@brendanzab
Copy link
Member

You could just remove the ability you destructure the tail for tuples, and go with:

let (first, second, .., last) = ...;
let Struct { s: s, i: i, .. } = ...;

Either way, going with .. is fits nicer with vector destructuring, and reduces the amount of overloading on *, which is already under strain.

@nikomatsakis
Copy link
Contributor

+1 for ..

For that matter, in vector patterns, we could probably make the _
implicit if the next token is a comma or closing brace etc. i.e.,
[a, b, .., d]

@brson
Copy link
Contributor

brson commented Nov 8, 2013

I'm going to make the existing syntax consistent with .. and open a separate issue for adding .. to tuples and tuple-structs, since that's a deeper change that I don't know if I want to tackle personally.

bors added a commit that referenced this issue Nov 19, 2013
This replaces `*` with `..` in enums, `_` with `..` in structs, and `.._` with `..` in vectors. It adds obsolete syntax warnings for the old forms but doesn't turn them on yet because we need a snapshot.

#5830
@alexcrichton
Copy link
Member

Renominating for demilestoning. We now have consistent "ignore the rest of these elements" across all patterns except for ignoring multiple fields in tuples (and tuple-like enum variants). We can always add those parts later (it's a backwards-compatible change), and I'm not sure that 1.0 should block on adding those features.

Additionally, I think this bug should be closed in favor of a new one which is up to date with the current state of affairs.

@pnkfelix
Copy link
Member

Switching to P-low because its almost done, and the only thing(s?) remaining are back-compat and low priority for post-1.0.

@alexcrichton
Copy link
Member

Closing in favor of #10365, which is what remains to be done.

flip1995 pushed a commit to flip1995/rust that referenced this issue Jul 26, 2020
trait_sel: only test predicates w/ no substs

r? @ghost
changelog: none
calebcartwright pushed a commit to calebcartwright/rust that referenced this issue Oct 23, 2023
* Use matches!() macro to improve readability

1. Use `matches!()` macro in `is_line_comment` and `is_block_comment` to
improve readability.
2. Very sightly improve the wording of the doc comment for these two functions.

* Update wording on doc comment on is_line_comment()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-grammar Area: The grammar of Rust P-low Low priority
Projects
None yet
Development

No branches or pull requests