< 返回版块

ltoddy 发表于 2018-07-11 18:06

Tags:type

先上代码:

let mut guess = String::new();

io::stdin().read_line(&mut guess)
    .ok()
    .expect("Failed to read line");

let guess: u32 = guess.trim().parse()
    .ok()
    .expect("Please type a number!");

这段代码中有两个guess,在第二个guess那里 guess: u32,然后等号右边是对第一个guess进行parse,然后给左边的引用。假设第二个guess是: let guess = guess.trim().parse() 没有加显式类型:u32,那么第二个guess的类型是一个泛型T,那么,按常理等号右边的先被计算,那么这里也就是代表rust是弱类型了。 我这里有很大疑问。

评论区

写评论
rust-beginner 2018-07-18 12:46

1、强类型和弱类型其实没有明确的定义 [1],所以这个可能很难达成共识。

2、相反,静态类型是指编译器在编译期就能通过静态分析确定下来类型的语言。因此 Rust 是一门静态类型语言。即使是类型推断也无损这一点。比较:Python 是一门动态类型语言。

3、关于 let

let a = xxx;
let a = yyy;

这里两个 a 并不是同一个,而只是个名字,我们只是把值绑定到名字上(而不是赋值)。它们先后被绑定的值是有明确类型的,而不是泛型或者无类型。

强行把类型确定放到运行时会报错:

fn main() {
    let a;
    if std::env::args().len() == 2 {
        a = "hello"; // &'static str
    } else {
        a = 123;     // i32
    }
}

而动态类型语言则会检查通过并能正常运行这个程序。

let 的这个特征来自于函数式编程语言。

[1] https://www.wikiwand.com/zh/%E5%BC%B7%E5%BC%B1%E5%9E%8B%E5%88%A5

SHA Miao 2018-07-17 15:25

按常理等号右边的先被计算,那么这里也就是代表rust是弱类型了

不能用编译期“暂时”、“马上就解决掉”的推断存疑,就否认一门语言是静态类型的。
否则你也可以说C++(模板)和Java(范型)都是所谓的“动态类型”……哈哈哈,所谓的“编译期动态”嘛。
编译器就是会在编译过程中前翻后查的,“一时尚未确定”,这很正常。

只要每个量的类型“能在编译期最终的敲定”,就是静态类型语言。
因为这等效于编译器“替”开发者把每个东西的类型,都给明确写了出来。

SHA Miao 2018-07-17 15:25

按常理等号右边的先被计算,那么这里也就是代表rust是弱类型了

不能用编译期“暂时”、“马上就解决掉”的推断存疑,就否认一门语言是静态类型的。 否则你也可以说C++(模板)和Java(范型)都是所谓的“动态类型”……哈哈哈,所谓的“编译期动态”嘛。 编译器就是会在编译过程中前翻后查的,“一时尚未确定”,这很正常。

只要每个量的类型“能在编译期最终的敲定”,就是静态类型语言。因为这等效于编译器“替”开发者把每个东西的类型,都给明确写了出来。

SHA Miao 2018-07-17 15:12

按常理等号右边的先被计算,那么这里也就是代表rust是弱类型了

你不能用编译期“暂时”、“马上就解决掉”的推断存疑,就否认一门语言是强类型的。
否则你也可以说C++(模板)和Java(范型)都是所谓的“弱类型”。 编译器就是会在编译过程中前翻后查的,“一时尚未确定”,这很正常。

只要每个类型“能在编译期最终的明确敲定”,就是强类型语言。因为这等效于编译器“替”开发者把每个东西的类型,都给明确写了出来。

SHA Miao 2018-07-17 15:04
let guess: u32 = 
    guess // String
    .trim() // &str
    .parse() // Result<F, E> where F: FromStr
    .ok() // Option<F> where F: FromStr
    .expect("Please type a number!"); // F where F: FromStr

也就是说,等号右侧这个表达式的类型,是 F where F: FromStr 。

这个类型“存疑”(尚未推断具体类型),根据rustc的规则,这个具体类型会在最早能够作出推断的地方进行推断。

而这个最早的地方正是赋值语句本身。首先 F 只能是 u32 ,保证赋值成立。其次 type F = u32 并不会和 where F: FromStr 约束产生矛盾(u32实现了FromStr)。

因此编译期判定 F = u32 成立。右侧各个计算环节的类型,是明确的静态类型。case closed。

SHA Miao 2018-07-17 14:55

一事一议吧。不推荐偏离楼主位讨论的问题。如果楼主对这个判断有信心,很期待看到楼主新的帖子。

@ltoddy 能不能本着格物致知!!不要说什么rust这个厉害那个厉害的,rust最初用ocaml实现,ocaml现在还有十分之一的C代码实现。rust现在才刚发展,还很弱小,stdlib缺陷很多,功能也不足,曾经见到有人吹嘘actix,我看过actix代码,没什么好吹嘘的,很平常的代码,rust需要走的路还很长。其实在我看了,虽然rust以及rust社区很活跃,但最多是昙花一现。

0kaguya 2018-07-14 09:43

你这是把Rust当成动态类型语言看了

damody 2018-07-13 01:21

你的問題是重複宣告,跟強類弱類無關 rust本來就可以重複宣告

fn main() {
    let a = "123";
    let a = 123;
    let a = 123.0;
}
damody 2018-07-13 01:19

let mut guess = String::new();

io::stdin().read_line(&mut guess) .ok() .expect("Failed to read line");

到這裡都是string let A = guess.trim().parse() .ok() .expect("Please type a number!"); 然後你把guess重複宣告改變型態 let guess = A;

