๊ด€๋ฆฌ ๋ฉ”๋‰ด

IT’s Portfolio

[Rust] Start Rust (Day 19) - Generic Types, Traits, and Lifetimes ๋ณธ๋ฌธ

Development Study/Rust

[Rust] Start Rust (Day 19) - Generic Types, Traits, and Lifetimes

f1r3_r41n 2023. 7. 1. 14:37
728x90
๋ฐ˜์‘ํ˜•

๐Ÿฆ€ Rust Day 19

๐Ÿณ๏ธ Generic Types, Traits, and Lifetimes

  • ๋Ÿฌ์ŠคํŠธ์˜ ์ œ๋„ค๋ฆญ(Generic)์€ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…(concrete type)์ด๋‚˜ ๋‹ค๋ฅธ ์†์„ฑ์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”์ƒํ™”๋œ ํƒ€์ž…์„ ํ™œ์šฉํ•จ
  • ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ๋Œ€์‹  ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Œ
    • Option<T>, Vec<T>, HashMap<K, V>, Result<T, E> ๋ชจ๋‘ ์ œ๋„ค๋ฆญ ํƒ€์ž…์ž„
  • ์ˆ˜๋ช…์€ ์ œ๋„ค๋ฆญ์˜ ์ผ์ข…์œผ๋กœ ์ฐธ์กฐ๊ฐ€ ์„œ๋กœ ์–ด๋–ป๊ฒŒ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ์— ์ œ๊ณตํ•จ

1๏ธโƒฃ ํ•จ์ˆ˜๋กœ๋ถ€ํ„ฐ ์ค‘๋ณต ์ œ๊ฑฐํ•˜๊ธฐ

fn main() {
    let num_list_1 = vec![34, 56, 77, 25, 100, 54];
    let num_list_2 = vec![102, 24, 6000, 89, 54, 2, 43, 8];

    let mut max = num_list_1[0];

    for number in num_list_1 {
        if number > max {
            max = number;
        }
    }

    println!("num_list_1's max: {max}");

    max = num_list_2[0];

    for number in num_list_2 {
        if number > max {
            max = number;
        }
    }

    println!("num_list_2's max: {max}");
}
// Result
// num_list_1's max: 100
// num_list_2's max: 6000 
  • ๋‘ ๊ฐœ์˜ ์ˆซ์ž ๋ฆฌ์ŠคํŠธ์—์„œ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋Š” ์ฝ”๋“œ
  • ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์Œ
fn get_max(num_list: &[i32]) -> i32 {
    let mut max = num_list[0];

    for number in num_list {
        if number > &max {
            max = *number;
        }
    }

    max
}

fn main() {
    let num_list_1 = vec![34, 56, 77, 25, 100, 54];
    let num_list_2 = vec![102, 24, 6000, 89, 54, 2, 43, 8];

    println!("num_list_1's max: {}", get_max(&num_list_1));
    println!("num_list_2's max: {}", get_max(&num_list_2));
}
// Result
// num_list_1's max: 100
// num_list_2's max: 6000
  • ์ค‘๋ณต๋œ ๋ถ€๋ถ„์„ ํ•จ์ˆ˜ํ™”์‹œํ‚จ ์ฝ”๋“œ
  • ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” i32 ๊ฐ’์˜ ์Šฌ๋ผ์ด์Šค๋ผ๋ฉด ์–ด๋–ค ํƒ€์ž…์ด๋“  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ

2๏ธโƒฃ ์ œ๋„ค๋ฆญ ๋ฐ์ดํ„ฐ ํƒ€์ž…

  • ์ œ๋„ค๋ฆญ์€ ์—ฌ๋Ÿฌ ๊ตฌ์ฒดํ™”๋œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋‚˜ ๊ตฌ์กฐ์ฒด ๊ฐ™์€ ์•„์ดํ…œ์„ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•จ

๐Ÿค” ํ•จ์ˆ˜ ์ •์˜์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

fn get_i32_max(num_list: &[i32]) -> i32 {
    let mut max = num_list[0];

    for number in num_list {
        if number > &max {
            max = *number;
        }
    }

    max
}

fn get_char_max(char_list: &[char]) -> char {
    let mut max = char_list[0];

    for char in char_list {
        if char > &max {
            max = *char;
        }
    }

    max
}

fn main() {
    let num_list = vec![34, 56, 77, 25, 100, 54];
    let char_list = vec!['y', 'm', 'a', 'q'];

    println!("num_list's max: {}", get_i32_max(&num_list));
    println!("char_list's max: {}", get_char_max(&char_list));
}
// Result
// num_list's max: 100
// char_list's max: y
  • ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฆฌํ„ด ํƒ€์ž…๋งŒ ๋‹ค๋ฅด๊ณ  ๋™์ž‘์€ ๊ฐ™์€ ๋‘ ์ค‘๋ณต ํ•จ์ˆ˜ ์ฝ”๋“œ
  • ๋‘ ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์€ ์™„์ „ํžˆ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์ด์šฉํ•ด ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋กœ ์ •์˜ํ•ด์•ผ ํ•จ
  • ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์— ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•  ์‹œ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์„ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— ์„ ์–ธํ•ด์„œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ทธ ์ด๋ฆ„์˜ ์˜๋ฏธ๋ฅผ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ
