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

Make square bracket [] more usable. #3583

Open
crlf0710 opened this issue Mar 8, 2024 · 10 comments
Open

Make square bracket [] more usable. #3583

crlf0710 opened this issue Mar 8, 2024 · 10 comments
Labels
A-syntax Syntax related proposals & ideas T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.

Comments

@crlf0710
Copy link
Member

crlf0710 commented Mar 8, 2024

TL;DR version: Make vec[key]_? = new_value; doesn't panic when key is out of bounds.

For Rust syntax budget, square bracket is perhaps one of the least rewarding current design at all. Every occurrence of square bracket reminds people the potential possibility of panicking. This might be suitable for the "error early if something goes wrong" style application, but for long running services, propagating the panic to the root of the thread callstack might not be a good idea.

This proposes putting an _(underscore) between the bracket and the ? operator to invoke new TryIndex{,Mut} traits instead, returning a Result with an error type, then perform ? operator on that to return early.

@fmease
Copy link
Member

fmease commented Mar 8, 2024

I generally like the idea of TryIndex{,Mut} but I'm not really sold on $expr[$expr]_?. Would $expr[$expr]_ also be allowed to enable for example $expr[$expr]_.unwrap_or($expr)?

@fmease fmease added T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC. A-syntax Syntax related proposals & ideas labels Mar 8, 2024
@kennytm
Copy link
Member

kennytm commented Mar 8, 2024

then perform ? operator on that to return early

The problem being that expr? is not a valid place, so if you treat x[y]_ and x? as independent constructs then x[y]_? = z will never compile.

@crlf0710
Copy link
Member Author

crlf0710 commented Mar 8, 2024

Yes, i meant operationally first call such TryIndex{,Mut} trait method, then call Try trait method and early return etc. Syntactically it's regarded as a whole, not two independent constructs.

@kennytm
Copy link
Member

kennytm commented Mar 8, 2024

The Try trait can't produce any "place" either. Unless you want it to return an &mut X on success and make the lowering implicitly dereference the Try result.

let x: Vec<String>;
let y: usize;
let z: String;
x[y]_? = z;

// equivalent to
*(x.try_index_mut(y)?) = z;
// fn try_index_mut(&mut self, key: usize) -> Result<&mut String, SomeError>;

The implicit dereference means method chaining is not possible without context-dependent lowering rules

x[y]_.inspect_err(|err| warn!(err, "{y} did not exist"))? = z;

@stiff
Copy link

stiff commented Mar 10, 2024

Interesting idea, but underscore looks ugly and inconvenient to type after ]. Maybe something like ?? to not return immediately but to act like expression-level equivalent of ? could work better?

let mut x = vec![1];
println!("{:?}", x[0]??); // Some(1)
println!("{:?}", x[3]??); // None

x[3]?? = 5;
println!("{:?}", x[3]??); // Some(5)
println!("{:?}", x[2]??); // ???

This could also be helpful be with maps:

let mut x = BTreeMap::<usize, usize>::new();

x[&3]?? += 5;
println!("{x:?}"); // { }

x[&3]?? = 5;
println!("{x:?}"); // { 3: 5 }

@kennytm
Copy link
Member

kennytm commented Mar 10, 2024

chained ? is already a valid syntax (and used in real code), you can't repurpose ?? to mean anything else.

fn lol(huh: Option<Option<Option<Option<Option<()>>>>>) -> Option<()> {
    huh????
}

@agreyyy
Copy link

agreyyy commented Mar 30, 2024

you could do !? like in haskell, its a good compromise between the uglyness of _? and ?? already being taken.

let arr = [1,2,3];
arr[3]!?; // returns Option<{Integer}>

@SOF3
Copy link

SOF3 commented Apr 12, 2024

! in Rust is already confusing enough (!matches!()), please don't add even more uses to it

@Alonely0
Copy link

The older I get, the less important I feel syntax-centric discussions are. Here is my proposal, take it or leave it:

array[?index]

As far as I am aware of, that is not taken.

However, we might want to CC the Effects WG, since they might have their own ideas about this as this issue overlaps with their work. Should we continue the discussion on Zulip?

@Einliterflasche

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-syntax Syntax related proposals & ideas T-lang Relevant to the language team, which will review and decide on the RFC. T-libs-api Relevant to the library API team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

8 participants