본문 바로가기
Language/Rust

고차원 함수와 매개변수화를 통한 코드 일반화

by y.j 2021. 10. 9.
728x90

고차원 함수와 클로저

고차원 함수 : 다른 함수를 매개변수로 받는 함수; < > 사이에 매개변수로 받을 함수의 타입을 적어야 한다.

fn again<F: Fn(i32) -> i32 >(f: F, s: i32) -> i32 { f(f(s)) }   // 고차원 함수

fn triples(s: i32) -> i32 {
    3 * s
} 

fn main() {
    let mut strength = 26;
    println!("My tripled strength equals {}", triples(strength));  // 26
    println!("My strength is still {}", strength);                 // 26
    strength = triples(strength);
    println!("My strength is now {}", strength);                   // 78
    strength = again(triples, strength);
    println!("I got so lucky to turn my strength into {}", strength);  // 702
}

익명함수 : pipe(|)사이에 매개변수를 입력하고, 중괄호({})에 입력

fn again<F: Fn(i32) -> i32> (f: F, s: i32) -> i32 {f(f(s))}

fn main() {
    strength = 78;
    let triples = |n| {3*n}; // 클로져; 익명함수
    strength = again(triples,strength);
    strength = again(|n|{3*n},strength);
}

클로저 : 익명 함수 내에서 주변 환경(environment)에 있는 변수들을 불러와 사용할 수 있다.

let num = 5;
let plus_num = |x: i32| x + num;

assert_eq!(10, plus_num(5));

mutable variable은 이미 누군가가 소유하고 있기 때문에 사용할 수 없다.

let mut num = 5;
let plus_num = |x: i32| x + num;  // 사용불가; num이 이미 소유권을 가지고 있다.

let y = &mut num;

scope를 다르게 해주면 사용이 가능하다.

let mut num = 5;
{
    let plus_num = |x: i32| x + num;

} // `plus_num`의 scope가 끝날 때, num의 소유도 끝난다.

let y = &mut num;

moving 클로저 : 둘러싸는(enclosing) 모든 변수의 소유권을 가져와 사용 할 수 있다.

fn again<F: Fn(i32) -> i32> (f: F, s: i32) -> i32 {f(f(s))}

fn main() {
    let mut strength = 78;
    let triples = |n| {3*n}; // 클로져; 익명함수
    strength = again(triples,strength);
    //strength = again(|n|{3*n},strength);

    println!("{}",strength);

    let x: i32 = 42;                          // x를 정의
    let print_add = |s| {
        println!("x is {}", x);
        x + s                                // closure x를 사용
    };

    let res = print_add(strength);

    assert_eq!(res, 744);

    let m: i32 = 42;                       // m을 정의
    let print_add_move = move |s| {        // moving closure 정의
        println!("m is {}", m);
        m + s                             
    };

    let res = print_add_move(strength);
    assert_eq!(res, 744)
}

반복자

처음부터 마지막까지 순서대로 반환하는 개체

fn main() {
    let mut rng = 0..7;
    println!("> {:?}", rng.next());
    println!("> {:?}", rng.next());
    for n in rng {
        print!("{} - ", n);
    }
}

컨슈머와 어댑터

컨슈머 : iterator()를 작동시켜 값을 반환한다.
컨슈머는 컴파일을 하지 않기 때문에 타입을 알려줄 필요가 있다.

 let rng = 0..1000;
 let rngvec = rng.collect::<Vec<i32>>();     // 타입을 알려줘야 한다.
 // let rngvec: Vec<i32> = rng.collect();    // 가능
 println!("{:?}", rngvec);

.find() : Option함수로 반환한다.
보통 |n|은 n의 참조자로 되어있어서 *n 역참조로 활용하여 사용해야 한다.

 let forty_two = rng.find(|n| *n >= 42);    // 
 println("{:?}". forty_two);                 // Some(42) 출력

어댑터 : 기존 반복자에서 새로운 박복자를 만드는 것

fn is_even(n: i32) -> bool {
    n % 2 == 0
}

let rng_even = rng.filter(|n| is_even(*n))
                  .collect::<Vec<i32>>();

let rng_even_pow3 = rng.filter(|n| is_even(*n))
                       .map(|n| n * n * n)          // 맵을 이용하여 새로운 아이템을 발생시킬 수 있다.
                       .collect::<Vec<i32>>();

.fold() : 정리 필요

728x90

'Language > Rust' 카테고리의 다른 글

일반화된 자료구조와 함수  (0) 2021.10.10
패턴매칭  (0) 2021.10.08
데이터 구조화  (0) 2021.10.06
함수와 제어문  (0) 2021.10.06
변수  (0) 2021.10.04

댓글