zbraniecki / tinystr

A small ASCII-only bounded length string representation.
Apache License 2.0
58 stars 9 forks source link

Recommendation for pattern matching #22

Open sffc opened 4 years ago

sffc commented 4 years ago

On Rust Nightly, I got the following pattern match to work:

const FOO: TinyStr16 = tinystr16!("foo");
const BAR: TinyStr16 = tinystr16!("bar");
match tinystr_input {
    FOO => /* ... */,
    BAR => /* ... */,
    _ => /* ... */,
}

This is fine, but it would be nicer if I could write

match tinystr_input {
    tinystr16!("foo") => /* ... */,
    tinystr16!("bar") => /* ... */,
    _ => /* ... */,
}

Unfortunately, this doesn't seem to work right now.

Is the first example the best way to do pattern matching on TinyStr, or is there a better way?

Manishearth commented 4 years ago

Deref it and match against string

sffc commented 4 years ago

I would expect a string match to be slower than a TinyStr (primitive int) match. I haven't done benchmarks.

Manishearth commented 4 years ago

oh, good point. Might be worth making a macro for matching then

zbraniecki commented 4 years ago

~4 times faster - https://github.com/zbraniecki/tinystr/wiki/Performance#partialeq

sffc commented 4 years ago

I think the compiler has the option to do additional optimization when matches are used, so I don't know if PartialEq tells the whole story. I made a new benchmark to specifically test match statement behavior: #23

I have functions with a 15-leaf match, some with str and some with tinystr. Results for me on my Lenovo X1 Carbon:

String Length Match(&str) Match(tinystr)
4 64.4 ns 35.1 ns
8 58.2 ns 32.0 ns
16 46.7 ns 42.8 ns

So, matching on TinyStr is faster, but not greatly so, especially on TinyStr16.

sffc commented 3 years ago

The solution for pattern matching is to just make a bunch of const TinyStrs, and then you can pass them on the left side of a match statement as the pattern. We should document this with an example.

Manishearth commented 3 years ago

I wonder if tinystr16!() can be written as a const fn now that that's stable

if so it's possible TinyStr::new("en") => ... might work (?)

sffc commented 3 years ago

The problem I previously had with that was const functions don't have a great answer for indexing into variable length strings. We could perhaps have a const function that takes [u8, 4], however.

Manishearth commented 3 years ago

if so it's possible TinyStr::new("en") => ... might work (?)

Ah, this is still not allowed. I think a custom match macro is probably your best bet

There is the vesta crate, a new crate that makes it possible to do generic matches. It may be useful, unsure, but really we can just write our own macro.