fn get_max<T>(list: &[T]) -> T {
  • ์ œ๋„ค๋ฆญ get_max ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์‹œ ํ•จ์ˆ˜์˜ ์ด๋ฆ„๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก ์‚ฌ์ด์˜ ๊บพ์‡ ๊ด„ํ˜ธ(<>) ์— ํƒ€์ž… ์ด๋ฆ„์„ ๋ช…์‹œํ•˜๋ฉด ๋จ
  • get_max ํ•จ์ˆ˜ ์ •์˜
    • ํ•จ์ˆ˜ get_max ๋Š” ์–ด๋–ค ํƒ€์ž… T ๋ฅผ ์ผ๋ฐ˜ํ™”ํ•œ ํ•จ์ˆ˜
  • ์œ„์˜ ์ œ๋„ค๋ฆญ get_max ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•จ
    • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€์—์„œ๋Š” std::cmp::PartialOrd ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์–ธ๊ธ‰ํ•จ
    • get_max ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์ด ๋ชจ๋“  ํƒ€์ž… T ์— ๋Œ€ํ•ด ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•จ
    • ํ•จ์ˆ˜ ๋ณธ๋ฌธ์—์„œ ํƒ€์ž… T ์˜ ๊ฐ’์„ ๋น„๊ตํ•˜๋ฏ€๋กœ ์ด ๊ฐ’์€ ๋ฐ˜๋“œ์‹œ ์ •๋ ฌ ๊ฐ€๋Šฅํ•ด์•ผ ํ•จ

๐Ÿค” ๊ตฌ์กฐ์ฒด ์ •์˜์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

struct Point<T> {
    x: T,
    y: T,
}
  • x์™€ y ์ขŒํ‘œ์˜ ๊ฐ’์„ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” Point<T> ๊ตฌ์กฐ์ฒด ์„ ์–ธ
  • ํ•˜๋‚˜์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž…๋งŒ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํƒ€์ž… T ๋ฅผ ์ผ๋ฐ˜ํ™”ํ•œ ๊ตฌ์กฐ์ฒด
  • ํ•„๋“œ์˜ ๊ฐ’์€ ๋ชจ๋‘ ๊ฐ™์€ ํƒ€์ž…์ด์–ด์•ผ ํ•จ
struct Point<T, U> {
    x: T,
    y: U,
}
  • ๋‹ค์ค‘ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„๋“œ์˜ ๊ฐ’๋“ค์„ ๊ฐ๊ฐ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ์ œ๋„ค๋ฆญ ๋ฐ์ดํ„ฐ ํƒ€์ž…์œผ๋กœ ์„ ์–ธ ๊ฐ€๋Šฅ
  • ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด ๋„ˆ๋ฌด ๋งŽ์ด ํ•„์š”ํ•ด์ง„๋‹ค๋Š” ๊ฒƒ์€ ์ฝ”๋“œ๋ฅผ ๋” ์ž‘์€ ๋ถ€๋ถ„์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋œปํ•จ

๐Ÿค” ์—ด๊ฑฐ์ž ์ •์˜์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

enum Option<T> {
    Some(T),
    None,
}
  • Option<T> ์—ด๊ฑฐ์ž ์ •์˜
    • ํƒ€์ž… T ๋ฅผ ์ผ๋ฐ˜ํ™”ํ•œ ์—ด๊ฑฐ์ž
    • Option<T> ์—ด๊ฑฐ์ž๋ฅผ ์ด์šฉํ•˜๋ฉด ์„ ํƒ์ ์ธ ๊ฐ’์˜ ๊ฐœ๋… ์ถ”์ƒํ™” ๊ฐ€๋Šฅ
    • Option<T> ๋Š” ์ œ๋„ค๋ฆญ ์—ด๊ฑฐ์ž์ด๋ฏ€๋กœ ์„ ํƒ์ ์ธ ๊ฐ’์˜ ํƒ€์ž…๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ถ”์ƒํ™”๋œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
enum Result<T, E> {
    Ok(T),
    Err(E),
}
  • Result<T, E> ์—ด๊ฑฐ์ž ์ •์˜
    • ๋‘ ๊ฐœ์˜ ํƒ€์ž… T ์™€ E ๋ฅผ ์ผ๋ฐ˜ํ™”ํ•œ ํƒ€์ž…

๐Ÿค” ๋ฉ”์„œ๋“œ ์ •์˜์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn get_x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let p = Point{
        x: 2,
        y: 5,
    };

    println!("{}", p.get_x());
}
// Result
// 2
  • Point<T> ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ x์˜ ๊ฐ’์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ •์˜
  • impl keyword ๋‹ค์Œ์— ํƒ€์ž… T ๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋Ÿฌ์ŠคํŠธ๋Š” Point ๊ตฌ์กฐ์ฒด์˜ ๊บพ์‡  ๊ด„ํ˜ธ ์•ˆ์— ์ง€์ •๋œ ํƒ€์ž…์ด ๊ตฌ์ฒดํ™”๋œ ํƒ€์ž…์ด ์•„๋‹Œ ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋ผ๋Š” ์ ์„ ์ธ์‹ํ•จ
struct Point<T> {
    x: T,
    y: T,
}

