2. Variable
• Typescript
• Rust
const num = 123;
num = 456;
// Uncaught TypeError: Assignment to constant variable.
console.log(`The value of num is: ${num}`);
let num = 123;
num = 456;
// error[E0384]: cannot assign twice to immutable variable `num`
println!("The value of numMut is: {}", num);
3. Variable
• Typescript
• Rust
let mut numMut = 123;
numMut = 456;
println!("The value of numMut is: {}", numMut);
let numMut = 123;
numMut = 456;
console.log(`The value of numMut is: ${numMut}`);
4. • Typescript
• Rust
fn add(x: i32, y: i32) -> i32 {
x + y
}
add(1, 2); // 3
function add(x: number, y: number) {
return x + y;
}
add(1, 2); // 3
Function
5. Function
• Typescript
• Rust
function return_undefined(x: number, y: number): void {
const added = x + y;
}
return_undefined(1, 2); // undefined
fn return_unit(x: i32, y: i32) -> () {
let added = x + y;
}
return_unit(1, 2); // ()
6. Lambda expression
• Typescript
• Rust
let add2 = (x: number) => x + 2;
let add3 = (x: number) => {
return x + 3;
}
let add2 = |x| x + 2;
let add3 = |x: i32| -> i32 {
x + 3
};
8. If else / Ternary
• Typescript
• Rust
let state: string = null;
if (condition) {
state = "a";
} else {
state = "b";
}
let state2 = condition ? "a" : "b";
let condition = true;
let state = if condition { "a" } else { "b" };
9. • Typescript
const options = {
cond1: false,
cond2: true,
propA: "a",
propB: "b"
};
let state = options.cond1 ? options.propA
: options.cond2
? doSomeThing(options.propB)
: doAnotherThing("c");
function doSomeThing(str: string) {
return "print: ".concat(str);
}
function doAnotherThing(str: string) {
return "print: ".concat(str);
}
Real World Case Study
10. • Typescript
const options = {
cond1: false,
cond2: true,
propA: "a",
propB: "b"
};
let state = options.cond1 ? options.propA
: options.cond2
? doSomeThing(options.propB)
: doAnotherThing("c");
function doSomeThing(str: string) {
return "print: ".concat(str);
}
function doAnotherThing(str: string) {
return "print: ".concat(str);
}
Real World Case Study
// print: b
11. • Rust
Real World Case Study
let options = Options {
cond1: false,
cond2: true,
propA: String::from("a"),
propB: String::from("b")
};
let state = if options.cond1 {
options.propA
} else if options.cond2 {
do_some_thing(&options.propB)
} else {
do_another_thing(&String::from(""))
};
println!("{:?}", state); // print: b
12. • Rust
Real World Case Study
let options = Options {
cond1: false,
cond2: true,
propA: String::from("a"),
propB: String::from("b")
};
let state = if options.cond1 {
options.propA
} else if options.cond2 {
do_some_thing(&options.propB)
} else {
do_another_thing(&String::from(""))
};
println!("{:?}", state); // print: b
13. • Rust
Real World Case Study
let options = Options {
cond1: false,
cond2: true,
propA: String::from("a"),
propB: String::from("b")
};
let state = if options.cond1 {
options.propA
} else if options.cond2 {
do_some_thing(&options.propB)
} else {
do_another_thing(&String::from(""))
};
println!("{:?}", state); // print: b
14. • Rust
Real World Case Study
let options = Options {
cond1: false,
cond2: true,
propA: String::from("a"),
propB: String::from("b")
};
let state = if options.cond1 {
options.propA
} else if options.cond2 {
do_some_thing(&options.propB)
} else {
do_another_thing(&String::from(""))
};
println!("{:?}", state); // print: b
16. Object v.s Struct
• Typescript
class User {
constructor(
public username: string,
public email: string,
public active: boolean,,
public sign_in_count: number,
) {}
}
const user = new User(
'someusername123',
'someone@example.com',
true,
1
);
61. Think with set and function
filter
let elders= |age| age > 40
74
43
2
38
74
43
62. Think with set and function
1
2
4
3
A
4
5
7
6
B
8
9
11
10
C
f: A -> B g: B -> C
let add_three = |a| a + 3 let add_four= |a| a + 4
63. Think with set and function
1
2
4
3
A
8
9
11
10
C
g ∘ f : A -> C
let add_seven= compose!(add_four, add_three);
64. • Delcarative: describes what you want, but
not how to achieve it.
• Divide and conquer: split big question to
multiple small questions.
Benefit of composition
• Think with data: focus on your goal.
71. Use Case: Variadic Function
let transducer = compose(
tap(x => console.log(`iter_value: ${x}`)),
map(x => x + 1),
take(2)
);
72. Use Case: Variadic Function
let transducer = compose(
tap(x => console.log(`iter_value: ${x}`)),
map(x => x + 1),
take(2)
);
function compose(f, g) {
return x => f(g(x));
};
73. Use Case: Variadic Function
let transducer = compose(
tap(x => console.log(`iter_value: ${x}`)),
map(x => x + 1),
take(2)
);
function compose(f, g) {
return x => f(g(x));
};
function compose(f, g, h) {
return x => f(g(h(x)));
};
74. Use Case: Variadic Function
function compose(…fns) {
return (arg) => fns.reduceRight((acc, fn) => fn(acc), args);
}
let newFunction = compose(
tap(x => console.log(`iter_value: ${x}`)),
map(x => x + 1),
take(2),
tap(x => console.log(`taked_value: ${x}`)),
);
75. Use Case: Variadic Function
macro_rules! compose {
($($fns:expr),+) => {
move |arg| compose!(@inner arg, $($fns),+)
};
(@inner $x:expr, $f:expr, $($fns: expr),+) => {
$f(compose!(@inner $x, $($fns),+))
};
(@inner $x:expr, $f:expr) => {
$f($x)
};
}
$($fns:expr),*: repeat functions
*: zero or more repetitions
+: one or more repetitions
$f:expr: matched function expression
76. Use Case: Variadic Function
macro_rules! compose {
($($fns:expr),+) => {
move |arg| compose!(@inner arg, $($fns),+)
};
(@inner $x:expr, $f:expr, $($fns: expr),+) => {
$f(compose!(@inner $x, $($fns),+))
};
(@inner $x:expr, $f:expr) => {
$f($x)
};
}
fn main() {
let f1 = |x: i32| x + 1;
let f2 = |y: i32| y + 2;
let f3 = |z: i32| z + 3;
let f4 = compose!(f3, f2, f1);
println!("{:?}", f4(4))
}
80. Trace the expansion of macros
#![feature(trace_macros)]
...
fn main() {
let f1 = |x: i32| x + 1;
let f2 = |y: i32| y + 2;
let f3 = |z: i32| z + 3;
trace_macros!(true);
let f4 = compose!(f3, f2, f1);
trace_macros!(false);
println!("{:?}", f4(4))
}
81. Trace the expansion of macros
#![feature(trace_macros)]
...
fn main() {
let f1 = |x: i32| x + 1;
let f2 = |y: i32| y + 2;
let f3 = |z: i32| z + 3;
trace_macros!(true);
let f4 = compose!(f3, f2, f1);
trace_macros!(false);
println!("{:?}", f4(4))
}
note: trace_macro
--> src/main.rs:18:14
|
18 | let f4 = compose!(f3, f2, f1);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: expanding `compose! { f3, f2, f1 }`
= note: to `move | arg | compose! (@inner arg, f3, f2, f1)`
= note: expanding `compose! { @inner arg, f3, f2, f1 }`
= note: to `f3 (compose! (@inner arg, f2, f1))`
= note: expanding `compose! { @inner arg, f2, f1 }`
= note: to `f2 (compose! (@inner arg, f1))`
= note: expanding `compose! { @inner arg, f1 }`
= note: to `f1 (arg)`