< 返回版块

Rust到底是强类型还是弱类型

ltoddy 发表于

先上代码:

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是弱类型了。 我这里有很大疑问。

评论区

damody 2018-07-11T13:30:13.783813

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

作者 ltoddy 2018-07-11T14:36:23.580990

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

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

admin 2018-07-12T02:19:07.375873

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

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

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

作者 ltoddy 2018-07-12T02:28:59.087082

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

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

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

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

作者 ltoddy 2018-07-12T03:30:33.365936

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

cxq 2018-07-12T04:53:38.264756

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

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

laizy 2018-07-12T08:57:40.196227

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

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

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

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

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

laizy 2018-07-12T09:05:35.969060

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

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

damody 2018-07-12T17:21:09.848012

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

fn main() {
    let a = "123";
    let a = 123;
    let a = 123.0;
}
0kaguya 2018-07-14T01:43:37.291131

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

SHA Miao 2018-07-17T06:55:02.496128

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

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

SHA Miao 2018-07-17T07:04:59.789226
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-17T07:25:57.358090

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

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

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

rust-beginner 2018-07-18T04:46:16.634828

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

1 共 14 评论, 共 1 页