impl Point<f64> {
    fn dis_from_ori(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

fn main() {
    let p = Point{
        x: 3.4,
        y: 8.9,
    };

    println!("{}", p.dis_from_ori());
}
// Result
// 9.527329111561121
  • ํŠน์ • ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค์—๋งŒ ์ ์šฉํ•  ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
  • Point<f64> ํƒ€์ž…์€ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ Point<T> ์ธ์Šคํ„ด์Šค๋Š” ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ
  • dis_from_ori ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ์ค€ ์ขŒํ‘œ(0.0, 0.0)์œผ๋กœ๋ถ€ํ„ฐ ์ง€์ •๋œ ์ขŒํ‘œ๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋จผ์ง€ ๊ณ„์‚ฐํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž„
    • ์ˆ˜ํ•™ ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋ถ€๋™ ์†Œ์ˆ˜์  ํƒ€์ž…์—๋งŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ์ž„
#[derive(Debug)]
struct Point<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point<T, U> {
    fn struct_mix<V, W> (self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}

fn main() {
    let p1 = Point { x: 4.5, y: 7.7 };
    let p2 = Point { x: "Hello", y: 'r'};

    println!("{:?}", p1.struct_mix(p2));
}
// Result
// Point { x: 4.5, y: 'r' }
  • ๊ตฌ์กฐ์ฒด์˜ ์ •์˜์™€๋Š” ๋‹ค๋ฅธ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
  • impl ๋ธ”๋ก๊ณผ ๋ฉ”์„œ๋“œ ์ •์˜์— ๊ฐ๊ฐ ๋‹ค๋ฅธ ์ œ๋„ค๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
    • ์ œ๋„ค๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜ T ์™€ U ๋Š” ๊ตฌ์กฐ์ฒด์˜ ์ •์˜์— ๋”ฐ๋ผ impl ๋ธ”๋ก ๋‹ค์Œ์— ์ง€์ •๋˜์–ด ์žˆ์Œ
    • ์ œ๋„ค๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜ V ์™€ W ๋Š” ๋ฉ”์„œ๋“œ์—๋งŒ ๊ด€๋ จ์ด ์žˆ์œผ๋ฏ€๋กœ ๋ฉ”์„œ๋“œ์— ์ •์˜ํ•จ
  • ํ•ด๋‹น ์ฝ”๋“œ์—์„œ p1๊ณผ p2๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ์— ์†Œ์œ ๊ถŒ์ด ๋„˜์–ด๊ฐ€๋ฏ€๋กœ ๋ฉ”์„œ๋“œ ์ž‘์—…์ด ๋๋‚œ ํ›„์—๋Š” ์œ ํšจํ•˜์ง€ ์•Š์Œ

๐Ÿค” ์ œ๋„ค๋ฆญ์˜ ์„ฑ๋Šฅ

  • ๋Ÿฌ์ŠคํŠธ๊ฐ€ ์ œ๋„ค๋ฆญ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ด์„œ ๊ตฌ์ฒดํ™”๋œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€์ง€ ์•Š์Œ
    • ์ปดํŒŒ์ผ ์‹œ์ ์— ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋‹จ์ผํ™”(Monomorphzation) ํ•˜๊ธฐ ๋•Œ๋ฌธ
    • ๋‹จ์ผํ™” : ์ปดํŒŒ์ผ ์‹œ์ ์— ์ œ๋„ค๋ฆญ ์ฝ”๋“œ๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์ฒดํ™”๋œ ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •
    • ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ œ๋„ค๋ฆญ ์ฝ”๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๋ถ€๋ถ„์„ ๋ชจ๋‘ ์ฐพ์•„ ์ œ๋„ค๋ฆญ ์ฝ”๋“œ์˜ ํ˜ธ์ถœ์— ์‚ฌ์šฉ๋œ ๊ตฌ์ฒดํ™”๋œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•จ
fn main() {
    let integer = Some(5);
    let float = Some(8.9);
}
  • ์šฐ๋ฆฌ๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ
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(8.9);
}
  • ๋‹จ์ผํ™”๋œ ๋ฒ„์ „์˜ ์ฝ”๋“œ
  • ์ œ๋„ค๋ฆญ Option<T> ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ƒ์„ฑํ•œ ํŠน์ • ์ •์˜๋กœ ๊ต์ฒด๋จ

3๏ธโƒฃ ํŠธ๋ ˆ์ดํŠธ: ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ํ–‰์œ„๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•

  • ํŠธ๋ ˆ์ดํŠธ(trait) : ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ํŠน์ • ํƒ€์ž…์ด ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์–ด๋–ค ํƒ€์ž…๊ณผ ์ด ๊ธฐ๋Šฅ์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋ฐฉ๋ฒ•
    • ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ํ–‰์œ„๋ฅผ ์ถ”์ƒํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ ์ธํ„ฐํŽ˜์ด์Šค(interface) ๊ธฐ๋Šฅ๊ณผ ์œ ์‚ฌํ•จ

๐Ÿค” ํŠธ๋ ˆ์ดํŠธ ์„ ์–ธํ•˜๊ธฐ

  • ํŠธ๋ ˆ์ดํŠธ ์ •์˜๋Š” ์–ด๋–ค ๋ชฉ์ ์„ ์ด๋ฃจ๋Š” ๋ฐ ํ•„์š”ํ•œ ์ผ๋ จ์˜ ํ–‰์œ„๋ฅผ ์ •์˜ํ•˜๊ณ  ์—ฌ๋Ÿฌ ํƒ€์ž…์— ์ ์šฉํ•  ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•
  • NewArticle ๊ตฌ์กฐ์ฒด๋Š” story ํ•„๋“œ์— ํŠน์ • ์ง€์—ญ์˜ ๋‰ด์Šค ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๋ฉฐ, Tweet ๊ตฌ์กฐ์ฒด๋Š” ์ตœ๋Œ€ 280๊ธ€์ž์˜ ํ…์ŠคํŠธ์™€ ํ•ด๋‹น ํŠธ์œ—์ด ์ƒˆ ํŠธ์œ—์ธ์ง€, ๋ฆฌํŠธ์œ—๋œ ํŠธ์œ—์ธ์ง€, ์•„๋‹ˆ๋ฉด ๋‹ค๋ฅธ ํŠธ์œ—์˜ ๋Œ“๊ธ€์ธ์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จ
  • ํ•ด๋‹น ๊ตฌ์กฐ์ฒด๋“ค์˜ ์ธ์Šคํ„ด์Šค์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์•ฝํ•ด์„œ ๋ณด์—ฌ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„
// src/lib.rs
pub trait Summary {
    fn summarize(&self) -> String;
}
  • trait keyword๋ฅผ ์ด์šฉํ•œ ํŠธ๋ ˆ์ดํŠธ ์ •์˜์™€ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์ •์˜
  • ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋Š” ๊ฐ๊ฐ ๋ณ„๊ฐœ์˜ ์ค„์— ์„ ์–ธํ•˜๋ฉฐ ๊ฐ ์ค„์€ ์„ธ๋ฏธ์ฝœ๋ก ์œผ๋กœ ๋๋‚˜์•ผ ํ•จ
    • ํ•ด๋‹น ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ ํƒ€์ž…์€ ๋ฐ˜๋“œ์‹œ ์ด ๋ฉ”์„œ๋“œ์˜ ๋ณธ๋ฌธ์— ์ž์‹ ์˜ ํ–‰์œ„๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

๐Ÿค” ํƒ€์ž…์— ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ํ•˜๊ธฐ

// src/lib.rs
pub trait Summary {
    fn summarize(&self) -> String;
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!(
            "{}, by {}, {}", 
            self.headline, self.author, self.location
        )
    }
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!(
            "{}: {}", 
            self.username, self.content
        )
    }
}
  • Summary ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์ด์šฉํ•ด ํ•„์š”ํ•œ ํ–‰์œ„ ์ •์˜
  • ํƒ€์ž…์— ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋ณดํ†ต์˜ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„๊ณผ ์œ ์‚ฌํ•จ
  • impl ๋ธ”๋ก์—์„œ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ด๋‹น ํƒ€์ž…์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ํŠน์ • ๋™์ž‘์„ ๊ตฌํ˜„
// src/main.rs
use trait_example::*;

fn main() {
    let tweet = Tweet {
        username: String::from("f1r3_r41n"),
        content: String::from("ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ๋‹จ๊ณ„ ing.."),
        reply: false,
        retweet: false,
    };

    println!("์ƒˆ ํŠธ์œ— 1๊ฐœ: {}", tweet.summarize());
}
// Result
// ์ƒˆ ํŠธ์œ— 1๊ฐœ: f1r3_r41n: ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ๋‹จ๊ณ„ ing..
  • NewsArticle ํƒ€์ž…, Tweet ํƒ€์ž…, Summary ํŠธ๋ ˆ์ดํŠธ๋Š” lib.rs ํŒŒ์ผ ํ•˜๋‚˜์— ๋ชจ๋‘ ์ •์˜ํ–ˆ์œผ๋ฏ€๋กœ ๋ชจ๋‘ ๊ฐ™์€ ๋ฒ”์œ„์— ์กด์žฌํ•จ
  • ๋งŒ์•ฝ ๋ณ„๊ฐœ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ”์œ„์— ์ •์˜๋œ ๊ตฌ์กฐ์ฒด์— Summary ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•จ
    • ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ๋ช…์‹œํ•˜์—ฌ ์ž์‹ ์ด ์ •์˜ํ•œ ํƒ€์ž…์— Summary ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„
    • ๋•Œ๋ฌธ์— ๊ณต๊ฐœ ํŠธ๋ ˆ์ดํŠธ๋กœ ์„ ์–ธํ•˜์˜€์Œ
  • ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ์‹œ ํ•œ ๊ฐ€์ง€ ์ œ์•ฝ
    • ํŠธ๋ ˆ์ดํŠธ๋‚˜ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ํƒ€์ž…์ด ํ˜„์žฌ ํฌ๋ ˆ์ดํŠธ์˜ ๋กœ์ปฌ ํƒ€์ž…์ด์–ด์•ผ ํ•จ
      • Display ๊ฐ™์€ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์ž์‹ ์˜ ํฌ๋ ˆ์ดํŠธ ์ผ๋ถ€์ธ Tweet ํƒ€์ž…์— ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” Tweet ํƒ€์ž…์ด ์ž์‹ ์˜ ํฌ๋ ˆ์ดํŠธ์˜ ๋กœ์ปฌ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ
      • Summary ํŠธ๋ ˆ์ดํŠธ๋Š” ์ž์‹ ์˜ ํฌ๋ ˆ์ดํŠธ์˜ ๋กœ์ปฌ ํƒ€์ž…์ด๋ฏ€๋กœ Vec<T> ํƒ€์ž…์— Summary ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
    • ์™ธ๋ถ€ ํƒ€์ž…์— ์™ธ๋ถ€ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†์Œ
      • Display ์™€ Vec<T> ๋Š” ๋ชจ๋‘ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ •์˜๋œ ํƒ€์ž…์ด๋ฉฐ ์ž์‹ ์˜ ํฌ๋ ˆ์ดํŠธ์˜ ๋กœ์ปฌ ํƒ€์ž…์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž์‹ ์˜ ํฌ๋ ˆ์ดํŠธ ์•ˆ์—์„œ Vec<T> ํƒ€์ž…์— Display ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†์Œ
    • ํ†ต์ผ์„ฑ(coherence) ํ˜น์€ ๊ณ ์•„ ๊ทœ์น™(orphan rule) ์ด๋ผ๊ณ  ์นญํ•จ

