diff --git a/ch10.html b/ch10.html new file mode 100644 index 0000000..ea055cb --- /dev/null +++ b/ch10.html @@ -0,0 +1,318 @@ +Rust Study
+

Generic Types, Traits, and Lifetimes

+
    +
  • Generic Type : 구체화된 타입을 추상화한 대체 타입 (보통 함수 파라미터로 활용)
  • +
  • Trait : Generic과 결합하여 특정 동작을 하는 타입으로 제한하는 역할
  • +
  • Lifetime : Generic의 일종으로 컴파일러에게 참조자들의 관계에 대해 정보 전달
  • +
+
+
+

Generic 적용해보기 1 - 전

+
fn largest(list: &[i32]) -> i32 {
+    let mut largest = list[0];
+
+    for &item in list.iter() {
+        if item > largest {
+            largest = item;
+        }
+    }
+
+    largest
+}
+
+fn main() {
+    let numbers = vec![34, 50, 25, 100, 65];
+
+    let result = largest(&numbers);
+    println!("The largest number is {}", result);
+
+    let numbers = vec![102, 34, 6000, 89, 54, 2, 43, 8];
+
+    let result = largest(&numbers);
+    println!("The largest number is {}", result);
+}
+
+
+
+

Generic 적용해보기 1 - 후

+
fn largest<T>(list: &[T]) -> T { # 여기 주목
+    let mut largest = list[0];
+
+    for &item in list.iter() {
+        if item > largest {      # binary operation `>` cannot be applied to type `T`
+            largest = item;
+        }
+    }
+
+    largest
+}
+
+fn main() {
+    let numbers = vec![34, 50, 25, 100, 65];
+
+    let result = largest(&numbers);
+    println!("The largest number is {}", result);
+
+    let chars = vec!['y', 'm', 'a', 'q'];
+
+    let result = largest(&chars);
+    println!("The largest char is {}", result);
+}
+
+
+
+

Generic 적용해보기 2 - 전

+
struct Point<T> {
+    x: T,
+    y: T,
+}
+
+fn main() {
+    let wont_work = Point { x: 5, y: 4.0 }; # expected integral variable, found
+}
+
+
+
+

Generic 적용해보기 2 - 후

+
struct Point<T, U> {
+    x: T,
+    y: U, # 다른 타입을 가질수 있게 정의됨
+}
+
+fn main() {
+    let both_integer = Point { x: 5, y: 10 };
+    let both_float = Point { x: 1.0, y: 4.0 };
+    let integer_and_float = Point { x: 5, y: 4.0 };
+}
+
+
+
+

Generic 적용해보기 3 (함수)

+
struct Point<T> {
+    x: T,
+    y: T,
+}
+
+impl<T> Point<T> {
+    fn x(&self) -> &T {
+        &self.x
+    }
+}
+
+fn main() {
+    let p = Point { x: 5, y: 10 };
+
+    println!("p.x = {}", p.x());
+}
+
+
+
+

Generic 적용해보기 4 (mixup)

+
struct Point<X1, Y1> {
+    x: X1,
+    y: Y1,
+}
+
+impl<X1, Y1> Point<X1, Y1> {
+
+    # impl에 선언한 것과 다른 타입 parameter를 받는 함수
+    fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
+        Point {
+            x: self.x,
+            y: other.y, # mixup
+        }
+    }
+}
+
+fn main() {
+    let p1 = Point { x: 5, y: 10.4 };
+    let p2 = Point { x: "Hello", y: 'c' }; # 다른 타입
+
+    let p3 = p1.mixup(p2);
+
+    println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
+}
+
+
+
+

Generic 코드 성능

+
    +
  • 런타임 비용은 없음
  • +
  • 컴파일 타임에 monomorphization를 통해 Generic을 명시적인 타입으로 치환함
  • +
+
# 컴파일 전
+let integer = Some(5);
+let float = Some(5.0);
+
+# 컴파일 후
+enum Option_i32 {
+    Some(i32),
+    None,
+}
+enum Option_f64 {
+    Some(f64),
+    None,
+}
+
+fn main() {
+    let integer = Option_i32::Some(5);
+    let float = Option_f64::Some(5.0);
+}
+
+
+
+

Traits: Defining Shared Behavior

+

기본 문법

+
pub trait Summary {
+    fn summarize(&self) -> String;
+}
+
+
+
+

Implementing a Trait on a Type