laizy 2018-07-12 17:05

别说从左边获取信息,从下边都行。

let mut v = vec![];  // 从下面的使用推导出v的类型.
...
v.push(10);   

laizy 2018-07-12 16:57

类型是在编译的时候就推导定下来的呀,和运行时的先执行右边没有半毛钱关系。

@ltoddy 在执行.parse()的时候,此时是无法获得左边的信息的。

@admin 它会搜集左侧的u32信息,解析的时候,直接按u32解析。不是单纯的先计算右边。

@LiuTao 我知道rust的自动类型推导,这是现代化语言最基本的功能。 但是你应该是知道程序的执行顺序,等号右边执行之后,返回了一个泛型T, 按照你的说法,进行类型推导,编译器读取等号左边的信息(显式的说明类型是u32), 那么rust类型系统中的泛型就出问题了,难道泛型可以随意的你想是什么类型就是什么类型吗。 当然你也可以说,在parse后面还有ok().expect(),但是,这样就会发现rust设计上的问题越来越多了,rust本着想要构建所谓的“安全”,他尽量在静态编译的时候给发现你的“不安全”,或者错误。这个时候,并不是在发现你的错误,而是在容忍你的错误,让你编译出来的程序成为“××”。

@damody 強類型啊! 自動推導太強大 讓你誤會了。

laizy 2018-07-12 16:56

类型是在编译的时候就推导定下来的呀,和运行时的先执行右边没有半毛钱关系。

cxq 2018-07-12 12:53

说的一点没错,很多用rust 的人,其实都是无脑的,把很多不合理的东西都当成圣经

@LiuTao 能不能本着格物致知!!不要说什么rust这个厉害那个厉害的,rust最初用ocaml实现,ocaml现在还有十分之一的C代码实现。rust现在才刚发展,还很弱小,stdlib缺陷很多,功能也不足,曾经见到有人吹嘘actix,我看过actix代码,没什么好吹嘘的,很平常的代码,rust需要走的路还很长。其实在我看了,虽然rust以及rust社区很活跃,但最多是昙花一现。

作者 ltoddy 2018-07-12 11:30

能不能本着格物致知!!不要说什么rust这个厉害那个厉害的,rust最初用ocaml实现,ocaml现在还有十分之一的C代码实现。rust现在才刚发展,还很弱小,stdlib缺陷很多,功能也不足,曾经见到有人吹嘘actix,我看过actix代码,没什么好吹嘘的,很平常的代码,rust需要走的路还很长。其实在我看了,虽然rust以及rust社区很活跃,但最多是昙花一现。

作者 ltoddy 2018-07-12 10:28

在执行.parse()的时候,此时是无法获得左边的信息的。

@admin 它会搜集左侧的u32信息,解析的时候,直接按u32解析。不是单纯的先计算右边。

@LiuTao 我知道rust的自动类型推导,这是现代化语言最基本的功能。 但是你应该是知道程序的执行顺序,等号右边执行之后,返回了一个泛型T, 按照你的说法,进行类型推导,编译器读取等号左边的信息(显式的说明类型是u32), 那么rust类型系统中的泛型就出问题了,难道泛型可以随意的你想是什么类型就是什么类型吗。 当然你也可以说,在parse后面还有ok().expect(),但是,这样就会发现rust设计上的问题越来越多了,rust本着想要构建所谓的“安全”,他尽量在静态编译的时候给发现你的“不安全”,或者错误。这个时候,并不是在发现你的错误,而是在容忍你的错误,让你编译出来的程序成为“××”。

@damody 強類型啊! 自動推導太強大 讓你誤會了。

Mike 2018-07-12 10:19

它会搜集左侧的u32信息,解析的时候,直接按u32解析。不是单纯的先计算右边。

@LiuTao 我知道rust的自动类型推导,这是现代化语言最基本的功能。 但是你应该是知道程序的执行顺序,等号右边执行之后,返回了一个泛型T, 按照你的说法,进行类型推导,编译器读取等号左边的信息(显式的说明类型是u32), 那么rust类型系统中的泛型就出问题了,难道泛型可以随意的你想是什么类型就是什么类型吗。 当然你也可以说,在parse后面还有ok().expect(),但是,这样就会发现rust设计上的问题越来越多了,rust本着想要构建所谓的“安全”,他尽量在静态编译的时候给发现你的“不安全”,或者错误。这个时候,并不是在发现你的错误,而是在容忍你的错误,让你编译出来的程序成为“××”。

@damody 強類型啊! 自動推導太強大 讓你誤會了。

作者 ltoddy 2018-07-11 22:36

我知道rust的自动类型推导,这是现代化语言最基本的功能。 但是你应该是知道程序的执行顺序,等号右边执行之后,返回了一个泛型T, 按照你的说法,进行类型推导,编译器读取等号左边的信息(显式的说明类型是u32), 那么rust类型系统中的泛型就出问题了,难道泛型可以随意的你想是什么类型就是什么类型吗。 当然你也可以说,在parse后面还有ok().expect(),但是,这样就会发现rust设计上的问题越来越多了,rust本着想要构建所谓的“安全”,他尽量在静态编译的时候给发现你的“不安全”,或者错误。这个时候,并不是在发现你的错误,而是在容忍你的错误,让你编译出来的程序成为“××”。

@damody 強類型啊! 自動推導太強大 讓你誤會了。

damody 2018-07-11 21:30

強類型啊! 自動推導太強大 讓你誤會了。

1 共 18 条评论, 1 页