[rust] 제네릭 메모이제이션

제네릭 메모이제이션은 제네릭 함수나 구조체의 호출 결과를 캐시하여 이후에 동일한 호출이 있는 경우에는 다시 계산하지 않고 캐시된 값을 반환하는 기법입니다. Rust에서는 이를 구현하기 위해 lazy_static 또는 once_cell 라이브러리를 사용할 수 있습니다.

lazy_static 라이브러리를 사용한 제네릭 메모이제이션

use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref CACHE: HashMap<i32, i32> = HashMap::new();
}

fn memoize<F, T>(arg: i32, func: F) -> i32
    where F: Fn(i32) -> T,
          T: Into<i32>,
{
    if let Some(&result) = CACHE.get(&arg) {
        return result;
    }

    let result = func(arg).into();
    CACHE.insert(arg, result);
    result
}

fn main() {
    let double = memoize(5, |x| x * 2);
    println!("{}", double); // Output: 10
}

위 코드에서 lazy_static 매크로를 사용해 전역적인 CACHE를 선언하고, memoize 함수를 통해 호출 결과를 캐시합니다. 이렇게 함으로써 동일한 입력값에 대한 재귀 호출을 효율적으로 처리할 수 있습니다.

once_cell 라이브러리를 사용한 제네릭 메모이제이션

use std::collections::HashMap;
use once_cell::sync::Lazy;

static CACHE: Lazy<HashMap<i32, i32>> = Lazy::new(HashMap::new);

fn memoize<F, T>(arg: i32, func: F) -> i32
    where F: Fn(i32) -> T,
          T: Into<i32>,
{
    if let Some(&result) = CACHE.get(&arg) {
        return result;
    }

    let result = func(arg).into();
    CACHE.insert(arg, result);
    result
}

fn main() {
    let double = memoize(5, |x| x * 2);
    println!("{}", double); // Output: 10
}

once_cell 라이브러리를 사용한 방법은 lazy_static과 유사하며, Rust 1.48 버전 이상에서 제네릭 메모이제이션을 위한 최신 방법으로 추천됩니다.

제네릭 메모이제이션은 복잡한 연산의 결과를 캐시함으로써 성능을 향상시킬 수 있는 유용한 패턴입니다.

참고 자료