В Rust мне нужен числовой тип с свойством иметь симметричную область вокруг 0. Если число n является допустимым значением, то также должно быть действительным число -n. Как я могу обеспечить безопасность типа во время инициализации и арифметики? Как было бы лучше реализовать модульную и насыщенную арифметику по типу?Как создать числовой тип с ограниченным типом?
Простейший пример задачи:
type MyNumber = i8; // Bound to domain (-100, 100)
fn main() {
let a = MyNumber(128); // Doesn't panic when 128 > 100
}
Есть несколько соображений, чтобы сделать, и я попытался различные решения. Я буду избегать общего программирования для приведенных ниже примеров:
Основание типа enum enum гарантирует, что возможны только допустимые значения. Это становится грязно очень быстро:
enum MyNumber { One, Two, ... } impl MyNumber { fn convert(i8) -> MyNumber { match { 1 => MyNumber::One, 2 => MyNumber::Two, ... } } }
Expose метод, который проверяет параметры перед установкой полей, учебник associated function. Это не препятствует назначению с помощью конструктора struct.
Проверять операнды (и принудительно исправлять их) всякий раз, когда происходит операция. Это кажется разумным, но требует, чтобы каждый метод повторял код проверки.
extern crate num; use num::Bounded; use std::cmp; struct MyNumber { val: i8, } impl Bounded for MyNumber { fn max_value() -> Self { MyNumber { val: 65 } } fn min_value() -> Self { MyNumber { val: -50 } } } impl MyNumber { fn clamp(&mut self) { self.val = cmp::min(MyNumber::max_value().val, cmp::max(MyNumber::min_value().val, self.val)) } fn add(&mut self, mut addend: Self) { self.clamp(); addend.clamp(); //TODO: wrap or saturate result self.val = self.val + addend.val } } fn main() { let mut a = MyNumber { val: i8::max_value() }; let b = MyNumber { val: i8::min_value() }; a.add(b); println!("{} + {} = {}", MyNumber::max_value().val, MyNumber::min_value().val, a.val); }
Ни одно из решений выше, не очень элегантно - в какой-то степени это происходит потому, что они являются реализациями прототипа. Должен быть более чистый способ ограничить область числового типа!
Какая комбинация типов и признаков будет проверять границы, использовать их для модульной/насыщенной арифметики и легко конвертировать в числовой примитив?
EDIT: Этот вопрос был помечен как дубликат гораздо более старого вопроса от 2014. Я не верю, что вопросы одинаковы на том основании, что Rust был pre alpha, и основные улучшения в языке были приведены с версией 1.0. Отличие состоит в больший масштаб, чем между Python 2 и 3.
Даже если * что-то достаточно важное было изменено или добавлено в Rust, все равно было бы целесообразно добавить эти ответы на существующий вопрос. В противном случае каждый отдельный вопрос о переполнении стека должен быть повторно запрошен каждые несколько месяцев, если что-то изменилось с окружающей средой. Полученный вами ответ повторяет уже существующий ответ (вплоть до реализаций конструктора и признаков), поэтому я не видел причин, по которым они не дублируются. Есть также проспект щедрости, если вы считаете, что более старый вопрос требует большего внимания. – Shepmaster
@Shepmaster Благодарим вас за разъяснение. Это справедливая точка зрения по этому вопросу. – Aaron3468
Не беспокойтесь! Более широкое сообщество может по-прежнему не соглашаться со мной и голосовать за повторное открытие; Я просто пытаюсь внести свой вклад в поддержание чистоты.^_^ – Shepmaster