Не следил активно за изменениями, но в своё время прочёл уже устаревшую Rust by Example и туториалы с официального сайта. Теперь вот начал неспешно читать новую «книгу», которая заменила собой старые гайды. Но некоторые моменты вызывают удивление. Знаю, что тут есть пару человек, которые в языке неплохо разбираются, так что может обьяснят почему сделали именно так.
1. Функции высшего порядка. Старый вариант:
fn test(f: |int| -> int) -> int
fn test<F: Fn(i32) -> i32>(f: F) -> i32
fn test<F, G>(x: i32, f: F, g: G) -> i32
where F: Fn(i32) -> i32, G: Fn(i32) -> i32 {
}
That is because in Rust each closure has its own unique type. So, not only do closures with different signatures have different types, but different closures with the same signature have different types, as well!
По моему, они взяли худшее из обоих вариантов. Есть в этом какой-то смысл?
Опять же where тут, в отличии от хаскеля, выглядит коряво. Мы и так сначала заявляем, что вот у нас есть типы (<F, G>), потом ещё раз про них говорим (f: F, g: G) и наконец-то определяем их. Я бы ещё понял, если бы where позволяло отказаться от указания типов в угловых скобках.
2. Closures.
В книге этот момент не поясняется, но всюду используется вариант |&:|. Раньше в гайдах писали просто ||. Правильно понимаю, что можно задавать как будут захватываться переменные? А на уровне отдельных переменных можно?
3. Named arguments, variable arguments.
В описании методов присутствует следующее:
Rust doesn't have method overloading, named arguments, or variable arguments. We employ the builder pattern instead.
Ну с перегрузкой ладно - аргументы за её отсутствие есть, да и некоторые языки без неё обходятся - жить можно. А вот с остальным? Раньше это всё обсуждалось, надеюсь не похоронили окончательно? Потому что страница кода с реализацией «билдера», приводимая как пример, совсем не вдохновляет.