+
    +
  • 일반 함수를 구현할때와 비슷하게 impl 키워드를 사용함
  • +
  • 뒤에 for 키워드가 따라온다는게 차이점
  • +
+
pub struct NewsArticle {
+    pub headline: String,
+    pub location: String,
+    pub author: String,
+    pub content: String,
+}
+
+impl Summary for NewsArticle {
+    fn summarize(&self) -> String {
+        format!("{}, by {} ({})", self.headline, self.author, self.location)
+    }
+}
+
+
+
+

Default Implementations

+
pub trait Summary {
+    fn summarize_author(&self) -> String;
+
+    fn summarize(&self) -> String {             # Default 구현에 있으면 추후 선언 없이 사용가능
+        format!("(Read more from {}...)", self.summarize_author())
+    }
+}
+
+impl Summary for Tweet {
+    fn summarize_author(&self) -> String {      # Overriding 가능
+        format!("@{}", self.username)
+    }
+}
+
+let tweet = Tweet {
+    username: String::from("horse_ebooks"),
+    content: String::from(
+        "of course, as you probably already know, people",
+    ),
+    reply: false,
+    retweet: false,
+};
+
+println!("1 new tweet: {}", tweet.summarize()); # 여기 주목
+
+
+
+

Traits as Parameters

+
    +
  • 인터페이스처럼 사용 가능
  • +
+
pub fn notify(item: &impl Summary) {
+    println!("Breaking news! {}", item.summarize());
+}
+
+
+
+

Trait Bound Syntax

+
    +
  • Generic을 활용해 특성 범위를 명시
  • +
+
pub fn notify<T: Summary>(item: &T) {
+    println!("Breaking news! {}", item.summarize());
+}
+
+
    +
  • +를 활용한 명시
  • +
