[译]参照TypeScript来学习Rust-S2

变量和可变性

在Rust中,通过let修饰的变量是不可变的。

fn main() {
    // IMMUTABLE
    let x = 5;
    println!("The value of x is: {}", x); // 5
    // x = 6; // CANNOT ASSIGN TWICE TO IMMUTABLE VARIABLE 
    // println!("The value of x is: {}", x);
}

在TypeScript中,我们如果需要创建一个不可变的变量需要用const修饰符。

// IMMUTABLE
const x = 5;
console.log(`The value of x is: ${x}`); // 5
// x = 6; // CANNOT ASSIGN BECAUSE CONSTANT
// console.log(`The value of x is: ${x}`)

注意:在Rust和TypeScript中,变量类型是通过由右往左推导出来的,我们可以不用严格的定义变量类型。

在Rust中,定义一个可变的变量需要通过let mut来修饰,

fn main() {
    // MUTABLE
    let mut y = 5;
    println!("The value of y is: {}", y); // 5
    y = 6;
    println!("The value of y is: {}", y); // 6
}

在TypeScript中,使用let来定义一个可变的变量。

// MUTABLE
let y = 5;
console.log(`The value of y is: ${y}`); // 5
y = 6;
console.log(`The value of y is: ${y}`); // 6

使用Rust,可以在运行时设置一个用let和let mut设置的变量:

fn another_function(x: i32) -> i32 {
    return x + 1;
}

fn main() {
    // RUN-TIME ASSIGNMENT
    let z = another_function(5);
    println!("The value of z is: {}", z); // 6
    let mut zz = another_function(5);
    zz = zz + 1;
    println!("The value of zz is: {}", zz); // 7
}

同样,对于TypeScript,使用const和let设置的变量:

const anotherFunction = (x: number): number => x + 1;
// RUN-TIME ASSIGNMENT
const z = anotherFunction(5);
console.log(`The value of z is: ${z}`); // 6
let zz = anotherFunction(5);
zz = zz + 1;
console.log(`The value of zz is: ${zz}`); // 7

Rust还有另一种不可变的变量类型,const。与之不同的是,让const不能在运行时设置(只能在编译时设置). 按照惯例,const变量名称是用大写的。

fn another_function(x: i32) -> i32 {
    return x + 1;
}

fn main() {
    // CONSTANT
    const MAX_POINTS: i32 = 100000;
    println!("The value of MAX_POINTS is: {}", MAX_POINTS); // 100000
    const ANOTHER_CONSTANT: i32 = 100000 + 1; // COMPILE-TIME ASSIGNMENT
    println!("The value of ANOTHER_CONSTANT is: {}", ANOTHER_CONSTANT); // 100001 
    // const YET_ANOTHER_CONSTANT: i32 = another_function(1); // CANNOT RUN-TIME ASSIGNMENT
    // println!("The value of YET_ANOTHER_CONSTANT is: {}", YET_ANOTHER_CONSTANT);
}

TypeScript没有等效的变量类型。 在这种情况下,通常使用TypeScript const变量类型,并按惯例将其大写。

Rust允许人们重新定义或修饰let类型的变量:

fn main() {
    // SHADOWING
    let a = 5;
    let a = a + 1;
    let a = a * 2;
    println!("The value of a is: {}", a); // 12
}

注意:重要的是要观察到结果变量a仍然是不可变的。 另外,虽然在此示例中未示出,但是变量类型也可能因修饰而有所不同。

TypeScript没有等效功能,即TypeScript无法重新声明块范围的变量。 在TypeScript中,通常在这种情况下只是创建一个新的const变量名。

数据类型

现在,我们遍历Rust Book数据类型部分中的示例; 首先从Rust标量类型开始。

fn main() {
    // NUMBERS
    let i = 1; // i32
    println!("The value of i is: {}", i); // 1
    let j = 1.1; // f64
    println!("The value of j is: {}", j); // 1.1

    // BOOLEAN
    let b = true; // bool
    println!("The value of b is: {}", b); // true

    // CHARACTER
    let c = 'a'; // char
    println!("The value of c is: {}", c); // a
}

让我们回一下TypeScript中的等效项(称为基本数据类型):

// NUMBERS
const i = 1; // number
console.log(`The value of i is: ${i}`); // 1
const j = 1.1 // number
console.log(`The value of j is: ${j}`); // 1.1

