rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Make square bracket `[]` more usable.

Open crlf0710 opened this issue 11 months ago • 10 comments

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.

crlf0710 avatar Mar 08 '24 10:03 crlf0710

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 avatar Mar 08 '24 12:03 fmease

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.

kennytm avatar Mar 08 '24 12:03 kennytm

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.

crlf0710 avatar Mar 08 '24 14:03 crlf0710

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;

kennytm avatar Mar 08 '24 15:03 kennytm

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 }

stiff avatar Mar 10 '24 07:03 stiff

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????
}

kennytm avatar Mar 10 '24 10:03 kennytm

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}>

agreyyy avatar Mar 30 '24 14:03 agreyyy

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

SOF3 avatar Apr 12 '24 06:04 SOF3

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?

Alonely0 avatar Apr 12 '24 07:04 Alonely0

I propose the ¿? syntax. That way we keep the style of surrounding brackets but make clear the operation may throw an error. assert_eq!(array¿5?, Ok(42)) and with the try operator let answer_to_everything: i32 = array¿5??;. Additionally a lot of people speak spanish so they already have access to the inverted question mark on their keyboard. everyone else will just have to copy paste until the keyboard layouts catch up.

Einliterflasche avatar Apr 22 '24 11:04 Einliterflasche