原文:Rust for JavaScript Developers – Variables and Data Types
翻译:http://www.mzh.ren/
这是写给javascript程序员的rust教程系列文章的第二部分:变量与数据类型。
第一部分见:写给javascript程序员的rust教程(一)工具链概述【译】 – 码中人。
变量
JavaScript有三种声明变量的方法:var,const和let。Rust也有const和let,但与JavaScript相比,它们的工作方式截然不同。
let
在rust中,用let 声明 变量:
let a = 123;
正如预期的那样,这将为变量 a 分配 123 的值。但默认情况下 ,Rust 变量不可更改,也就是说在赋值之后,你将无法改变它的值。
let a = 123;a = 456; // Error!
乍一看,这与JavaScript的const类似,但JavaScript的const并不能使变量不可变,它只是使绑定不可变。
如果你想让变量可变,你需要使用mut关键字显式地声明。
let mut a = 123;a = 456; // No Error
const
Rust的const与JavaScript的const也有很大的不同–最好把Rust的const看成是一个常量值的 “标签”。在编译时,它们在所有被使用的地方都会被它们的实际值取代。它通常用于端口号、超时值、错误代码等常量。
你也可以在全局级别定义const外部函数,这是用let做不到的。
数据类型
数值
在JavaScript中,我们同时具有数字类型(整数(无小数点的数字)和浮点数(有小数点的数字))。
在Rust中,整数和浮点数有很多选择,但默认情况下,我们可以将i32用作整数,将f64用作浮点数。
let x = 123; // i32let y = 4.5; // f64
布尔值
非常简单-JavaScript和Rust都具有带有true / false值的布尔值。
let x = false; // bool
字符串
在使用JavaScript时,我们通常不会过多考虑字符串-它们总是可以“正常工作”。在Rust中,字符串的类型有很多种,其中被广泛使用的字符串是:String和&str。
String是可变长的,&str 是定长的。
当你使用字符串字面量创建字符串,该字符串默认为&str类型。
let name = "Saitama"; // &str
可以使用String::from 或 t0_string 方法创建String 类型字符串。
let name = String::from("Genos"); // Stringlet name2 = "King".to_string(); // String
通过 as_str 函数可以将 String 类型转化成 &str 类型。
let name2 = "King".to_string(); // Stringlet name3 = name2.as_str(); // &str
关于字符串,后续文章会进一步讨论。
Optionals
JavaScript的空值有两种类型–undefined和null。undefined是指变量、属性等未被定义,而null则是指故意为空。
Rust 完全没有这些–它甚至没有一个专门的 null 数据类型。与之替代,它有一个叫做Option的东西。当我们遇到一个值可能为空或初始未定义的情况时,就会使用这个 Option 类型。
使用过TypeScript/Flow的人可能会发现这里有一些相似之处,但在如何创建和使用optionals方面却有很大不同。
假设我们想写一个函数,接收一个文件路径并返回其内容。并且要求当空字符串作为文件路径传递时,我们想返回一个 “null “值。
下面是我们在JavaScript/TypeScript中的写法:
function read_file(path: string): string | null { const contents = "hello"; if (path !== "") { return contents; } return null;}
Rust 通过 Option 完成相同的操作:
fn read_file(path: &str) -> Option { let contents = "hello"; if path != "" { return Some(contents); } return None;}
你可以看到,对于空值,我们返回None,但对于非空值,我们并没有原封不动地返回内容,而是将其 “包裹 “在Some里面并返回。返回类型也不是TypeScript例子中的 “string或null”,而是 “Option that contains &str “类型。
下面是你在JavaScript/TypeScript中调用read_file这个函数的方式:
function main() { const file_contents = read_file("/path/to/file"); if (file_contents !== null) { console.log(file_contents); // file_contents is refined to string type } else { console.log("Empty!"); }}
Rust 调用方式:
fn main() { let file = read_file("path/to/file"); if file.is_some() { let contents = file.unwrap(); println!("{}", contents); } else { println!("Empty!"); }}
如你所见,我们需要手动 “拆开 “Option来获取里面的内容。
数组
与字符串类似,Rust有两种类型的数组–一种是固定大小的数组(简称为 “Array”),另一种是可以增长/收缩大小的数组(称为 “Vectors”)。
Arrays
fn main() { let list = [1, 2, 3]; println!("{:?}", list);}
Vectors
fn main() { let mut list = vec![1, 2, 3]; list.push(4); println!("{:?}", list);}
对象
从技术上讲,所有的非原生类型在JavaScript中都是 “对象”,但我们通常使用 “对象 “一词来做两件事–Bag of data (数据包) 和hashmap(hash字典)。
Bag of data (数据包)
与其他语言不同的是,JavaScript最酷的地方,你不需要经过很多仪式来创建一个对象。比如,要在JavaScript中创建一个雇员对象:
function main() { const employee = { name: "Saitama", age: 25, occupation: "Hero", };}
Rust创建类似javascript的对象,需要用到struct:
struct Employee { name: String, age: i32, occupation: String,}fn main() { let employee = Employee { name: "Saitama".to_string(), age: 25, occupation: "Hero".to_string(), };}
HashMap
在JavaScript中,要创建具有任意键值对的对象,我们可以使用对象字面量或Map对象:
function main() { const colors = new Map(); colors.set("white", "#fff"); colors.set("black", "#000"); console.log(colors.get("white")); // #fff}
Rust 可以使用HashMap类型实现:
use std::collections::HashMap;fn main() { let mut colors = HashMap::new(); colors.insert("white".to_string(), "#fff"); colors.insert("black".to_string(), "#000"); println!("{:?}", colors.get("white").unwrap()); // #fff}
请注意上面 unwrap 的用法。HashMap的get方法返回的是一个Option类型,我们需要对这个Option类型进行解包来获取里面的值。
谢谢你的阅读