【问题标题】:Why do I have to add type when declaring variables that are structs defined with generics?为什么在声明使用泛型定义的结构的变量时必须添加类型?
【发布时间】:2021-08-29 12:19:19
【问题描述】:

我有以下代码尝试应用泛型。

fn main() {
    
let HALVING2016: When= When {
        year: 2016.0,
    month: 7.0,
    day: 9.0,
    };
    
let HIGH2017: When= When {
        year: 2017.0,
    month: 12.0,
    day: 20.0,
    };

let HALVING2020: When= When {
        year: 2020.0,
    month: 5.0,
    day: 18.0,
    };


let DAYS_IN_Y: f32 = 365.25;

let DAYS_IN_M: f32 = 30.43757;

    
let NO_OF_DAYS_FROM_YEARS: f32 =   (HIGH2017.year - HALVING2016.year) * DAYS_IN_Y ; 

let NO_OF_DAYS_FROM_MONTHS: f32 =   (HIGH2017.month - HALVING2016.month) * DAYS_IN_M ; //This number can be negative!

let NO_OF_DAYS_FROM_DAYS: f32 = HIGH2017.day - HALVING2016.day ; //This number can be negative!


let DAYS_ALLTOGETHER: f32 = NO_OF_DAYS_FROM_YEARS + NO_OF_DAYS_FROM_MONTHS + NO_OF_DAYS_FROM_DAYS;

let MONTHS_ALLTOGETHER: f32 = DAYS_ALLTOGETHER / DAYS_IN_M ;


let DAYS_FROM_DM: f32 = DAYS_ALLTOGETHER - DAYS_IN_Y ;



    
let high2021: When= When {
    year: HALVING2020.year + (MONTHS_ALLTOGETHER) / 12.0,
    month: DAYS_FROM_DM / DAYS_IN_M + 5.0 ,
    day: 20.0 + NO_OF_DAYS_FROM_DAYS ,
    
    };  

let low2015: Low = Low {
    high: 1128.4, 
    low: 197.84 ,
    percentage: (1128.4 - 197.84 ) / 1128.4,
};  
    
println!("The all-time high for Bitcoin will happen on {:.0}/{:.0}/{:.0} i.e. {:.1} months from its halving in May of 2020.", high2021.day, high2021.month, high2021.year, MONTHS_ALLTOGETHER );


let low2018: Low = Low {
    high: 19798.6, 
    low: 3156.2, //13/12/2018 the same date as XMR
    percentage: (19798.6 - 3156.2 ) / 19798.6,
};

let low2022: Low = Low {
    high: ( low2018.high / 1128.4 ) * low2018.high , //We do not have the data for the ATH of XMR that corresponds to BTC 1128.4
    low: (1.0 - 0.8326284) * ( low2018.high / 1128.4 ) * low2018.high,
    percentage: (0.82467216 + 0.8405847 ) / 2.0,
};

println!("The all-time high of ${:.0} for Bitcoin was followed by the drop of {:.1}%.", low2015.high, low2015.percentage * 100.0 );

println!("The last all-time high of {:.0} for Bitcoin was followed by the drop of {:.1}%.", low2018.high, low2018.percentage * 100.0 );

println!("The high of 2017 was {:.2} times higher than the high of 2014. The average of the last two corrections is {:.1}%.\n", low2022.high / low2018.high, low2022.percentage * 100.0 );

println!("Should the high of 2021 be {:.2} times higher than the high of 2017 it would be at the price of ${:.0}.", low2022.high / low2018.high, low2022.high );

println!("Should the correction in the 2022-2023 be that of {:.2}% from the top of {:.0}, the bottom would be at ${:.0}.\n", low2022.percentage * 100.0, low2022.high, low2022.low );

}



struct When{
    year: f32,
    month: f32,
    day: f32,
}

struct Low {
    high: f32,
    low: f32,
    percentage: f32  
}

一开始我试过了 通过替换结构When的定义来在结构定义中使用泛型:

struct When<T>{
    year: T,
    month: T,
    day: T,
}

然后,当我运行它时,我会从编译器获取消息:

error[E0107]: missing generics for struct `When`
  --> src/main.rs:3:18
   |
