2014-01-12 4 views
10

Предположим, у меня есть функция, которая сравнивает число аргумент константа и возвращает логическое значение:Сравните общий номер аргумента с константой

fn compare(n: f64) -> bool { 
    n > 42 as f64 
} 

Это прекрасно работает, но я не могу показаться, чтобы сделать его родовое :

fn compare<T: Ord>(n: T) -> bool { 
    n > 42 as T // error: non-scalar cast: `<VI0>` as `T` 
} 

fn compare<T: Ord>(n: T) -> bool { 
    n > 42  // mismatched types: expected `T` but found `<VI0>` (expected type parameter but found integral variable) 
} 

fn compare<T: Num>(n: T) -> bool { 
    n > 42  // error: binary operation > cannot be applied to type `T` 
} 

Как вы это сделаете?

+1

Я не эксперт, но я понимаю, что вы не можете сделать 20> 10,5 в ржавчине. Это означает, что вы не можете сравнивать более двух разных типов. – sunny1304

+0

Исправить. Я надеюсь, что есть способ автоматически включить константу в совместимый тип. Константы, вероятно, должны быть нетипизированы, в первую очередь, как в Go. – Gunchars

ответ

9

Как вы видели, оператор Rust as очень ограничен в своих действиях. Согласно Rust manual,

Числовое значение может быть присвоено любому цифровому типу. Необработанное значение указателя может быть добавлено к типу целого типа или необработанного указателя. Любые другие роли не поддерживаются и не будут компилироваться.

Кроме того, Rust не делает какое-либо подразумеваемого время выполнения числового принуждения, поэтому вы должны явно принуждать аргументы операторов сравнения к тому же типу (с Ord определяет lt метод с прототипом fn lt(&self, other: &Self)).

Возникает интересный вопрос - к какому типу следует аргументы оператора < в вашей compare функции быть литой, T или int (предполагаемый тип 42)? В этом случае вам нужно сравнить n со значением 42 после преобразования в T. Самый простой способ выполнить это, оставаясь общим, - потребовать, чтобы T реализовал признак FromPrimitive, содержащийся во внешнем num crate, который предоставляет методы получения значения типа T из int (или других примитивных числовых типов ржавчины).Ваша compare функция может быть записана следующим образом:

extern crate num; 

use num::FromPrimitive; 

fn compare<T: Ord + FromPrimitive>(n: T) -> bool { 
    n > FromPrimitive::from_int(42).expect("42 must be convertible to type of n") 
} 


Чтобы проверить это, я создал простой BinaryNumber тип, который представляет собой двоичное число как массив bool:

use std::num::abs; 

type Bits = [bool, ..64]; 

struct BinaryNumber { 
    priv negbit: bool, 
    priv bits: Bits, 
} 

fn bits_from_u64(n: u64) -> Bits { 
    let mut bits = [false, ..64]; 
    for i in range(0u, 64u) { 
     if ((1 << i) & n) != 0 { 
      bits[i] = true; 
     } 
    } 
    bits 
} 

impl FromPrimitive for BinaryNumber { 
    fn from_u64(n: u64) -> Option<BinaryNumber> { 
     Some(BinaryNumber { 
       negbit: false, 
       bits: bits_from_u64(n.to_u64().unwrap()) 
     }) 
    } 
    fn from_i64(n: i64) -> Option<BinaryNumber> { 
     Some(BinaryNumber { 
       negbit: n < 0, 
       bits: bits_from_u64(abs(n).to_u64().unwrap()) 
     }) 
    } 
} 

impl Eq for BinaryNumber { 
    fn eq(&self, other: &BinaryNumber) -> bool { 
     if self.negbit != other.negbit { return false } 
     for i in range(0, 64).map(|i| 64 - 1 - i) { 
      if self.bits[i] != other.bits[i] { 
       return false; 
      } 
     } 
     true 
    } 
} 

impl Ord for BinaryNumber { 
    fn lt(&self, other: &BinaryNumber) -> bool { 
     match (self.negbit, other.negbit) { 
      (true, false) => true, 
      (false, true) => false, 
      _    => { 
       let neg = self.negbit; 
       for i in range(0, 64).map(|i| 64 - 1 - i) { 
        if neg && self.bits[i] && !other.bits[i] { 
         return true; 
        } else if !self.bits[i] && other.bits[i] { 
         return true; 
        } 
       } 
       false 
      } 
     } 
    } 
} 

Затем следующий код

fn main() { 
    let x: BinaryNumber = FromPrimitive::from_int(0).unwrap(); 
    let y: BinaryNumber = FromPrimitive::from_int(42).unwrap(); 
    let z: BinaryNumber = FromPrimitive::from_int(100).unwrap(); 
    println!("compare(x) = {}", compare(x)); 
    println!("compare(y) = {}", compare(y)); 
    println!("compare(z) = {}", compare(z)); 
} 

печатает

compare(x) = false 
compare(y) = false 
compare(z) = true 
+1

У меня нет опыта ржавчины, но +1 для полноты :) – Bohemian

+2

Как и Rust 1.0, этот ответ устарел. Признак 'FromPrimitive' был [удален из стандартной библиотеки] (https://github.com/rust-lang/rust/issues/16920). –

2

Вы могли бы попробовать это

compare<T: PartialOrd<i32>>(n: T) -> bool { 
    n > 42 
} 

выражение л.ш.> RHS равно < T, как PartialOrd <U> > :: GT (& л.ш., & шк)
где lhs имеет тип T и шк имеет тип U
Таким образом T должен реализовать PartialOrd для того, чтобы разрешить использование оператора >

+1

Этот ответ появился в очереди просмотра низкого качества, по-видимому, потому, что вы не объяснили код. Если вы объясните это (в своем ответе), у вас гораздо больше шансов получить больше бонусов - и у испытуемого больше шансов узнать что-то! –

+0

Но единственным T: PartialOrd в [std] (https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html) является i32 – Jacob

Смежные вопросы