๐Ÿค” ๊ธฐ๋ณธ ๊ตฌํ˜„

  • ํŠธ๋ ˆ์ดํŠธ์— ์„ ์–ธ๋œ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ์š”๊ตฌํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ผ๋ถ€ ํ˜น์€ ์ „์ฒด ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ๊ตฌํ˜„ํ•ด ์ฃผ๋ฉด ํŠน์ • ํƒ€์ž…์— ๊ตฌํ˜„ํ•  ๋•Œ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Œ
// src/lib.rs
pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(๊ณ„์† ์ฝ๊ธฐ)")
    }
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for NewsArticle { }

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!(
            "{}: {}", 
            self.username, self.content
        )
    }
}
  • Summary ํŠธ๋ ˆ์ดํŠธ ์ •์˜ ๋ธ”๋ก์—์„œ summarize ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณต
  • NewsArticle ๊ตฌ์กฐ์ฒด์—์„œ summarize ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์žฌ์ •์˜ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ ๊ตฌํ˜„์ด ์ œ๊ณต๋จ
// src/main.rs
use trait_example::*;

fn main() {
    let article = NewsArticle {
        headline: String::from("headline"),
        location: String::from("korea"),
        author: String::from("f1r3_r41n"),
        content: String::from("text..."),
    };

    println!("์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ: {}", article.summarize());
}
// Result
// ์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ: (๊ณ„์† ์ฝ๊ธฐ)
  • Tweet ๊ตฌ์กฐ์ฒด์˜ summarize ๋ฉ”์„œ๋“œ๋Š” ์žฌ์ •์˜๋œ ๊ตฌํ˜„์ด ์ œ๊ณต๋จ
  • ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์žฌ์ •์˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ๋ฒ•์€ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ํŠธ๋ ˆ์ดํŠธ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฌธ๋ฒ•๊ณผ ๊ฐ™์Œ
// src/lib.rs
pub trait Summary {
    fn summarize_author(&self) -> String;
    fn summarize(&self) -> String {
        format!("{}๋‹˜์˜ ๊ธฐ์‚ฌ ๋” ์ฝ๊ธฐ", self.summarize_author())
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
}
  • ๊ธฐ๋ณธ ๊ตฌํ˜„์€ ๊ฐ™์€ ํŠธ๋ ˆ์ดํŠธ์˜ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋„ ํ˜ธ์ถœ ๊ฐ€๋Šฅ
    • ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์ง€ ์•Š์•„๋„ ๊ฐ€๋Šฅ
// src/main.rs
use trait_example::*;

fn main() {
    let tweet = Tweet {
        username: String::from("f1r3_r41n"),
        content: String::from("ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ๋‹จ๊ณ„ ing.."),
        reply: false,
        retweet: false,
    };

    println!("์ƒˆ ํŠธ์œ— 1๊ฐœ: {}", tweet.summarize());
}
// Result
// ์ƒˆ ํŠธ์œ— 1๊ฐœ: @f1r3_r41n๋‹˜์˜ ๊ธฐ์‚ฌ ๋” ์ฝ๊ธฐ
  • ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๋ฉด์„œ ๊ธฐ๋ณธ ๊ตฌํ˜„ ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜๋Š” ์—†์Œ

๐Ÿค” ํŠธ๋ ˆ์ดํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜

// src/lib.rs
pub trait Summary {
    fn summarize(&self) -> String;
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!(
            "{}, by {}, {}",
            self.headline, self.author, self.location
        )
    }
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!(
            "{}: {}",
            self.username, self.content
        )
    }
}

pub fn notify(item: impl Summary) {
    println!("์†๋ณด! {}", item.summarize());
}

// src/main.rs
use trait_example::*;

fn main() {
    let article = NewsArticle {
        headline: String::from("headline"),
        location: String::from("korea"),
        author: String::from("f1r3_r41n"),
        content: String::from("text..."),
    };

    println!("์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ: {}", article.summarize());
    notify(article);
}
// Result
// ์ƒˆ๋กœ์šด ๊ธฐ์‚ฌ: headline, by f1r3_r41n, korea
// ์†๋ณด! headline, by f1r3_r41n, korea
  • impl Trait ๋ฌธ๋ฒ• : ์ง€์ •๋œ ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ชจ๋“  ํƒ€์ž…์„ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ
    • ๋น„๊ต์  ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” ์ž˜ ๋™์ž‘
    • ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๋” ๊ธด ๋ฌธ๋ฒ•์„ ๊ฐ„๋‹จํžˆ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ํŽธ์˜ ์žฅ์น˜

(1) ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ๋ฌธ๋ฒ•

pub fn notify<T: Summary>(item: T) {
    println!("์†๋ณด! {}", item.summarize());
}
  • ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ๋ฌธ๋ฒ• : ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊บพ์‡ ๊ด„ํ˜ธ ์•ˆ์— ์ฝœ๋ก ์„ ์ด์šฉํ•ด ์ง€์ •
    • ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์ธ ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ : impl Trait ๋ฌธ๋ฒ•
    • ๊ฐ™์€ ํƒ€์ž…์ธ ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ ์–ธ : ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ๋ฌธ๋ฒ•

(2) + ๋ฌธ๋ฒ•์œผ๋กœ ์—ฌ๋Ÿฌ ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ์ •์˜ํ•˜๊ธฐ

