d47081
December 18, 2024, 8:12am
1
I have good old, tested function in PHP to work with multi-local plural translations:
private function _plural(int $number, array $texts)
{
$cases = [2, 0, 1, 1, 1, 2];
return $texts[(($number % 100) > 4 && ($number % 100) < 20) ? 2 : $cases[min($number % 10, 5)]];
}
almost converted to Rust, but stuck with min function replacement:
fn plural(number: usize, strings: &[&str]) {
let cases = [2, 0, 1, 1, 1, 2];
strings[if (number % 100) > 4 && (number % 100) < 20 {
2
} else {
cases[min(number % 10, 5)] // here
}]
}
AI gives me following alternative:
fn min_in_array<T: Ord>(arr: &[T]) -> Option<&T> {
arr.iter().min()
}
not sure it's correct, and yet nothing native in STD asset.
fogzot
December 18, 2024, 8:20am
2
You probably want cmp::min(number % 10, 5)
.
2 Likes
Pretty sure you can just use std::cmp::min
and it'll work as expected. This function is pretty codegolfy though, so making it more readable wouldn't be a bad idea.
3 Likes
This compiles. Don't know if you actually wanna deal with the string references or just clone them.
fn plural<'a>(number: usize, strings: &[&'a str]) -> &'a str {
let cases = [2, 0, 1, 1, 1, 2];
strings[if (number % 100) > 4 && (number % 100) < 20 {
2
} else {
cases[std::cmp::min(number % 10, 5)]
}]
}
EDIT
Sorry for the weird code highlighting. I don't know what is happening.
3 Likes
d47081
December 18, 2024, 8:32am
5
Thanks, guys!
just last question (even it's work) - is the lifetimes defined properly?
fn plural<'a>(number: usize, strings: &'a [&'a str]) -> &'a str {
let cases = [2, 0, 1, 1, 1, 2];
strings[if (number % 100) > 4 && (number % 100) < 20 {
2
} else {
cases[std::cmp::min(number % 10, 5)]
}]
}
d47081
December 18, 2024, 8:35am
6
Thanks for reply, just wrote same lifetimes construction
I think it's better to keep strings referenced, without clone or the ownership taking. Maybe later I will make some crate to integrate this function everywhere.
Mine is slightly different from yours. I only put 'a
on the &'a str
but not on the slice &[&'a str]
in the second argument.
1 Like
d47081
December 18, 2024, 8:42am
8
ah, really!
p.s. also shortened this function to
fn plural<'a>(n: usize, s: &[&'a str]) -> &'a str {
s[if (n % 100) > 4 && (n % 100) < 20 {
2
} else {
[2, 0, 1, 1, 1, 2][std::cmp::min(n % 10, 5)]
}]
}
If somebody want the subject to work with this function
let result = plural(total, &["match", "matches", "matches"]); // en version
p.p.s sometimes I miss ?
/:
sugar for if
/else
in Rust..
p.p.p.s just created new crate .
You can also use the method min
from the Ord
trait:
(n % 10).min(5)
// or 5.min(n % 10)
// or even usize::min(n % 10, 5)
Honestly I believe that std::cmp::min/max
only exist because Ord
didn’t have those methods before Rust 1.21.
1 Like
d47081
December 18, 2024, 11:32am
10
Thank you, replaced with usize
- just not sure about performance (if it has any sense here)
There’s zero difference. It’s just a matter of preference.
2 Likes