+
pub fn notify(item: &(impl Summary + Display)) {
+# 또는
+pub fn notify<T: Summary + Display>(item: &T) {
+
+
+
+

Trait Bound Syntax

+
    +
  • Generic을 활용해 특성 범위를 명시
  • +
+
pub fn notify<T: Summary>(item: &T) {
+    println!("Breaking news! {}", item.summarize());
+}
+
+
    +
  • +를 활용한 명시
  • +
+
pub fn notify(item: &(impl Summary + Display)) {
+# 또는
+pub fn notify<T: Summary + Display>(item: &T) {
+
+
+
+

Clearer Trait Bounds with where Clauses

+
    +
  • 가독성 개선을 위해 where절을 쓸 수 있음
  • +
+
fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
+fn some_function<T, U>(t: &T, u: &U) -> i32
+where
+    T: Display + Clone,
+    U: Clone + Debug,
+{
+
+
+
+

Using Trait Bounds to Conditionally Implement Methods

+
use std::fmt::Display;
+
+struct Pair<T> {
+    x: T,
+    y: T,
+}
+
+impl<T> Pair<T> {
+    fn new(x: T, y: T) -> Self {
+        Self { x, y }
+    }
+}
+
+impl<T: Display + PartialOrd> Pair<T> {
+    fn cmp_display(&self) {
+        if self.x >= self.y {
+            println!("The largest member is x = {}", self.x);
+        } else {
+            println!("The largest member is y = {}", self.y);
+        }
+    }
+}
+
+
+
+
\ No newline at end of file diff --git a/ch11.html b/ch11.html new file mode 100644 index 0000000..f8e27e1 --- /dev/null +++ b/ch11.html @@ -0,0 +1,102 @@ +Rust Study
+

How to Write Tests

+
    +
  • Rust의 테스트 코드는 #[test] 주석이 달린 함수 +
      +
    • 함수를 테스트 함수로 바꾸려면 함수 선언 전에 #[test] 주석을 추가하면 됨
    • +
    +
  • +
  • #[cfg(test)]를 모듈 선언 전에 추가하면 cargo build에서 제외됨
  • +
+
#[cfg(test)]
+mod tests {
+    #[test]
+    fn it_works() {
+        let result = 2 + 2;
+        assert_eq!(result, 4);
+    }
+}
+
+
+
+

Assert

+
    +
  • assert!는 boolean 결과를 검증하기 위해 사용
  • +
+
assert!(larger.can_hold(&smaller));
+
+
    +
  • assert_eq!는 두 결과가 같은지 검증
  • +
+
assert_eq!(4, add_two(2));
+
+
    +
  • format
  • +
+
assert!(
+    result.contains("Carol"),
+    "Greeting did not contain name, value was `{}`",
+    result
+);
+
+
+
+

Panic

+
    +
  • should_panic은 panic 발생을 검증
  • +
+
#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    #[should_panic]
+    fn greater_than_100() {
+        Guess::new(200);
+    }
+
+    #[test]
+    #[should_panic(expected = "less than or equal to 100")]
+    fn greater_than_100() {
+        Guess::new(200);
+    }
+}
+
+
+
+

Testing Private Functions

+
pub fn add_two(a: i32) -> i32 {
+    internal_adder(a, 2)
+}
+
+fn internal_adder(a: i32, b: i32) -> i32 {
+    a + b
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*; # 이 트릭(?)을 통해 private 함수에 접근
+
+    #[test]
+    fn internal() {
+        assert_eq!(4, internal_adder(2, 2));
+    }
+}
+
+
+
\ No newline at end of file diff --git a/ch7.html b/ch7.html new file mode 100644 index 0000000..d08c3af --- /dev/null +++ b/ch7.html @@ -0,0 +1,267 @@ +Rust Study
+

Module System 구성요소

+
    +
  • Packages: Crates 빌드, 테스트, 공유를 위한 기능
  • +
  • Crates: 라이브러리 또는 실행파일의 트리
  • +
  • Modules and use: organization, scope, and privacy of paths 제어
  • +
  • Paths:struct, function, or module 네이밍 방법
  • +
+
+
+

Crate

+
    +
  • Binary Crate (main 있음)
  • +
  • Library Crate (main 없음)
  • +
  • Cargo.toml에 진입점 명시하지 않음 +
      +
    • src/main.rs 또는 src/lib.rs 존재 여부로 Binary/Library 여부 판단
    • +
    +
  • +
+
+
+

Module 동작 방식

+
    +
  • Crate Root(src/main.rs 또는 src/lib.rs)로 진입
  • +
  • Crate Root에 모듈 선언 (mod garden;)
  • +
  • 모듈(ex. garden)에 하위 모듈 선언 가능 (mod vegetables;)
  • +
  • 코드 경로 : crate::garden::vegetables::Asparagus
  • +
  • Privacy 설정 pub mod vs mod
  • +
  • Use 키워드 use crate::garden::vegetables::Asparagus 이후엔 Asparagus로 호출
  • +
+
backyard
+├── Cargo.lock
+├── Cargo.toml
+└── src
+    ├── garden
+    │   └── vegetables.rs
+    ├── garden.rs
+    └── main.rs
+
+
+
+

Module 동작 방식

+
use crate::garden::vegetables::Asparagus;
+
+pub mod garden; # 컴파일러에게 garden 모듈에서 찾은 코드를 포함하도록 지시
+
+fn main() {
+    let plant = Asparagus {};
+    println!("I'm growing {:?}!", plant);
+}
+
+
+
+

Crates

+
    +
  • 모듈을 활용해 코드 그룹핑 가능
  • +
+
mod front_of_house {
+    mod hosting {
+        fn add_to_waitlist() {}
+
+        fn seat_at_table() {}
+    }
+
+    mod serving {
+        fn take_order() {}
+
+        fn serve_order() {}
+
+        fn take_payment() {}
+    }
+}
+
+
+
+

Module Tree

+
crate
+ └── front_of_house
+     ├── hosting
+     │   ├── add_to_waitlist
+     │   └── seat_at_table
+     └── serving
+         ├── take_order
+         ├── serve_order
+         └── take_payment
+
+
+
+

Module Tree Referencing

+
    +
  • 절대경로는 crate 키워드로 시작
  • +
  • 상대경로는 self/super과 같은 모듈 식별자 사용 가능
  • +
+
mod front_of_house {
+    mod hosting {
+        fn add_to_waitlist() {}
+    }
+}
+
+pub fn eat_at_restaurant() {
+    // Absolute path
+    crate::front_of_house::hosting::add_to_waitlist();
+
+    // Relative path
+    front_of_house::hosting::add_to_waitlist();
+}
+
+
    +
  • 위 코드는 컴파일 에러 남
  • +
+
+
+

Exposing Paths with the pub Keyword

+
mod front_of_house {
+    pub mod hosting {   # 여기에 pub 키워드 추가
+        pub fn add_to_waitlist() {} # 여기도 pub 키워드 추가
+    }
+}
+
+pub fn eat_at_restaurant() {
+    // Absolute path
+    crate::front_of_house::hosting::add_to_waitlist();
+
+    // Relative path
+    front_of_house::hosting::add_to_waitlist();
+}
+
+
+
+

Making Structs and Enums Public

+
mod back_of_house {
+    pub struct Breakfast {
+        // 필드별로 공개 여부를 설정 가능
+        pub toast: String,
+        seasonal_fruit: String,
+    }
+
+    impl Breakfast {
+        pub fn summer(toast: &str) -> Breakfast {
+            Breakfast {
+                toast: String::from(toast),
+                seasonal_fruit: String::from("peaches"),
+            }
+        }
+    }
+}
+
+pub fn eat_at_restaurant() {
+    let mut meal = back_of_house::Breakfast::summer("Rye");
+    meal.toast = String::from("Wheat");
+    println!("I'd like {} toast please", meal.toast);
+
+    // 아래 코드는 작동 안됨
+    // meal.seasonal_fruit = String::from("blueberries");
+}
+
+
+
+

Shorten

+
mod front_of_house {
+    pub mod hosting {
+        pub fn add_to_waitlist() {}
+    }
+}
+
+use crate::front_of_house::hosting;
+
+mod customer {
+    pub fn eat_at_restaurant() {
+        hosting::add_to_waitlist();
+    }
+}
+
+// 또는
+
+use crate::front_of_house::hosting::add_to_waitlist;
+
+pub fn eat_at_restaurant() {
+    add_to_waitlist();
+}
+
+
+
+

use Scope

+
mod front_of_house {
+    pub mod hosting {
+        pub fn add_to_waitlist() {}
+    }
+}
+
+use crate::front_of_house::hosting;
+
+mod customer {
+    pub fn eat_at_restaurant() {
+        hosting::add_to_waitlist(); // 에러 발생
+    }
+}
+
+
+
+

Creating Idiomatic use Paths

+
    +
  • structs, enums 등을 가져올 때는 use전체 경로를 지정하는 것이 관용적
  • +
  • std::fmt::Resultuse std::io::Result 중 어느 것을 가져올지 모호한 상황이 종종 생김
  • +
+
use std::fmt;
+use std::io;
+
+fn function1() -> fmt::Result {
+    // --snip--
+}
+
+fn function2() -> io::Result<()> {
+    // --snip--
+}
+
+
+
+

Re-export

+
mod front_of_house {
+    pub mod hosting {
+        pub fn add_to_waitlist() {}
+    }
+}
+
+pub use crate::front_of_house::hosting; // 
+
+pub fn eat_at_restaurant() {
+    hosting::add_to_waitlist();
+}
+
+
+
+

Module 파일 분리

+
// src/lib.rs
+mod front_of_house;
+
+pub use crate::front_of_house::hosting;
+
+pub fn eat_at_restaurant() {
+    hosting::add_to_waitlist();
+}
+
+
// src/front_of_house.rs
+pub mod hosting {
+    pub fn add_to_waitlist() {}
+}
+
+
+
+
\ No newline at end of file diff --git a/ch8.html b/ch8.html new file mode 100644 index 0000000..8a1fae4 --- /dev/null +++ b/ch8.html @@ -0,0 +1,195 @@ +Rust Study
+

Common Collections

+
    +
  • Vector : 여러 값을 나란히 저장
  • +
  • String : char 컬렉션
  • +
  • Hash Map : key-value 형태로 저장
  • +
+
+
+

Vector

+
    +
  • +

    벡터는 0부터 시작하여 숫자로 인덱싱

    +
  • +
  • +

    Create

    +
  • +
+
let v: Vec<i32> = Vec::new();
+let v = vec![1, 2, 3];
+
+
    +
  • Update
  • +
+
let mut v = Vec::new();
+
+v.push(5);
+v.push(6);
+v.push(7);
+v.push(8);
+
+
+
+

Vector read

+
let v = vec![1, 2, 3, 4, 5];
+
+let third: &i32 = &v[2];
+println!("The third element is {third}");
+
+let third: Option<&i32> = v.get(2);
+match third {
+    Some(third) => println!("The third element is {third}"),
+    None => println!("There is no third element."),
+}
+
+
+
+

Vector safe read

+
    let v = vec![1, 2, 3, 4, 5];
+
+    let does_not_exist = &v[100];    // panic
+    let does_not_exist = v.get(100); // return None
+
+
+
+

Vector loop

+
    // 1
+    let v = vec![100, 32, 57];
+    for i in &v {
+        println!("{i}");
+    }
+
+    // 2
+    let mut v = vec![100, 32, 57];
+    for i in &mut v {
+        *i += 50;
+    }
+
+
+
+

Vector with multiple types

+
    +
  • Enum을 활용하여 여러 타입 사용 가능
  • +
+
    enum SpreadsheetCell {
+        Int(i32),
+        Float(f64),
+        Text(String),
+    }
+
+    let row = vec![
+        SpreadsheetCell::Int(3),
+        SpreadsheetCell::Text(String::from("blue")),
+        SpreadsheetCell::Float(10.12),
+    ];
+
+
+
+

Dropping a Vector Drops Its Elements

+
    {
+        let v = vec![1, 2, 3, 4];
+
+        // do stuff with v
+    } // <- v goes out of scope and is freed here
+
+
+
+

String

+
let mut s = String::new();
+
+
+
+

Update a String

+
let s1 = String::from("Hello, ");
+let s2 = String::from("world!");
+let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
+
+
+
+

Hash map

+
    +
  • 새 Hash map 생성
  • +
+
use std::collections::HashMap;
+
+let mut scores = HashMap::new();
+
+scores.insert(String::from("Blue"), 10);
+scores.insert(String::from("Yellow"), 50);
+
+
+
+

Hash map read

+
let team_name = String::from("Blue");
+let score = scores.get(&team_name).copied().unwrap_or(0);
+// loop
+for (key, value) in &scores {
+    println!("{key}: {value}");
+}
+
+
+
+

Hash map 소유권

+
    +
  • Hash map에 값을 넣으면 소유권이 이동됨 (단, 참조를 넣으면 이동되지 않음)
  • +
+
use std::collections::HashMap;
+
+let field_name = String::from("Favorite color");
+let field_value = String::from("Blue");
+
+let mut map = HashMap::new();
+map.insert(field_name, field_value);
+// field_name and field_value are invalid at this point, try using them and
+// see what compiler error you get!
+
+
+
+

Hash map 업데이트

+
    use std::collections::HashMap;
+
+    let mut scores = HashMap::new();
+    scores.insert(String::from("Blue"), 10);
+
+    scores.entry(String::from("Yellow")).or_insert(50);
+    scores.entry(String::from("Blue")).or_insert(50); // 덮어써짐
+
+    println!("{:?}", scores);
+
+
+
+

Hash map 업데이트2

+
    +
  • 이전 값 기반 업데이트
  • +
+
    use std::collections::HashMap;
+
+    let text = "hello world wonderful world";
+
+    let mut map = HashMap::new();
+
+    for word in text.split_whitespace() {
+        let count = map.entry(word).or_insert(0);
+        *count += 1;
+    }
+
+    println!("{:?}", map);
+
+
+
\ No newline at end of file diff --git a/ch9.html b/ch9.html new file mode 100644 index 0000000..0c08c7d --- /dev/null +++ b/ch9.html @@ -0,0 +1,52 @@ +Rust Study
+

Unrecoverable Error

+
    +
  • 복구할 수 없는 오류에 대해선 panic! 키워드로 패닉 발생 가능
  • +
  • panic이 발생하면 기본적으론 스택을 따라가며 자원을 해제하는 unwinding이 발생하지만, 때에 따라 abort로 설정도 가능
  • +
+
# Cargo.toml
+[profile.release]
+panic = 'abort'
+
+
+
+

Recoverable Error

+
    +
  • 복구 가능한 오류에 대해선 Enum으로 유형 정의
  • +
+
enum Result<T, E> {
+    Ok(T),
+    Err(E),
+}
+
+
+
+

Recoverable Error

+
use std::fs::File;
+
+fn main() {
+    let greeting_file_result = File::open("hello.txt");
+
+    let greeting_file = match greeting_file_result {
+        Ok(file) => file,
+        Err(error) => panic!("Problem opening the file: {:?}", error),
+    };
+}
+
+
+
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..0006429 --- /dev/null +++ b/index.html @@ -0,0 +1,24 @@ +Rust Study
+

Rust Slides

+

Chapter7. Packages, Crates, and Modules

+

Chapter8. Common Collections

+

Chapter9. Error Handling

+

Chapter10. Generic Types, Traits, and Lifetimes

+

Chapter11. Writing Automated Tests

+
+
\ No newline at end of file