pub fn notify(item: impl Summary + Display) {
  • impl Trait ๋ฌธ๋ฒ•
  • notify ํ•จ์ˆ˜์—์„œ item ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์— ์ถœ๋ ฅ ํ˜•์‹์„ ์ ์šฉํ•˜๋Š” ๋™์‹œ์— summarize ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•  ๋•Œ + ๋ฌธ๋ฒ•์œผ๋กœ ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ๋ช…์‹œ
pub fn notify<T: Summary + Display>(item: T) {
  • ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ๋ฌธ๋ฒ•

(3) where ์ ˆ์„ ์ด์šฉํ•ด ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ์ •๋ฆฌํ•˜๊ธฐ

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š” ํ•จ์ˆ˜์—๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก ์‚ฌ์ด์— ๋„ˆ๋ฌด ๋งŽ์€ ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ๋‚˜์—ดํ•˜๊ฒŒ ๋˜์–ด ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์ฝ๊ธฐ ์–ด๋ ค์›Œ์ง
fn function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {
  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„
fn function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone, U: Clone + Debug {
  • where ์ ˆ์„ ์ด์šฉํ•ด ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ •๋ฆฌํ•œ ์ฝ”๋“œ

๐Ÿค” ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ’ ๋ฆฌํ„ดํ•˜๊ธฐ

fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("f1r3_r41n"),
        content: String::from("ํŠธ๋ ˆ์ดํŠธ ๊ตฌํ˜„ ๋‹จ๊ณ„ ing.."),
        reply: false,
        retweet: false,
    }
}
  • ๋ฆฌํ„ด ํƒ€์ž…์— impl Summary ๋ฅผ ์ง€์ •ํ–ˆ๊ธฐ์— Summary ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์–ด๋–ค ํƒ€์ž…๋„ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ์Œ
  • ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๋Š” ์‹ค์ œ ๋ฆฌํ„ด ํƒ€์ž…์„ ์•Œ์ง€ ๋ชปํ•จ
  • impl Trait ๋ฌธ๋ฒ•์€ ํ•˜๋‚˜์˜ ํƒ€์ž…์„ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
    • ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ impl Trait ๋ฌธ๋ฒ•์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์ œ์•ฝ ๋•Œ๋ฌธ

๐Ÿค” ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ด์šฉํ•ด largest ํ•จ์ˆ˜ ์ž‘์„ฑํ•˜๊ธฐ

fn get_max<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut max = list[0];

    for &i in list.iter() {
        if i > max {
            max = i;
        }
    }

    max
}

fn main() {
    let num_list = vec![34, 56, 77, 25, 100, 54];
    let char_list = vec!['y', 'm', 'a', 'q'];

    println!("max: {}", get_max(&num_list));
    println!("max: {}", get_max(&char_list));
}
// Result
// max: 100
// max: y
  • > ์—ฐ์‚ฐ์ž๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ std::cmp::PartialOrd ํŠธ๋ ˆ์ดํŠธ์˜ ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ๋กœ ์ •์˜๋˜์–ด ์žˆ์Œ
    • T ํƒ€์ž…์— PartialOrd ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ง€์ •ํ•˜์—ฌ ํ•จ์ˆ˜๊ฐ€ ์‹ค์ œ๋กœ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์˜ ์Šฌ๋ผ์ด์Šค๋งŒ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ
  • ํฌ๊ธฐ๊ฐ€ ์ด๋ฏธ ์ •ํ•ด์ง„ ์Šค์นผ๋ผ ๊ฐ’์€ ์Šคํƒ์— ์ €์žฅ๋˜๋ฏ€๋กœ Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋‚˜ ์ œ๋„ค๋ฆญ ๋ณ€์ˆ˜์— Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š” ํƒ€์ž…์˜ ๊ฐ’์ด ์ „๋‹ฌ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์ƒ๊น€
    • T ํƒ€์ž…์— Copy ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ง€์ •ํ•˜์—ฌ Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํƒ€์ž…์— ๋Œ€ํ•ด์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ
  • Copy ๋Œ€์‹  Clone ํŠธ๋ ˆ์ดํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์งˆ ๋•Œ ์Šฌ๋ผ์ด์Šค์˜ ๊ฐ ๊ฐ’์„ ๋ณต์ œํ•จ
    • clone ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์€ String ์ฒ˜๋Ÿผ ํž™ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํƒ€์ž…์€ ๋” ๋งŽ์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋ฉฐ, ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์†๋„๊ฐ€ ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Œ
  • ์Šฌ๋ผ์ด์Šค์— ์ €์žฅ๋œ T ํƒ€์ž…์˜ ์ฐธ์กฐ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ
    • Clone ํ˜น์€ Copy ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ์„ ์–ธํ•  ํ•„์š” ์—†์œผ๋ฉฐ ํž™ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น๋„ ํ•„์š”ํ•˜์ง€ ์•Š์Œ

(1) ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ด์šฉํ•ด ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ

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!("๊ฐ€์žฅ ํฐ ๋ฉค๋ฒ„๋Š” x = {}", self.x);
        } else {
            println!("๊ฐ€์žฅ ํฐ ๋ฉค๋ฒ„๋Š” y = {}", self.y);
        }
    }
}

fn main() {
    let p = Pair::new(2, 4);
    p.cmp_display();
}
// Result
// ๊ฐ€์žฅ ํฐ ๋ฉค๋ฒ„๋Š” y = 4
  • ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” impl ๋ธ”๋ก์— ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„ ์‚ฌ์šฉ ์‹œ ํƒ€์ž…์ด ํŠน์ • ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ
impl<Display> ToString for T {
    // -- ์ƒ๋žต --
}

fn main() {
    let s = 3.to_string();
}
  • ๋ฎ๊ฐœ ๊ตฌํ˜„(blanket implementations) : ํƒ€์ž…์— ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๋ฅผ ๋งŒ์กฑํ•˜๋Š” ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ
    • ๋Ÿฌ์ŠคํŠธ์˜ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋งค์šฐ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์‚ฌ์šฉ
    • ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” Display ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํƒ€์ž…์—๋Š” ToString ํŠธ๋ ˆ์ดํŠธ๋„ ํ•จ๊ป˜ ๊ตฌํ˜„ํ•จ
      • ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฎ๊ฐœ ๊ตฌํ˜„ ๊ธฐ๋ฒ•์œผ๋กœ ์ธํ•ด Display ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ชจ๋“  ํƒ€์ž…์— ๋Œ€ํ•ด ToString ํŠธ๋ ˆ์ดํŠธ๊ฐ€ ์ •์˜ํ•œ to_string ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๊ฐ€๋Šฅ

4๏ธโƒฃ ์ˆ˜๋ช…์„ ์ด์šฉํ•ด ์ฐธ์กฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌํ•˜๊ธฐ

  • ์ˆ˜๋ช…(lifetimes) : ์ฐธ์กฐ๊ฐ€ ์œ ํšจํ•œ ๋ฒ”์œ„
    • ์•”๋ฌต์ ์ด๋ฉฐ, ํƒ€์ž…์ด ๋Œ€๋ถ€๋ถ„ ์ถ”๋ก (inferred) ์— ์˜ํ•ด ๊ฒฐ์ •๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ˆ˜๋ช… ์—ญ์‹œ ์ถ”๋ก ์„ ํ† ๋Œ€๋กœ ๋™์ž‘
    • ์ˆ˜๋ช…์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์„ ๋•Œ ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

๐Ÿค” ์ˆ˜๋ช…์„ ์ด์šฉํ•ด ์ฃฝ์€ ์ฐธ์กฐ์˜ ๋ฐœ์ƒ ๋ฐฉ์ง€ํ•˜๊ธฐ