// BOOLEAN
const b = true; // boolean
console.log(`The value of b is: ${b}`); // true

// CHARACTER
const c = 'a'; // string
console.log(`The value of c is: ${c}`); // a

一个很大的不同是,在JavaScript(或者TypeScript)中,所有数字都是64位浮点数,而Rust则有许多整数和浮点类型。

另一个区别是JavaScript(或者TypeScript)具有可以包含任意数量字符的原始字符串类型。 不只是一个字符。

Rust有两种复合类型; 元组和数组。 元组是各种类型的值的固定长度的有序列表。 数组是相同类型的值的固定长度的有序列表。

fn main() {
    // TUPLE
    let tup = (0, 'a', 1.1); // (i32, char, f64)
    println!("The second value of tup is: {}", tup.1); // a
    let (t1, t2, t3) = tup;
    println!("The value of t1 is: {}", t1); // 0
    println!("The value of t2 is: {}", t2); // a
    println!("The value of t3 is: {}", t3); // 1.1

    // ARRAY
    let arr = [0, 1, 2]; // [i32, 3]
    println!("The second value of arr is: {}", arr[1]); // 1
    let [a1, a2, a3] = arr;
    println!("The value of a1 is: {}", a1); // 0
    println!("The value of a2 is: {}", a2); // 0
    println!("The value of a3 is: {}", a3); // 0
}

在TypeScript中,元组本质上与Rust中相同。 但是,数组的长度是任意的,例如,我们可以附加一个值。

// TUPLE
const tup: [number, string, number] = [0, 'a', 1.1]; // [number, string, number]
console.log(`The second value of tup is: ${tup[1]}`); // a
const [t1, t2, t3] = tup;
console.log(`The value of t1 is: ${t1}`); // 0 
console.log(`The value of t2 is: ${t2}`); // a
console.log(`The value of t3 is: ${t3}`); // 1.1

// ARRAY
const arr = [0, 1, 2]; // number[]
console.log(`The second value of arr is: ${arr[1]}`); // 1
const [a1, a2, a3] = arr;
console.log(`The value of a1 is: ${a1}`); // 0 
console.log(`The value of a2 is: ${a2}`); // 1
console.log(`The value of a3 is: ${a3}`); // 2
arr[3] = 3;
console.log(`The fourth value of arr is: ${arr[3]}`); // 3

对象或者引用

到目前为止,Rust和TypeScript极度相似。 然而,复合类型上却有很大的不同。 不同之处在于它们各自如何将复合类型存储在变量中。

在Rust中,复合类型变量的值是对象本身。

fn main() {
    ...
    // OBJECT OR REFEREENCE
    let mut tup2 = (0, 'a', 1.1); // (i32, char, f64)
    let tup3 = tup2;
    tup2.0 = 1;
    println!("The first value of tup2 is: {}", tup2.0); // 1
    println!("The first value of tup3 is: {}", tup3.0); // 0

    let mut arr2 = [0, 1, 2]; // [i32, 3]
    let arr3 = arr2;
    arr2[0] = 1;
    println!("The first value of arr2 is: {}", arr2[0]); // 1
    println!("The first value of arr3 is: {}", arr3[0]); // 0
}

我们观察:

另一方面,在TypeScript中,复合类型的值是对该对象的引用。

在TypeScript中,基本类型(布尔,数字,字符串)的行为类似于Rust,其变量值为对象本身。

// OBJECT OR REFERENCE
const tup2: [number, string, number] = [0, 'a', 1.1]; // [number, string, number]
const tup3 = tup2;
tup2[0] = 1;
console.log(`The first value of tup2 is ${tup2[0]}`); // 1
console.log(`The first value of tup3 is ${tup3[0]}`); // 1

const arr2 = [0, 1, 2]; // number[]
const arr3 = arr2;
arr2[0] = 1;
console.log(`The first value of arr2 is ${arr2[0]}`); // 1
console.log(`The first value of arr3 is ${arr3[0]}`); // 1

我们观察:

我已经看到,这将使我适应一些,因为我将TypeScript模式蚀刻到了大脑。

流程控制

在Rust和TypeScript之间,围绕控制流的核心概念几乎是相同的。 同样在TypeScript中实现: 我们观察: