Mark Mara

Mark Mara

1573573005

Learning Rust by Contrasting with TypeScript

Prerequisites

The common requirement for both the Rust and TypeScript projects is the GIT version control system.

Rust Installation

Rust installation involves installing global binaries, e.g., rustc and cargo. This article was written using version 1.38.0.

TypeScript Installation

TypeScript depends on the JavaScript runtime Node.js; must first be installed. This installation involves installing global binaries, e.g., node and npm. This article was written using version 12.13.0.

TypeScript itself is installed as a Node.js project dependency as we will see below.

Rust Project Creation

Project setup involves running the cargo command to scaffold a Rust project:

note: The completed project is available for download.

cargo new r00_hello_world

The project is also initialized as a GIT repository with a .gitignore file. It also includes the sample source file: src/main.rs:

main.rs

fn main() {
    println!("Hello, world!");
}

TypeScript Project Creation

Project setup first requires scaffolding a JavaScript Node.js project by creating a folder and using the npm command:

note: The completed project is available for download.

mkdir t00_hello_world
cd t00_hello_world
npm init --yes

We initialize the project as a GIT repository with:

git init

and create a .gitignore file:
.gitignore

node_modules

We then convert the JavaScript Node.js project into TypeScript by first installing the TypeScript development dependency:

npm install -D typescript

We then create a TypeScript configuration file: tsconfig.json. Here we use the microsoft/TypeScript-Node-Starter example.

We update the .gitignore file to ignore the output directory: dist:

.gitignore

node_modules
dist

We update the package.json; updating the main value and adding a start and build to scripts:

package.json

{
  "name": "t00_hello_world",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "scripts": {
    "start": "node dist/index.js",
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^3.6.4"
  }
}

Finally, we create the source file: src/index.ts:

index.ts

console.log('Hello World!');

Rust Build

During development, we use the following command to build a Rust project:

cargo build

The output is a compiled OS executable: target/debug/r00_hello_world.

For release, an optimized build, we use the following command:

cargo build --release

The output is a compiled OS executable: target/release/r00_hello_world.

TypeScript Build

We use the following command to build a TypeScript project:

npm run build

The output is a transpiled JavaScript file: dist/index.js.

Rust Execute

We simply execute the compiled OS executable as we would any other:

./target/debug/r00_hello_world

We can also use the command:

cargo run

to both build and run.

TypeScript Execute

We execute the transpiled JavaScript file using the npm script:

npm start

or we can execute it directly:

node dist/index.js

In either case, we are executing our project on top of the JavaScript runtime.

Variables and Mutability

Let us walk through the examples in the Rust Book Variables and Mutability section and contrast them with TypeScript.

With Rust, a variable set with let as shown is immutable.

main.rs

...
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);
    ...
}

In TypeScript, the equivalent is a variable set with const.

index.ts

...
// 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}`)
...

note: In both Rust and TypeScript the variable types are inferred from the right-hand-side; thus explicit typing is not required.

With Rust, a variable set with let mut as shown is mutable.

main.rs

...
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
    ...
}

In TypeScript, the equivalent is a variable set with let.

index.ts

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

With Rust, a variable set with let and let mut can be set at run-time:

main.rs

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
    ...
}

Likewise for TypeScript for variables set with both const and let:
index.ts

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 has another immutable variable type; const. Unlike, let however, const cannot be set at run-time (only set at compile-time). The upper-case const variable names is by convention.
main.rs

n 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 does not have an equivalent variable type. For this situation, one typically uses the TypeScript const variable type and simply name it with upper-case by convention.

Rust allows one to redefine, or shadow, a variable of type let:

main.rs

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

note: It is important to observe that the resultant variable a can still be immutable. Also, while not illustrated in this example, the variable types can also differ through shadowing.

TypeScript does not have an equivalent feature, i.e., TypeScript cannot redeclare a block-scoped variable. In TypeScript, one often simply creates a new const variable name in this situation.

Data Types

Now we walk through the examples in the Rust Book Data Typessection; starting first with the Rust scalar types.

main.rs

...
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
    ...
}

Let us consider the equivalents (called primitives) in TypeScript:
index.ts

...
// 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
...

One big difference is that in JavaScript (and thus TypeScript) all numbers are 64-bit floating point where-as Rust there are a number of integer and floating point types.

Another difference is that JavaScript (and thus TypeScript) has a primitive string type that can contain an arbitrary number of characters; not just a single character.