fn main() {
    let r;
    {
        let x = 5;
        r = &x;
    }
    println!("r: {}", r);
}
// Result
// error[E0597]: `x` does not live long enough
  • ์ˆ˜๋ช…์˜ ์ฃผ์š” ๋ชฉ์ ์€ ์ฃฝ์€ ์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ
    • ์ฃฝ์€ ์ฐธ์กฐ: ํ”„๋กœ๊ทธ๋žจ์ด ์›๋ž˜ ์˜๋„ํ–ˆ๋˜ ๋ฐ์ดํ„ฐ์™€๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋  ๋•Œ๋ฅผ ๋œปํ•จ
  • ๋ณ€์ˆ˜ x๋Š” ์•ˆ์ชฝ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ์ˆœ๊ฐ„ ๋”๋Š” ์œ ํšจํ•˜์ง€ ์•Š๊ธฐ์— ์ˆ˜๋ช…์ด ์ถฉ๋ถ„์น˜ ์•Š๋‹ค๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ
  • ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋Œ€์—ฌ ๊ฒ€์‚ฌ๊ธฐ ๋ฅผ ํƒ‘์žฌํ•˜์—ฌ ์ฝ”๋“œ๊ฐ€ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š์€์ง€ ์•Œ ์ˆ˜ ์žˆ์Œ

๐Ÿค” ๋Œ€์—ฌ ๊ฒ€์‚ฌ๊ธฐ

  • ๋Œ€์—ฌ ๊ฒ€์‚ฌ๊ธฐ(borrow checker) : ๋Œ€์—ฌํ•œ ๊ฐ’์ด ํ˜„์žฌ ๋ฒ”์œ„ ๋‚ด์—์„œ ์œ ํšจํ•œ์ง€ ๊ฒ€์‚ฌ
fn main() {
    let x = 5;
    let r = &x;
    println!("r: {r}");
}
  • ๋ณ€์ˆ˜ x๋ฅผ ๋ณ€์ˆ˜ r๋ณด๋‹ค ์ˆ˜๋ช…์„ ๋Š˜๋ ค ์ฃฝ์€ ์ฐธ์กฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ์ฝ”๋“œ
    • ๋ณ€์ˆ˜ x๊ฐ€ ์œ ํšจํ•œ ๋™์•ˆ ๋ณ€์ˆ˜ r์ด ์ฐธ์กฐํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ญ์ƒ ์œ ํšจํ•จ

๐Ÿค” ํ•จ์ˆ˜์˜ ์ œ๋„ค๋ฆญ ์ˆ˜๋ช…

fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let msg1 = String::from("abcd");
    let msg2 = "xyz";
    println!("longest: {}", longest(msg1.as_str(), msg2));
}
// Result
// error[E0106]: missing lifetime specifier
  • ๋Ÿฌ์ŠคํŠธ ์ž…์žฅ์—์„œ ๋ฆฌํ„ด๊ฐ’์ด ๋ณ€์ˆ˜ x์™€ y ์ค‘ ์–ด๋–ค ๊ฒƒ์ด ๋ฆฌํ„ด๋  ์ง€ ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ฆฌํ„ด ํƒ€์ž…์— ์ œ๋„ค๋ฆญ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•จ
  • ํ•จ์ˆ˜์— ์ „๋‹ฌ๋˜๋Š” ์ฐธ์กฐ์˜ ์‹ค์ œ ์ˆ˜๋ช…๋„ ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ฒ”์œ„๋ฅผ ์ด์šฉํ•ด ๋ฆฌํ„ดํ•˜๋ ค๋Š” ์ฐธ์กฐ๊ฐ€ ํ•ญ์ƒ ์œ ํšจํ•œ์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์Œ

๐Ÿค” ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜ ๋ฌธ๋ฒ•

  • ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜์€ ์ฐธ์กฐ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ๋ณ€๊ฒฝํ•˜์ง€๋Š” ์•Š์œผ๋ฉฐ ๊ฐœ๋ณ„ ์ฐธ์กฐ์˜ ์ˆ˜๋ช…์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ์—ฌ๋Ÿฌ ์ฐธ์กฐ ๊ฐ„ ์ˆ˜๋ช…์˜ ๊ด€๊ณ„๋ฅผ ์„œ์ˆ ํ•  ์ˆ˜ ์žˆ์Œ
  • ์ œ๋„ค๋ฆญ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋ฉด ์–ด๋–ค ์ˆ˜๋ช…์˜ ์ฐธ์กฐ๋„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Œ
&i32            // ์ฐธ์กฐ
&'a i32         // ๋ช…์‹œ์ ์ธ ์ˆ˜๋ช…์„ ๊ฐ€์ง„ ์ฐธ์กฐ
&'a mut i32     // ๋ช…์‹œ์ ์ธ ์ˆ˜๋ช…์„ ๊ฐ€์ง„ ๊ฐ€๋ณ€ ์ฐธ์กฐ
  • ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜ ๋ฌธ๋ฒ•
  • ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜์€ ๊ทธ ์ž์ฒด๋กœ ๋งŽ์€ ์˜๋ฏธ๋ฅผ ๊ฐ–์ง€ ์•Š์Œ
    • ๋Ÿฌ์ŠคํŠธ์—๊ฒŒ ์ œ๋„ค๋ฆญ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ง€์ •๋œ ๊ฐ ์ฐธ์กฐ๊ฐ€ ์„œ๋กœ ์–ด๋–ค ๊ด€๊ณ„์ธ์ง€ ๋ช…์‹œํ•  ๋ฟ

๐Ÿค” ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์˜ ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let msg1 = String::from("abcd");
    let msg2 = "xyz";
    println!("longest: {}", longest(msg1.as_str(), msg2));
}
// Result
// longest: abcd
  • ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•จ์ˆ˜ ์ด๋ฆ„๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ์ด์˜ ๊บพ์‡ ๊ด„ํ˜ธ์— ์ œ๋„ค๋ฆญ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•จ
  • ๋ชจ๋“  ์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฆฌํ„ด๊ฐ’์ด ๊ฐ™์€ ์ˆ˜๋ช…์„ ๊ฐ€์ ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆ˜๋ช… 'a ๋ฅผ ๋ชจ๋“  ์ฐธ์กฐ์— ์ง€์ •ํ•จ
  • ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— ๋ช…์‹œํ•œ๋‹ค๊ณ  ํ•ด์„œ ํ•จ์ˆ˜์— ์ „๋‹ฌ๋˜๊ฑฐ๋‚˜ ํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ดํ•˜๋Š” ๊ฐ’์˜ ์ˆ˜๋ช…์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹˜
    • ๋Œ€์—ฌ ๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ์ด ์ œ์•ฝ์— ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•  ๋ฟ
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let msg1 = String::from("abcd");
    {
        let msg2 = String::from("xyz");
        let result = longest(msg1.as_str(), msg2.as_str());
        println!("longest: {result}");
    }
}
// Result
// longest: abcd
  • ๋ฆฌํ„ด๊ฐ’์— ๋Œ€ํ•œ ์ฐธ์กฐ์ธ ๋ณ€์ˆ˜ result๊ฐ€ ์•ˆ์ชฝ ๋ฒ”์œ„์—์„œ ์œ ํšจํ•˜๊ธฐ์— ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ๋จ
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let msg1 = String::from("abcd");
    let result;
    {
        let msg2 = String::from("xyz");
        result = longest(msg1.as_str(), msg2.as_str());
    }
    println!("longest: {result}");
}
// Result
// error[E0597]: `msg2` does not live long enough
  • ๋ณ€์ˆ˜ result๊ฐ€ ์œ ํšจํ•˜๋ ค๋ฉด ๋ณ€์ˆ˜ msg2๊ฐ€ ๋ฐ”๊นฅ์ชฝ ๋ฒ”์œ„๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ์œ ํšจํ•ด์•ผ ํ•จ
  • ๋ณ€์ˆ˜ msg2๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š๊ธฐ์— ์œ ํšจํ•˜์ง€ ์•Š์€ ์ฐธ์กฐ๋ฅผ ๋ฆฌํ„ดํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด์„œ ์ปดํŒŒ์ผ๋˜์ง€ ์•Š์Œ

