# generic_static **Repository Path**: rustup/generic_static ## Basic Information - **Project Name**: generic_static - **Description**: from crates.io - **Primary Language**: Rust - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-26 - **Last Updated**: 2021-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### Problem lets consider following code: ```rust use once_cell::sync::OnceCell; trait X{ fn string() -> String; } // having to recompute string() over and over might be expensive (not in this example, but still) // so we use lazy initialization fn generic() -> &'static str{ static VALUE: OnceCell = OnceCell::new(); VALUE.get_or_init(||{ T::string() }) } // And now it can be used like this struct A; impl X for A{ fn string() -> String{ "A".to_string() } } struct B; impl X for B{ fn string() -> String{ "B".to_string() } } fn main(){ assert_eq!(generic::(), "A"); assert_eq!(generic::(), "A"); // Wait what? // Not completely behaviour I was expecting // This is due to fact that static variable placed inside of generic function // wont be cloned into each version of function, but will be shared // Thus second call does not initialize value for B, but takes value // initialized in previous call. } ``` ### Solution This crate was designed to solve this particular problem. Lets make some changes: ```rust use generic_static::StaticTypeMap; use once_cell::sync::OnceCell; trait X{ fn string() -> String; } // having to recompute string() over and over might be expensive (not in this example, but still) // so we use lazy initialization fn generic() -> &'static str{ // T is bound to 'static static VALUE: OnceCell> = OnceCell::new(); let map = VALUE.get_or_init(|| StaticTypeMap::new()); map.call_once::(||{ T::string() }) } // And now it can be used like this struct A; impl X for A{ fn string() -> String{ "A".to_string() } } struct B; impl X for B{ fn string() -> String{ "B".to_string() } } fn main(){ assert_eq!(generic::(), "A"); assert_eq!(generic::(), "B"); } ``` ### Drawbacks Current implementation uses RwLock to make it safe in concurrent applications, which will be slightly slower then regular