Rust 在线摸索(八):泛型没入门
结构 初步了解了,先跳到 泛型。之前 struct 的命名开头大写,而方法等都是下划线分隔的小写。char 是内置类型,也用全小写,也许是为了与非内置类型区分开?不知有没有类似 Java 里 int 和 Integer 的对应。
如果改为 let _字: 个泛<String> = 个泛('a');
报错(1):
error[E0308]: mismatched types
--> src/main.rs:21:29
|
21 | let _字: 个泛<String> = 个泛('a');
| ---- ^^^- help: try using a conversion method: `.to_string()`
| | |
| | expected `String`, found `char`
| arguments to this struct are incorrect
|
help: the type constructed contains `char` due to the type of the argument passed
--> src/main.rs:21:26
|
21 | let _字: 个泛<String> = 个泛('a');
| ^^^^^---^
| |
| this argument influences the type of `个泛`
note: tuple struct defined here
--> src/main.rs:12:8
|
12 | struct 个泛<T>(T);
| ^^^^
For more information about this error, try `rustc --explain E0308`.
哪个是 tuple struct
?感觉各个错误间的关系难以看清,尤其在报错信息无间隔的情况下。
如果将 ‘a’ 改为 ‘ab’,是否就是 String 了呢?报错:
error: character literal may only contain one codepoint
--> src/main.rs:21:29
|
21 | let _字: 个泛<String> = 个泛('ab');
| ^^^^
|
help: if you meant to write a string literal, use double quotes
|
21 | let _字: 个泛<String> = 个泛("ab");
| ~ ~
根据建议改为双引号。结果报错:
error[E0308]: mismatched types
--> src/main.rs:21:29
|
21 | let _字: 个泛<String> = 个泛("ab");
| ---- ^^^^- help: try using a conversion method: `.to_string()`
| | |
| | expected `String`, found `&str`
| arguments to this struct are incorrect
|
help: the type constructed contains `&'static str` due to the type of the argument passed
【后半部分同报错(1)】
之前的建议不到位啊。继续加了 .to_string()
,通过编译,看来多数标准库的函数命名风格是下划线小写。不知像 println 的特例有几个。
带出的另一个问题是 String 和 &str 的差别。另外,帮助里提到 “ab” 是个 &'static str
,那为啥不直接在 “expected String
, found &str
” 里写明 static 呢?反馈信息的简约度还有改进空间。
试了一下 let _个 = 个泛(个);
也可以,如果参数是自己 let _个泛 = 个泛(个泛);
,则报错:
error[E0282]: type annotations needed
--> src/main.rs:28:18
|
28 | let _个泛 = 个泛(个泛);
| ^^^^ cannot infer type of the type parameter `T` declared on the struct `个泛`
|
help: consider specifying the generic argument
|
28 | let _个泛 = 个泛(个泛::<T>);
| +++++
For more information about this error, try `rustc --explain E0282`.
感觉可以搞个报错信息数据库,记录各种错误信息和可对应复现的代码。回头看看rustc –explain是不是已有类似数据。
报错是说光看 个泛
无法确定类型,合理,不过建议里居然可以用 generic argument,试试先,于是报错:
error[E0412]: cannot find type `T` in this scope
--> src/main.rs:28:23
|
6 | struct 个(甲);
| -------------- similarly named struct `个` defined here
...
28 | let _个泛 = 个泛(个泛::<T>);
| ^ help: a struct with a similar name exists: `个`
For more information about this error, try `rustc --explain E0412`.
例程里有个 struct 个泛<T>(T);
,我就以为是它是结合了这个上下文才提示可以直接写 T
,为确认一下,改成 struct 个泛<S>(S);
报错还是之前那样。
看来前面那个报错里的 T 实际上是泛指某个类的意思。于是改成比如char let _个泛 = 个泛(个泛::<char>);
,就通过了。
后三句看着有点不和谐,甲 是个类名,而 6 和 ‘a’ 都是值,如果改成对应的 i32,结果报错:
error[E0423]: expected value, found builtin type `i32`
--> src/main.rs:25:17
|
25 | let _数 = 个泛(i32); // Uses `i32`.
| ^^^ not a value
|
help: consider importing one of these functions instead
|
2 + use fastrand::i32;
|
2 + use nom::character::complete::i32;
|
2 + use nom::character::streaming::i32;
|
2 + use nom::number::complete::i32;
|
and 2 other candidates
For more information about this error, try `rustc --explain E0423`.
那这句改成 let _字: 个泛<String> = 个泛(String);
呢?还报错:
error[E0423]: expected value, found struct `String`
--> src/main.rs:21:29
|
21 | let _字: 个泛<String> = 个泛(String);
| ^^^^^^
|
::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/string.rs:362:1
|
362 | pub struct String {
| ----------------- `String` defined here
|
help: consider importing one of these tuple variants instead
|
2 + use clap::error::ContextValue::String;
|
2 + use clap_builder::error::ContextValue::String;
|
2 + use fs_extra::dir::DirEntryValue::String;
|
2 + use gimli::AttributeValue::String;
|
and 7 other candidates
For more information about this error, try `rustc --explain E0423`.
为啥 甲 这个 struct 就可以当参数而 String 不可以?改成 let _类: 个泛<甲> = 个泛(甲);
也是没问题的。
至少粗看报错信息没看出端倪。。。留着疑惑先到这。代码如下:
// A concrete type `甲`.
struct 甲;
// In defining the type `个`, the first use of `甲` is not preceded by `<甲>`.
// Therefore, `个` is a concrete type, and `甲` is defined as above.
struct 个(甲);
// ^ Here is `个`s first use of the type `甲`.
// Here, `<类>` precedes the first use of `类`, so `个泛` is a generic type.
// Because the type parameter `类` is generic, it could be anything, including
// the concrete type `甲` defined at the top.
struct 个泛<类>(类);
fn main() {
// `个` is concrete and explicitly takes `甲`.
let _个 = 个(甲);
// Create a variable `_字` of type `个泛<char>`
// and give it the value `个泛('a')`.
// Here, `个泛` has a type parameter explicitly specified.
let _字: 个泛<char> = 个泛('a');
// `个泛` can also have a type parameter implicitly specified:
let _类 = 个泛(甲); // Uses `甲` defined at the top.
let _数 = 个泛(6); // Uses `i32`.
let _字 = 个泛('a'); // Uses `char`.
}