๐Ÿค” ์ˆ˜๋ช…์˜ ๊ด€์ ์—์„œ ์ƒ๊ฐํ•˜๊ธฐ

  • ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์€ ํ•จ์ˆ˜์˜ ๋™์ž‘์— ๋”ฐ๋ผ ๋‹ค๋ฆ„
  • ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐ๋ฅผ ๋ฆฌํ„ดํ•  ๋•Œ๋Š” ๋ฆฌํ„ด ํƒ€์ž…์˜ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์ค‘ ํ•˜๋‚˜์˜ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ผ์น˜ํ•ด์•ผ ํ•จ
  • ์ˆ˜๋ช… ๋ฌธ๋ฒ•์€ ํ•จ์ˆ˜์˜ ์—ฌ๋Ÿฌ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฆฌํ„ด๊ฐ’์˜ ์ˆ˜๋ช…์„ ์—ฐ๊ฒฐํ•จ
    • ์ˆ˜๋ช…์ด ์—ฐ๊ฒฐ๋˜๋ฉด ๋Ÿฌ์ŠคํŠธ๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์•ˆ์ •์ ์ธ ์ž‘์—…์„ ํ—ˆ์šฉํ•˜๊ณ , ์ฃฝ์€ ํฌ์ธํ„ฐ๋‚˜ ๊ธฐํƒ€ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ „์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋Š” ์ž‘์—…์„ ์ฐจ๋‹จํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ถฉ๋ถ„ํ•œ ์ •๋ณด๋ฅผ ์–ป์Œ

๐Ÿค” ๊ตฌ์กฐ์ฒด ์ •์˜์—์„œ์˜ ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜

struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("์ฃ„์™€ ๋ฒŒ. ๊ฐ€๋‚œํ•œ ๋Œ€ํ•™์ƒ ์ถœ์‹ ์ธ ๋ผ์Šค์ฝœ๋‹ˆ์ฝ”ํ”„๋Š”...");
    let first_sentence = novel.split('.')
        .next().expect(
            "๋ฌธ์žฅ์—์„œ '.'๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ."
        );
    let i = ImportantExcerpt { part: first_sentence };

    println!("first_sentence: {first_sentence}");
    println!("i: {}", i.part);
}
// Result
// first_sentence: ์ฃ„์™€ ๋ฒŒ
// i: ์ฃ„์™€ ๋ฒŒ
  • ImportantExcerpt ๊ตฌ์กฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ part ํ•„๋“œ์— ์ €์žฅ๋œ ์ฐธ์กฐ์˜ ์ˆ˜๋ช…์„ ๋ฒ—์–ด๋‚  ์ˆ˜ ์—†์Œ

๐Ÿค” ์ˆ˜๋ช…์˜ ์ƒ๋žต

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

fn main() {
    let msg = String::from("Hello, Rust!");

    println!("{}", first_word(msg.as_str()));
}
// Result
// Hello,
  • ๋Ÿฌ์ŠคํŠธ์˜ ์ดˆ๊ธฐ ๋ฒ„์ „์—์„œ๋Š” ๋ชจ๋“  ์ฐธ์กฐ๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ์ˆ˜๋ช…์ด ์žˆ์–ด์•ผ ํ–ˆ์Œ
    • ํŠน์ • ์ƒํ™ฉ์—์„œ ๊ฐ™์€ ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜์„ ๋ฐ˜๋ณตํ•ด์„œ ์ ์šฉํ•ด์•ผ ํ•จ
    • ๋•Œ๋ฌธ์— ๋ช‡ ๊ฐ€์ง€ ๊ฒฐ์ •์ ์ธ ํŒจํ„ด์„ ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ฝ”๋“œ์— ์ถ”๊ฐ€ํ•ด์„œ ๋Œ€์—ฌ ๊ฒ€์‚ฌ๊ธฐ๊ฐ€ ํ•ด๋‹น ์ƒํ™ฉ์—์„œ๋Š” ์ˆ˜๋ช…์„ ์ถ”๋ก ํ•จ์œผ๋กœ์จ ๋ช…์‹œ์ ์ธ ์• ๋…ธํ…Œ์ด์…˜์ด ํ•„์š”์น˜ ์•Š๋„๋ก ํ–ˆ์Œ
  • ์ˆ˜๋ช… ์ƒ๋žต ๊ทœ์น™(lifetime elision rules) : ๋Ÿฌ์ŠคํŠธ์˜ ์ฐธ์กฐ ๋ถ„์„์— ์ถ”๊ฐ€๋œ ํŒจํ„ด
    • ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ค€์ˆ˜ํ•ด์•ผ ํ•  ๊ทœ์น™์ด ์•„๋‹Œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ณ ๋ คํ•ด์•ผ ํ•  ํŠน์ •ํ•œ ์ƒํ™ฉ์„ ์˜๋ฏธ
    • ์™„๋ฒฝํ•œ ์ถ”๋ก ์„ ์ œ๊ณตํ•˜์ง€๋Š” ์•Š์Œ
    • ์ž…๋ ฅ ์ˆ˜๋ช…(input lifetime) : ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ ์šฉ๋˜๋Š” ์ˆ˜๋ช…
    • ์ถœ๋ ฅ ์ˆ˜๋ช…(output lifetime) : ๋ฆฌํ„ด๊ฐ’์— ์ ์šฉ๋˜๋Š” ์ˆ˜๋ช…
    • ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์„ธ ๊ฐœ์˜ ๊ทœ์น™์„ ๋ชจ๋‘ ์ ์šฉํ–ˆ๋Š”๋ฐ๋„ ์ฐธ์กฐ์˜ ์ ์ ˆํ•œ ์ˆ˜๋ช…์„ ํŒ๋‹จํ•  ์ˆ˜ ์—†์œผ๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ
      • fn ํ‚ค์›Œ๋“œ๋กœ ์ •์˜ํ•œ ํ•จ์ˆ˜, impl ๋ธ”๋ก์—๋„ ์ ์šฉ๋จ
    • ๊ทœ์น™ (1) ๊ฐ ์ฐธ์กฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ฐ๊ฐ์˜ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์–ด์•ผ ํ•จ
    • ๊ทœ์น™ (2) ๋ช…์‹œ์ ์œผ๋กœ ํ•˜๋‚˜์˜ ์ž…๋ ฅ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ์ž…๋ ฅ ์ˆ˜๋ช…์„ ๋ชจ๋“  ์ถœ๋ ฅ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ ์šฉํ•จ
    • ๊ทœ์น™ (3) ์ž…๋ ฅ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํ•˜๋‚˜ ์ด์ƒ์ด๋ฉฐ ํ•จ์ˆ˜๊ฐ€ ๋ฉ”์„œ๋“œ๋กœ ์„ ์–ธ๋˜์–ด์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ &self ๋‚˜ &mut self ์ผ ๋•Œ๋Š” self ๋ณ€์ˆ˜์˜ ์ˆ˜๋ช…์„ ๋ชจ๋“  ์ถœ๋ ฅ ์ˆ˜๋ช… ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ ์šฉํ•จ
      • ๋ฉ”์„œ๋“œ์˜ ์„ ์–ธ์— ๋” ์ ์€ ์‹ฌ๋ณผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ๋ฉ”์„œ๋“œ๋ฅผ ์ฝ๊ณ  ์“ฐ๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›€