Rust has two compound types; tuple and array. A tuple being a fixed length ordered list of values of varying types. An array being a fixed length ordered list of values of the same type.

main.rs

...
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
    ...
}

In TypeScript, a tuple is essentially the same as in Rust. An array, however is of arbitrary length, e.g., we can append a value.

index.ts

...
// 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
...

Sidebar into Object or Reference

So far, Rust and TypeScript have been relatively similar; however there is a big difference lurking in compound types. The difference is in how each of them store compound types in variables.

In Rust, the value of a compound type variable is the object itself.

main.rs

...
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
}

Observations:

  • We have to use let mut for tup2 in order to mutate the value later
  • Assigning tup2 to tup3 (copying their value) creates a completely new tuple
  • The result is that mutating tup2 has no relevance to tup3
  • Some logic applies to arrays

On the other hand, in TypeScript, the value of a compound type is a reference to the object.

note: In TypeScript, primitive types (boolean, number, string) behave like Rust with the value of the variable being the object itself.

index.ts

...
// 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
...

Observations:

  • We can use const for tup2 because we are mutating the object and not the reference
  • Assigning tup2 to tup3 (copying their value) copies the reference to the same tuple object
  • The result that mutating tup2 is really mutating the common tuple object referenced by both tup2 and tup3
  • Same logic applies to arrays

I can already see that this is going to take me some getting used to as I have the TypeScript pattern etched into my brain.

Addendum 11/8/19: Having written a couple of more articles, I have come to realize (believe it was buried in the Rust book too), that the compound types tuple and array are likely only to be used as constants, e.g., days of the week, and as such this difference between Rust and TypeScript is irrelevant. Specifically, we will likely be using the Rust Vec type as the equivalent to TypeScript arrays.

Control Flow

The core concepts around flow of control are virtually identical between Rust and TypeScript; confirming this by walking through examples in the Rust Book Control Flowsection.

fn another_function() {
    println!("Another function.");
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

fn abs(x: i32) -> i32 {
    if x >= 0 {
        return x;
    }
    x * -1
}

fn main() {
    // FUNCTIONS
    another_function();
    let x = 0;
    let y = plus_one(x);
    println!("The value of y is: {}", y); // 1
    let a = -1;
    let b = abs(a);
    println!("The value of b is: {}", b); // 1

    // COMMENTS
    /*
    Rust supports
    mult-line comments.
    */

    // IF EXPRESSIONS
    let number = 3;
    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }

    let number = 6;
    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }

    let condition = true;
    let number = if condition {
        5
    } else {
        6
    };
    println!("The value of number is: {}", number);

    // LOOPS
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    println!("The result is {}", result);

    let mut number = 3;
    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }
    println!("LIFTOFF!!!");

    let a = [10, 20, 30, 40, 50];
    for element in a.iter() {
        println!("the value is: {}", element);
    }
}

The same implemented in TypeScript:
index.ts

const anotherFunction = () => console.log('Another funciton.');

const plusOne = (x: number): number => x + 1;

const abs = (x: number): number => {
  if (x >= 0) {
    return x;
  }
  return x * -1;
}

// FUNCTIONS
anotherFunction();
const x = 0;
const y = plusOne(x);
console.log(`The value of y is: ${y}`); // 1
const a = -1;
const b = abs(a);
console.log(`The value of b is: ${b}`); // 1

// COMMENTS
/*
TypeScript supports
multi-line comments.
*/

// IF EXPRESSIONS
const number = 3;
if (number < 5) {
  console.log('condition was true');
} else {
  console.log('condition was false');
}

const number2 = 6;
if (number2 % 4 === 0) {
  console.log('number2 is divisible by 4');
} else if (number2 % 3 === 0) {
  console.log('number2 is divisible by 3');
} else if (number2 % 2 === 0) {
  console.log('number2 is divisible by 2');
}

const condition = true;
const number3 = condition ? 5 : 6;
console.log(`The value of number3 is: ${number3}`);

let counter = 0;
let result: number;
while (true) {
  counter += 1;
  if (counter === 10) {
    result = counter * 2;
    break;
  }
}
console.log(`The result is ${result}`);

let number4 = 3;
while (number4 !== 0) {
  console.log(`${number4}!`);
  number4 -= 1;
}
console.log('LIFTOFF!!!');

const arr = [10, 20, 30, 40, 50];
arr.forEach(element => console.log(`the value is: ${element}`));

