Можно ли написать обобщенную функцию c целочисленной длины в Rust? - PullRequest
0 голосов
/ 15 марта 2020

Я написал функцию длины для u32. Я мог бы легко копировать / вставлять / редактировать другие типы int, но когда я пытаюсь использовать дженерики, я застреваю. Есть ли понятия, которые я неправильно понимаю?

Функция длины передачи

fn len_int(n: u32) -> u32 { // 0
    std::iter::repeat_with({
        let mut l = 0;
        // can't call pow on ambiguous numeric type
        move || match n / 10u32.pow(l) { // 1
            0 => 0,
            _ => {
                l += 1;
                1
            }
        }
    })
        .take_while(|&x| x != 0)
        // count returns usize
        .count() as u32 // 2
}

Неисправная функция длины c: I

fn len_int<T>(n: T) -> T
where
    T: Copy + Clone,
{
    std::iter::repeat_with({
        let mut l = 0;
        move || match n / 10.pow(l) {
            //1
            0 => 0,
            _ => {
                l += 1;
                1
            }
        }
    })
    .take_while(|&x| x != 0)
    .count() at T // 2
}

Компилятор сообщает мне Я не могу call method pow on ambiguous numeric type {integer} cannot divide T by type error или конвертировать count() в конце с as T, так как T не является примитивным типом. детская площадка

Ответы [ 2 ]

0 голосов
/ 21 марта 2020

Мы можем определить черту, а затем реализовать черту для конкретных типов, которые вы хотите поддерживать в вашей обобщенной функции c:

pub trait IntLenExt<T> {
    fn is_divis(&self, power: u32) -> bool;
    fn cast_count(count: usize) -> T;
}

impl IntLenExt<u32> for u32 {
    fn is_divis(&self, power: u32) -> bool {
        self / 10u32.pow(power) == 0
    }

    fn cast_count(count: usize) -> u32 {
        count as u32
    }
}

impl IntLenExt<u64> for u64 {
    fn is_divis(&self, power: u32) -> bool {
        self / 10u64.pow(power) == 0
    }

    fn cast_count(count: usize) -> u64 {
        count as u64
    }
}

fn len_int<T>(n: T) -> T
where
    T: Copy + Clone + IntLenExt<T>,
{
    T::cast_count(std::iter::repeat_with({
        let mut l = 0;
        move || match n.is_divis(l) {
            //1
            true => 0,
            false => {
                l += 1;
                1
            }
        }
    })
    .take_while(|&x| x != 0)
    .count()) // 2
}


fn main() {
    let input: u64 = 100;
    println!("len_int({}) => {}", input, len_int(input));
}
0 голосов
/ 19 марта 2020

Вы можете иметь в своем уме определенные c типы, но компилятор этого не знает. Для компилятора общий c тип T может быть абсолютно любым . Это может быть строка. Это может быть ссылка на указатель на функцию. Это может быть вектор файловых дескрипторов. Все . Поэтому вашему коду потребуется работать со всеми этими возможными типами одновременно.

Для работы с более конкретными c типами необходимо заранее объявить все , что вы хотите тип для поддержки. Компилятор не позволит вам использовать операции, которые вы не объявили.

В стандартной библиотеке Rust нет признака .pow, поэтому вы не можете объявить это «из коробки». Вы можете сделать его самостоятельно или использовать num-traits .

...