回顾

感谢 上篇 评论区指出,struct 一节 的例程未吃透。如这个 unit struct:

    // Instantiate a unit struct
    let 某单元 = 单元;

实例化不需要括号。如果加了括号则报错,比较意外:

error[E0618]: expected function, found struct `单元`
  --> src/main.rs:64:15
   |
11 | struct 单元;
   | ----------- struct `单元` defined here
...
64 |     let 某单元 = 单元();
   |                  ^^^^--
   |                  |
   |                  call expression requires function
   |
help: `单元` is a unit struct, and does not take parentheses to be constructed
   |
64 -     let 某单元 = 单元();
64 +     let 某单元 = 单元;
   |

For more information about this error, try `rustc --explain E0618`.

经回复进一步指点,三种struct实例化的语法与定义语法有一一对应关系(unit 无括号,tuple 用小括号,具名字段的用大括号)。好奇为何不直接用一种语法?在可以从定义很明显看出区别的情况下,还用小括号和大括号作语法上的区分,是否有另外的设计考虑呢?小括号更多是用在函数参数,大括号多用在代码块,但这和具名与否有何关联呢?

也试了一下这样用错括号:

struct 对子 {
    x: i32,
    y: f32,
}

    let x = 1;
    let y = 0.1;
    let 某对子 = 对子(x, y);

报错里找到了命名相近的结构:

error[E0423]: expected function, found struct `对子`
  --> src/main.rs:75:15
   |
14 |   struct 对(i32, f32);
   |   -------------------- similarly named tuple struct `对` defined here
15 |
16 | / struct 对子 {
17 | |     x: i32,
18 | |     y: f32,
19 | | }
   | |_- `对子` defined here
...
75 |       let 某对子 = 对子(x, y);
   |                    ^^^^^^^^^^
   |
help: use struct literal syntax instead
   |
75 |     let 某对子 = 对子 { x: val, y: val };
   |                  ~~~~~~~~~~~~~~~~~~~~~~~
help: a tuple struct with a similar name exists
   |
75 |     let 某对子 = 对(x, y);
   |                  ~~

For more information about this error, try `rustc --explain E0423`.

修正后的对照如下。在可读性方面,除了从初始化语句可看出该 struct 的细分类型之外,不知有何其他好处?

struct (i32, f32);

struct 对子 {
    x: i32,
    y: f32,
}

    let 某对 = (x, y);
    let 某对子 = 对子{x, y};

泛型之实现

继续吧。

空定义

struct ; // Concrete type `甲`
struct 泛型类<>(); // Generic type `泛型类`

// impl of 泛型类 where we explicitly specify type parameters:
impl 泛型类<f32> {} // Specify `f32`
impl 泛型类<> {} // Specify `甲` as defined above

// `<类>` Must precede the type to remain generic
impl<某类> 泛型类<某类> {}

只在 泛型类 定义时有效(scope),如果在 impl<某类> 泛型类<某类> {} 就报错:

error[E0412]: cannot find type `类` in this scope
 --> src/lib.rs:9:14
  |
9 | impl<某类> 泛型类<类> {}
  |      ----         ^^
  |      |
  |      similarly named type parameter `某类` defined here
  |
help: a type parameter with a similar name exists
  |
9 | impl<某类> 泛型类<某类> {}
  |                   ~~~~
help: you might be missing a type parameter
  |
9 | impl<某类, 类> 泛型类<类> {}
  |          ++++

For more information about this error, try `rustc --explain E0412`.

看到第二个建议,想起了 昨天看到 的报错 unused type parameter,试了下果然报错:

error[E0207]: the type parameter `某类` is not constrained by the impl trait, self type, or predicates
 --> src/lib.rs:9:6
  |
9 | impl<某类, 类> 泛型类<类> {}
  |      ^^^^ unconstrained type parameter

For more information about this error, try `rustc --explain E0207`.

这种建议的代码本身有错的情况对新手来说影响会更大。

非空定义

3i32 这种表达挺扎眼,去掉 i32 输出相同。如果用char的话,报错如下:

error: invalid suffix `char` for number literal
  --> src/main.rs:25:23
   |
25 |   let y = 泛型值类 { 泛型值: 3char };
   |                              ^^^^^ invalid suffix `char`
   |
   = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)

至于 &,似乎那段目标代码里没有,其在类型的作用暂不深究。

中文化后代码:

struct 值类 {
  : f64,
}

struct 泛型值类<> {
  泛型值: ,
}

// impl of 值类
impl 值类 {
  fn 取值(&self) -> &f64 {
      &self.值
  }
}

// impl of 泛型值类 for a generic type `某类`
impl<某类> 泛型值类<某类> {
  fn 取值(&self) -> &某类 {
      &self.泛型值
  }
}

fn main() {
  let x = 值类 { : 3.0 };
  let y = 泛型值类 { 泛型值: 3i32 };

  println!("{}, {}", x.取值(), y.取值());
}