Observations:

  • The Rust pattern of having the last line of a function being an expression (with no semi-colon) to mean the return value was novel to me
  • Having gotten used to the TypeScript ternary operator, found the Rust equivalent a bit verbose
  • With Rust, having a loop return a value is novel to me

Next Steps

We dive into the complexities of ownership in the next article: Learning Rust by Contrasting with TypeScript: Part 3.

#rust #TypeScript

What is GEEK

Buddha Community

Learning Rust by Contrasting with TypeScript

Serde Rust: Serialization Framework for Rust

Serde

*Serde is a framework for serializing and deserializing Rust data structures efficiently and generically.*

You may be looking for:

Serde in action

Click to show Cargo.toml. Run this code in the playground.

[dependencies]

# The core APIs, including the Serialize and Deserialize traits. Always
# required when using Serde. The "derive" feature is only required when
# using #[derive(Serialize, Deserialize)] to make Serde work with structs
# and enums defined in your crate.
serde = { version = "1.0", features = ["derive"] }

# Each data format lives in its own crate; the sample code below uses JSON
# but you may be using a different one.
serde_json = "1.0"

 

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 1, y: 2 };

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&point).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: Point = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}

Getting help

Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the #rust-questions or #rust-beginners channels of the unofficial community Discord (invite: https://discord.gg/rust-lang-community), the #rust-usage or #beginners channels of the official Rust Project Discord (invite: https://discord.gg/rust-lang), or the #general stream in Zulip. For asynchronous, consider the [rust] tag on StackOverflow, the /r/rust subreddit which has a pinned weekly easy questions post, or the Rust Discourse forum. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time.

Download Details:
Author: serde-rs
Source Code: https://github.com/serde-rs/serde
License: View license

#rust  #rustlang 

Mark Mara

Mark Mara

1573573005

Learning Rust by Contrasting with TypeScript

Prerequisites

The common requirement for both the Rust and TypeScript projects is the GIT version control system.

Rust Installation

Rust installation involves installing global binaries, e.g., rustc and cargo. This article was written using version 1.38.0.

TypeScript Installation

TypeScript depends on the JavaScript runtime Node.js; must first be installed. This installation involves installing global binaries, e.g., node and npm. This article was written using version 12.13.0.

TypeScript itself is installed as a Node.js project dependency as we will see below.

Rust Project Creation

Project setup involves running the cargo command to scaffold a Rust project:

note: The completed project is available for download.

cargo new r00_hello_world

The project is also initialized as a GIT repository with a .gitignore file. It also includes the sample source file: src/main.rs:

main.rs

fn main() {
    println!("Hello, world!");
}

TypeScript Project Creation

Project setup first requires scaffolding a JavaScript Node.js project by creating a folder and using the npm command:

note: The completed project is available for download.

mkdir t00_hello_world
cd t00_hello_world
npm init --yes

We initialize the project as a GIT repository with:

git init

and create a .gitignore file:
.gitignore

node_modules

We then convert the JavaScript Node.js project into TypeScript by first installing the TypeScript development dependency:

npm install -D typescript

We then create a TypeScript configuration file: tsconfig.json. Here we use the microsoft/TypeScript-Node-Starter example.

We update the .gitignore file to ignore the output directory: dist:

.gitignore

node_modules
dist

We update the package.json; updating the main value and adding a start and build to scripts:

package.json

{
  "name": "t00_hello_world",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "scripts": {
    "start": "node dist/index.js",
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^3.6.4"
  }
}

Finally, we create the source file: src/index.ts:

index.ts

console.log('Hello World!');

Rust Build

During development, we use the following command to build a Rust project:

cargo build

The output is a compiled OS executable: target/debug/r00_hello_world.

For release, an optimized build, we use the following command:

cargo build --release

The output is a compiled OS executable: target/release/r00_hello_world.

TypeScript Build

We use the following command to build a TypeScript project:

npm run build

The output is a transpiled JavaScript file: dist/index.js.

Rust Execute

We simply execute the compiled OS executable as we would any other:

./target/debug/r00_hello_world

We can also use the command:

cargo run

to both build and run.

TypeScript Execute

We execute the transpiled JavaScript file using the npm script:

npm start

or we can execute it directly:

node dist/index.js

In either case, we are executing our project on top of the JavaScript runtime.

Variables and Mutability

Let us walk through the examples in the Rust Book Variables and Mutability section and contrast them with TypeScript.

With Rust, a variable set with let as shown is immutable.

main.rs

...
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);
    ...
}

In TypeScript, the equivalent is a variable set with const.

index.ts

...
// 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}`)
...