๐Ÿค” ๋ฉ”์„œ๋“œ ์ •์˜์—์„œ์˜ ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜

struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention! {}", announcement);
        self.part
    }
}

fn main() {
    let novel = String::from("์ฃ„์™€ ๋ฒŒ. ๊ฐ€๋‚œํ•œ ๋Œ€ํ•™์ƒ ์ถœ์‹ ์ธ ๋ผ์Šค์ฝœ๋‹ˆ์ฝ”ํ”„๋Š”...");
    let first_sentence = novel.split('.')
        .next().expect(
            "๋ฌธ์žฅ์—์„œ '.'๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ."
        );
    let i = ImportantExcerpt { part: first_sentence };

    println!("{}", i.level());
    println!("{}", i.announce_and_return_part("Everyone!!"));
}
// Result
// 3
// Attention! Everyone!!
// ์ฃ„์™€ ๋ฒŒ
  • self ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ•˜๋‚˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํฌํ•จํ•˜๋ฉฐ ๋ฆฌํ„ด๊ฐ’์œผ๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” i32 ํƒ€์ž…์„ ๋ฆฌํ„ดํ•˜๋Š” level ๋ฉ”์„œ๋“œ
    • ์ฒซ ๋ฒˆ์งธ ์ƒ๋žต ๊ทœ์น™ ๋•๋ถ„์— self ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ˆ˜๋ช… ์ง€์ • ํ•„์š” ์—†์Œ
  • ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š” announce_and_return_part ๋ฉ”์„œ๋“œ
    • ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ˆ˜๋ช…์ด ๋ช…์‹œ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ฒซ ๋ฒˆ์งธ ์ˆ˜๋ช… ์ƒ๋žต ๊ทœ์น™์„ ์ ์šฉํ•ด &self ์™€ announcement ๋งค๊ฐœ๋ณ€์ˆ˜์— ๊ฐ๊ฐ์˜ ์ˆ˜๋ช… ๋ถ€์—ฌ
    • ๋งค๊ฐœ๋ณ€์ˆ˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ &self ์ด๋ฏ€๋กœ ๋ฆฌํ„ด ํƒ€์ž… ์—ญ์‹œ &self ์˜ ์ˆ˜๋ช…์„ ์ด์–ด๋ฐ›์•„ ๋ชจ๋“  ์ฐธ์กฐ๊ฐ€ ์ˆ˜๋ช…์„ ๊ฐ–๊ฒŒ ๋จ

๐Ÿค” ์ •์  ์ˆ˜๋ช…

let s: &'static str = "String has a static lifetime.";
  • ์ •์  ์ˆ˜๋ช…('static) : ํŠน๋ณ„ํ•œ ์ˆ˜๋ช…์œผ๋กœ ์ „์ฒด ํ”„๋กœ๊ทธ๋žจ์— ์ ์šฉ๋จ
    • ํ”„๋กœ๊ทธ๋žจ ๋ฐ”์ด๋„ˆ๋ฆฌ์— ์ง์ ‘ ์ €์žฅ๋˜๋ฉฐ ํ•ญ์ƒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
    • ์ฐธ์กฐ์— 'static ์ˆ˜๋ช…์„ ์ ์šฉํ•˜๊ธฐ์— ์•ž์„œ ์ด ์ฐธ์กฐ๊ฐ€ ์‹ค์ œ๋กœ ํ”„๋กœ๊ทธ๋žจ์˜ ์ „์ฒด ์ˆ˜๋ช…๊ณผ ๊ฐ™์•„์•ผ ํ•˜๋Š”์ง€ ์ƒ๊ฐํ•ด ๋ณผ ํ•„์š”๊ฐ€ ์žˆ์Œ
      • ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ ๋Œ€๋ถ€๋ถ„์€ ์ฃฝ์€ ์ฐธ์กฐ๋‚˜ ์ˆ˜๋ช… ๋ถˆ์ผ์น˜๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ
      • ์ด๋Ÿฐ ๋ฌธ์ œ์˜ ์ ์ ˆํ•œ ํ•ด๊ฒฐ์ฑ…์€ 'static ์ˆ˜๋ช… ์ ์šฉ์ด ์•„๋‹Œ ๋ฌธ์ œ์˜ ๊ทผ๋ณธ ์›์ธ์„ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ž„

5๏ธโƒฃ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜, ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„, ๊ทธ๋ฆฌ๊ณ  ์ˆ˜๋ช…

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str 
    where T: Display
{
    println!("Attention! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let msg1 = String::from("abcd");
    let msg2 = String::from("xyz");

    let result = longest_with_an_announcement(
        msg1.as_str(), msg2.as_str(), "Everyone!!"
    );

    println!("result: {}", result);
}
  • ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜, ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„, ์ˆ˜๋ช…์„ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜์— ๋ชจ๋‘ ์ ์šฉํ•œ ์˜ˆ์ œ ์ฝ”๋“œ
  • ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ๋ฌธ์ž์—ด ์Šฌ๋ผ์ด์Šค์˜ ๊ธธ์ด๋ฅผ ๋น„๊ตํ•˜๊ธฐ ์ „์— ์ œ๋„ค๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋ฏ€๋กœ Display ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„๊ฐ€ ํ•„์š”ํ•จ

Summary

  • ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜
    • ๋‹ค๋ฅธ ํƒ€์ž…์„ ๋Œ€์ƒ์œผ๋กœ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ
  • ํŠธ๋ ˆ์ดํŠธ์™€ ํŠธ๋ ˆ์ดํŠธ ๊ฒฝ๊ณ„
    • ์ฝ”๋“œ์— ํ•„์š”ํ•œ ํ–‰์œ„๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•
    • ์ œ๋„ค๋ฆญ ํƒ€์ž…์—๋„ ๊ฐ€๋Šฅํ•จ
  • ์ˆ˜๋ช… ์• ๋…ธํ…Œ์ด์…˜
    • ์ฃฝ์€ ์ฐธ์กฐ์— ๋Œ€ํ•œ ๊ฑฑ์ • ์—†์ด ์œ ์—ฐํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ
    • ์ด์— ๋Œ€ํ•œ ๋ถ„์„์€ ๋ชจ๋‘ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ์— ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Œ
728x90
๋ฐ˜์‘ํ˜•
Comments