3  | let HALVING2016: When = When {
   |                  ^^^^ expected 1 type argument
   |
note: struct defined here, with 1 type parameter: `T`
  --> src/main.rs:86:8
   |
86 | struct When<T>{
   |        ^^^^ -
help: use angle brackets to add missing type argument
   |
3  | let HALVING2016: When<T> = When {

按照编译器的建议,我添加了缺少的类型参数 (&lt;T&gt;),因此代码现在看起来像这样:

fn main() {
    
let HALVING2016: When<T> = When {
        year: 2016.0,
    month: 7.0,
    day: 9.0,
    };
    
let HIGH2017: When<T> = When {
        year: 2017.0,
    month: 12.0,
    day: 20.0,
    };

let HALVING2020: When<T> = When {
        year: 2020.0,
    month: 5.0,
    day: 18.0,
    };


let DAYS_IN_Y: f32 = 365.25;

let DAYS_IN_M: f32 = 30.43757;

    
let NO_OF_DAYS_FROM_YEARS: f32 =   (HIGH2017.year - HALVING2016.year) * DAYS_IN_Y ; 

let NO_OF_DAYS_FROM_MONTHS: f32 =   (HIGH2017.month - HALVING2016.month) * DAYS_IN_M ; //This number can be negative!

let NO_OF_DAYS_FROM_DAYS: f32 = HIGH2017.day - HALVING2016.day ; //This number can be negative!


let DAYS_ALLTOGETHER: f32 = NO_OF_DAYS_FROM_YEARS + NO_OF_DAYS_FROM_MONTHS + NO_OF_DAYS_FROM_DAYS;

let MONTHS_ALLTOGETHER: f32 = DAYS_ALLTOGETHER / DAYS_IN_M ;


let DAYS_FROM_DM: f32 = DAYS_ALLTOGETHER - DAYS_IN_Y ;
    
let high2021: When<T> = When {
    year: HALVING2020.year + (MONTHS_ALLTOGETHER) / 12.0,
    month: DAYS_FROM_DM / DAYS_IN_M + 5.0 ,
    day: 20.0 + NO_OF_DAYS_FROM_DAYS ,
    
    };  

let low2015: Low = Low {
    high: 1128.4, 
    low: 197.84 ,
    percentage: (1128.4 - 197.84 ) / 1128.4,
};  
    
println!("The all-time high for Bitcoin will happen on {:.0}/{:.0}/{:.0} i.e. {:.1} months from its halving in May of 2020.", high2021.day, high2021.month, high2021.year, MONTHS_ALLTOGETHER );


let low2018: Low = Low {
    high: 19798.6, 
    low: 3156.2, //13/12/2018 the same date as XMR
    percentage: (19798.6 - 3156.2 ) / 19798.6,
};

let low2022: Low = Low {
    high: ( low2018.high / 1128.4 ) * low2018.high , //We do not have the data for the ATH of XMR that corresponds to BTC 1128.4
    low: (1.0 - 0.8326284) * ( low2018.high / 1128.4 ) * low2018.high,
    percentage: (0.82467216 + 0.8405847 ) / 2.0,
};

println!("The all-time high of ${:.0} for Bitcoin was followed by the drop of {:.1}%.", low2015.high, low2015.percentage * 100.0 );

println!("The last all-time high of {:.0} for Bitcoin was followed by the drop of {:.1}%.", low2018.high, low2018.percentage * 100.0 );

println!("The high of 2017 was {:.2} times higher than the high of 2014. The average of the last two corrections is {:.1}%.\n", low2022.high / low2018.high, low2022.percentage * 100.0 );

println!("Should the high of 2021 be {:.2} times higher than the high of 2017 it would be at the price of ${:.0}.", low2022.high / low2018.high, low2022.high );

println!("Should the correction in the 2022-2023 be that of {:.2}% from the top of {:.0}, the bottom would be at ${:.0}.\n", low2022.percentage * 100.0, low2022.high, low2022.low );

}


struct When<T>{
    year: T,
    month: T,
    day: T,
}


struct Low {
    high: f32,
    low: f32,
    percentage: f32  
}


这一次我从编译器得到以下消息:

error[E0412]: cannot find type `T` in this scope
 --> src/main.rs:3:23
  |
3 | let HALVING2016: When<T> = When {
  |                       ^ not found in this scope

error[E0412]: cannot find type `T` in this scope
 --> src/main.rs:9:20
  |
9 | let HIGH2017: When<T> = When {
  |                    ^ not found in this scope

error[E0412]: cannot find type `T` in this scope
  --> src/main.rs:15:23
   |
15 | let HALVING2020: When<T> = When {
   |                       ^ not found in this scope

error[E0412]: cannot find type `T` in this scope
  --> src/main.rs:44:20
   |
44 | let high2021: When<T> = When {
   |                    ^ not found in this scope

我被困住了。为什么我必须添加? In an example from this textbook 他们的代码没有它们也能正常工作。

附:我很清楚在命名时违反约定 我的变量带有大写字母,但这超出了问题的范围。

【问题讨论】:

    标签: generics struct rust


    【解决方案1】:

    定义一个结构和实例化一个结构时,你需要做的事情略有不同。

    当你写作时:

    struct When<T>{
        year: T,
        month: T,
        day: T,
    }
    

    你是说“会有一个类型,我们称之为T,我不知道那个类型是什么,但是当这个结构被实例化时你会知道它是什么” . T 就像一个占位符。

    当您实例化该类型时,您不能再只是说它是 When&lt;T&gt; - 编译器需要知道什么类型正在填充名为 T 的占位符。

    您可以通过三种方式在代码中做到这一点:

    1. 您可以明确说明并告诉编译器“泛型 T 的类型为 f32”:
    let HALVING2016: When<f32> = When {
        year: 2016.0,
        month: 7.0,
        day: 9.0,
    };
    
    1. 您可以要求编译器为您解决 - 它并不总是能够做到这一点,并且可能会要求您明确说明,但它可能适用于您的情况。我们通过使用下划线 (_) 而不是类型来做到这一点,这意味着编译器“自己解决这个问题”(更正式地称为推理):
    let HALVING2016: When<_> = When {
        year: 2016.0,
        month: 7.0,
        day: 9.0,
    };
    
    1. 我们可以完全停止归类类型,编译器将尝试对整个类型进行推断(同样,这可能会失败并出错,要求您明确说明,但我怀疑它在这种情况下会起作用):
    let HALVING2016 = When {
        year: 2016.0,
        month: 7.0,
        day: 9.0,
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      相关资源
      最近更新 更多