note: In both Rust and TypeScript the variable types are inferred from the right-hand-side; thus explicit typing is not required.

With Rust, a variable set with let mut as shown is mutable.

main.rs

...
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
    ...
}

In TypeScript, the equivalent is a variable set with let.

index.ts

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

With Rust, a variable set with let and let mut can be set at run-time:

main.rs

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
    ...
}

Likewise for TypeScript for variables set with both const and let:
index.ts

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 has another immutable variable type; const. Unlike, let however, const cannot be set at run-time (only set at compile-time). The upper-case const variable names is by convention.
main.rs

n 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 does not have an equivalent variable type. For this situation, one typically uses the TypeScript const variable type and simply name it with upper-case by convention.

Rust allows one to redefine, or shadow, a variable of type let:

main.rs

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

note: It is important to observe that the resultant variable a can still be immutable. Also, while not illustrated in this example, the variable types can also differ through shadowing.

TypeScript does not have an equivalent feature, i.e., TypeScript cannot redeclare a block-scoped variable. In TypeScript, one often simply creates a new const variable name in this situation.

Data Types

Now we walk through the examples in the Rust Book Data Typessection; starting first with the Rust scalar types.

main.rs

...
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
    ...
}

Let us consider the equivalents (called primitives) in TypeScript:
index.ts

...
// 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
...

One big difference is that in JavaScript (and thus TypeScript) all numbers are 64-bit floating point where-as Rust there are a number of integer and floating point types.

Another difference is that JavaScript (and thus TypeScript) has a primitive string type that can contain an arbitrary number of characters; not just a single character.

Rust has two compound types; tuple and array. A tuple being a fixed length ordered list of values of varying types. An array being a fixed length ordered list of values of the same type.

main.rs

...
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
    ...
}

In TypeScript, a tuple is essentially the same as in Rust. An array, however is of arbitrary length, e.g., we can append a value.

index.ts

...
// 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
...

Sidebar into Object or Reference

So far, Rust and TypeScript have been relatively similar; however there is a big difference lurking in compound types. The difference is in how each of them store compound types in variables.

In Rust, the value of a compound type variable is the object itself.

main.rs

...
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
}

Observations:

  • We have to use let mut for tup2 in order to mutate the value later
  • Assigning tup2 to tup3 (copying their value) creates a completely new tuple
  • The result is that mutating tup2 has no relevance to tup3
  • Some logic applies to arrays

On the other hand, in TypeScript, the value of a compound type is a reference to the object.

note: In TypeScript, primitive types (boolean, number, string) behave like Rust with the value of the variable being the object itself.

index.ts

...
// 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
...

Observations:

  • We can use const for tup2 because we are mutating the object and not the reference
  • Assigning tup2 to tup3 (copying their value) copies the reference to the same tuple object
  • The result that mutating tup2 is really mutating the common tuple object referenced by both tup2 and tup3
  • Same logic applies to arrays

I can already see that this is going to take me some getting used to as I have the TypeScript pattern etched into my brain.

Addendum 11/8/19: Having written a couple of more articles, I have come to realize (believe it was buried in the Rust book too), that the compound types tuple and array are likely only to be used as constants, e.g., days of the week, and as such this difference between Rust and TypeScript is irrelevant. Specifically, we will likely be using the Rust Vec type as the equivalent to TypeScript arrays.

Control Flow

The core concepts around flow of control are virtually identical between Rust and TypeScript; confirming this by walking through examples in the Rust Book Control Flowsection.

fn another_function() {
    println!("Another function.");
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

fn abs(x: i32) -> i32 {
    if x >= 0 {
        return x;
    }
    x * -1
}

fn main() {
    // FUNCTIONS
    another_function();
    let x = 0;
    let y = plus_one(x);
    println!("The value of y is: {}", y); // 1
    let a = -1;
    let b = abs(a);
    println!("The value of b is: {}", b); // 1

    // COMMENTS
    /*
    Rust supports
    mult-line comments.
    */

    // IF EXPRESSIONS
    let number = 3;
    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }

    let number = 6;
    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }

    let condition = true;
    let number = if condition {
        5
    } else {
        6
    };
    println!("The value of number is: {}", number);

    // LOOPS
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    println!("The result is {}", result);

    let mut number = 3;
    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }
    println!("LIFTOFF!!!");

    let a = [10, 20, 30, 40, 50];
    for element in a.iter() {
        println!("the value is: {}", element);
    }
}

The same implemented in TypeScript:
index.ts

const anotherFunction = () => console.log('Another funciton.');

const plusOne = (x: number): number => x + 1;

const abs = (x: number): number => {
  if (x >= 0) {
    return x;
  }
  return x * -1;
}

// FUNCTIONS
anotherFunction();
const x = 0;
const y = plusOne(x);
console.log(`The value of y is: ${y}`); // 1
const a = -1;
const b = abs(a);
console.log(`The value of b is: ${b}`); // 1

// COMMENTS
/*
TypeScript supports
multi-line comments.
*/

// IF EXPRESSIONS
const number = 3;
if (number < 5) {
  console.log('condition was true');
} else {
  console.log('condition was false');
}

const number2 = 6;
if (number2 % 4 === 0) {
  console.log('number2 is divisible by 4');
} else if (number2 % 3 === 0) {
  console.log('number2 is divisible by 3');
} else if (number2 % 2 === 0) {
  console.log('number2 is divisible by 2');
}

const condition = true;
const number3 = condition ? 5 : 6;
console.log(`The value of number3 is: ${number3}`);

let counter = 0;
let result: number;
while (true) {
  counter += 1;
  if (counter === 10) {
    result = counter * 2;
    break;
  }
}
console.log(`The result is ${result}`);

let number4 = 3;
while (number4 !== 0) {
  console.log(`${number4}!`);
  number4 -= 1;
}
console.log('LIFTOFF!!!');

const arr = [10, 20, 30, 40, 50];
arr.forEach(element => console.log(`the value is: ${element}`));

Observations:

  • The Rust pattern of having the last line of a function being an expression (with no semi-colon) to mean the return value was novel to me
  • Having gotten used to the TypeScript ternary operator, found the Rust equivalent a bit verbose
  • With Rust, having a loop return a value is novel to me

Next Steps

We dive into the complexities of ownership in the next article: Learning Rust by Contrasting with TypeScript: Part 3.

#rust #TypeScript

Jerad  Bailey

Jerad Bailey

1598891580

Google Reveals "What is being Transferred” in Transfer Learning

Recently, researchers from Google proposed the solution of a very fundamental question in the machine learning community — What is being transferred in Transfer Learning? They explained various tools and analyses to address the fundamental question.

The ability to transfer the domain knowledge of one machine in which it is trained on to another where the data is usually scarce is one of the desired capabilities for machines. Researchers around the globe have been using transfer learning in various deep learning applications, including object detection, image classification, medical imaging tasks, among others.

#developers corner #learn transfer learning #machine learning #transfer learning #transfer learning methods #transfer learning resources

sophia tondon

sophia tondon

1620898103

5 Latest Technology Trends of Machine Learning for 2021

Check out the 5 latest technologies of machine learning trends to boost business growth in 2021 by considering the best version of digital development tools. It is the right time to accelerate user experience by bringing advancement in their lifestyle.

#machinelearningapps #machinelearningdevelopers #machinelearningexpert #machinelearningexperts #expertmachinelearningservices #topmachinelearningcompanies #machinelearningdevelopmentcompany

Visit Blog- https://www.xplace.com/article/8743

#machine learning companies #top machine learning companies #machine learning development company #expert machine learning services #machine learning experts #machine learning expert

Jackson  Crist

Jackson Crist

1617331066

Intro to Reinforcement Learning: Temporal Difference Learning, SARSA Vs. Q-learning

Reinforcement learning (RL) is surely a rising field, with the huge influence from the performance of AlphaZero (the best chess engine as of now). RL is a subfield of machine learning that teaches agents to perform in an environment to maximize rewards overtime.

Among RL’s model-free methods is temporal difference (TD) learning, with SARSA and Q-learning (QL) being two of the most used algorithms. I chose to explore SARSA and QL to highlight a subtle difference between on-policy learning and off-learning, which we will discuss later in the post.

This post assumes you have basic knowledge of the agent, environment, action, and rewards within RL’s scope. A brief introduction can be found here.

The outline of this post include:

  • Temporal difference learning (TD learning)
  • Parameters
  • QL & SARSA
  • Comparison
  • Implementation
  • Conclusion

We will compare these two algorithms via the CartPole game implementation. This post’s code can be found here :QL code ,SARSA code , and the fully functioning code . (the fully-functioning code has both algorithms implemented and trained on cart pole game)

The TD learning will be a bit mathematical, but feel free to skim through and jump directly to QL and SARSA.

#reinforcement-learning #artificial-intelligence #machine-learning #deep-learning #learning