#static #lazy-evaluation #getter-setter #macro

type_cell

使用静态获取/设置方法将值静态地附加到类型上

8 个版本

0.3.4 2023 年 12 月 29 日
0.3.3 2023 年 12 月 27 日
0.2.1 2023 年 11 月 12 日
0.1.1 2023 年 9 月 10 日
0.1.0 2023 年 8 月 30 日

#729 in Rust 模式


bevy_cell 使用

MIT/Apache

48KB
649

宏将值静态地附加到类型上,使用静态获取和设置方法。

[dependencies]
type_cell = "0.3"
use type_cell::*;

tycell!{
    {String} 
        [nice_str]
        [lazy_str.clone() -> String {"hello"}]
    {bool > Vec<bool>} 
        [is_nice]
    {!Vec<bool>} 
        [are_nice]
}

fn main(){
    String::set_nice_str("world");
    assert_eq!(
        "hello world",
        &format!("{} {}",&String::lazy_str(),String::nice_str())
    );
}

🧱 基本用法

  • 使用宏:tycell!{...}
  • 值应该附加在哪种类型上?u32 {...}
  • 值是什么类型?static u32:
    • 它将使用哪些设置?
      🌟 once_read 设置一次。以只读方式获取!(与 Mutex/RwLock/... 结合使用以实现可变性)
      🏁 once_write 设置一次。以可变方式获取,但存在竞态条件风险!(确保你赢得这场竞争!)
      🦥 lazy_readonce_read 类似,但在宏内部设置延迟!
      👹 lazy_writeonce_write 类似,但在宏内部设置延迟!!
    • 示例:static u32: once_read;static String: lazy_read;
  • 默认设置器方法的名称是什么?set_type()
  • 默认获取器方法的名称是什么?get_type()
// Basic Usage 
tycell!{ bool {
    static Vec<bool>: once_read;
    set set_vec();
    get vec();
}}
// Set it somewhere once:
bool::set_vec(Vec::from([true,false,true]));
// Get it anywhere afterwards:
assert_eq!(&[true,false,true],bool::vec().as_slice());

默认设置器参数是一个动态的 Into<..>,并使用 .into()
这意味着在这个示例中,你也可以这样设置它

bool::set_vec([true,false,true]);
assert_eq!(&[true,false,true],bool::vec().as_slice());

⚗ 高级用法

可以定义具有不同参数和返回类型的多个设置器和获取器!
有两种方法可以做到这一点

  • 方法
    • 使用内联方法进行简单转换!
    • 设置设置布尔值(选项<usize>): 执行.有值();
    • 获取获取布尔值() -> 布尔值: 静态.克隆();
  • 函数
    • 使用具有正确参数/返回类型且在同一文件中可访问的函数!
    • 在函数元之前使用 =
    • 设置=设置基函数(a:选项<usize>);
    • 获取=获取基函数() -> 布尔值;
// Advanced Usage 
fn set_by_function (a:Option<usize>) -> bool {a.is_some()}
fn get_by_function (a:&bool) -> bool {a.clone()}
tycell!{ bool {
    static bool: once_read;
    set set_raw();
    set set_by_methods(Option<usize>): do.is_some();
    set =set_by_function(a:Option<usize>);
    get get_raw();
    get get_by_methods() -> bool: static.clone();
    get =get_by_function() -> bool;
}}
bool::set_by_methods(None);
assert_eq!(false,bool::get_by_methods());

支持两种不同的方式支持带有参数的方法

  • 常量
    • 在常量值之前使用 =
    • 设置设置数字(u32): 执行.夹具(=0,=100);
    • 获取获取数字() -> 布尔值: 静态.夹具(=0,=100);
  • 透传
    • 使用值的类型命名,将其传递到函数中!
    • 设置设置数字(u32): 执行.夹具(最小:u32,最大:u32);
    • 获取获取数字() -> 布尔值: 静态.夹具(最小:u32,最大:u32);
// Advanced Usage 
tycell!{ u32 {
    static u32: once_read;
    set set_raw();
    set set_by_methods(u32): do.clamp(=0,=100);
    set set_pass(u32): do.clamp(min:u32,max:u32);
    get get_raw();
    get get_by_methods() -> u32: static.add(=5);
    get get_pass() -> u32: static.add(val:u32);
}}
// Sets value to 1000.clamp(0,123) = 123
u32::set_pass(1000,0,123); 
// Gets 123.add(5) = 128
assert_eq!(128,u32::get_by_methods());

🧊 常量

您还可以设置常量值!

// Constant
tycell!{ u32 {
    const u32 = 100;
    get number();
}}
// Gets 10!
assert_eq!(10,u32::number());

👹 有风险的可变选项

只有 use this if you're sure there are no race conditions (or they 're not ) or for debug purposes!
要使静态值可变,请使用 once_writelazy_write

// Risky Mutable
tycell!{ u32 {
    static u32: risky_write;
    set set_number();
    get number();
}}
// Set it somewhere once:
u32::set_number(5u32);
// Default getter is mutable already
*u32::number() = 10;
// Gets 10!
assert_eq!(10,*u32::number());

🦥 作为惰性静态

要创建惰性静态值,请使用 lazy_read 选项,并用块代替设置器函数!

// Lazy Static
tycell!{ u32 {
    static HashMap<u32,String>: lazy_read;
    set {
        let mut map = HashMap::new();
        for i in 0..100 {
            map.insert(i,i.to_string());
        }
        map
    }
    get get_lazy_map();
    get get_lazy() -> Option<&String>: static.get(id:&u32);
}}
// Gets Some("3":&String)
assert_eq!(&"3",&u32::get_lazy(&3).unwrap());

➡ 简单映射

如果您只需要默认的获取器和设置器,则有一种简短的形式

// Simple Usage
tycell!{
    // store a vec of bools on the bool type
    // a single specifier inside [..] will use once_read
    // adding 'mut' before it sets it to once_write
    // adding a block {} after the specifier will use lazy_.. instead of once_..
    bool > Vec<bool>: [bools] [mut more_bools] [lazy_bools{vec![true,false]}];
    // adding '= value' after the specifier will set a constant value
    bool > u32: [number=100];
}
bool::set_bools([true,false]);
bool::set_more_bools([true,false]);

如果您只附加与父项相同类型的值

// Simplest Usage
tycell!{
    // Same as bool > bool: [is_nice];
    bool: [is_nice];
}

如果您想将一个类型附加到其单个泛型类型上,例如 u32 > Vec<u32> 您可以使用 !Vec<u32>.
通过增加 ! 的数量来设置级别,例如 u32 > Vec<Vec<u32>> <=> !!Vec<Vec<u32>>.

tycell!{
    !Vec<bool>:[is_nice];
}

除非在 {} 中包装,否则不能混合不同的左手语法。

// working
tycell!{
    {!Vec<bool>} [is_nice]
    {bool>Vec<bool>} [is_v_nice]
    {bool} [is_x_nice]
}
// NOT working
tycell!{
    !Vec<bool>: [is_nice];
    bool>Vec<bool>: [is_v_nice];
    bool: [is_x_nice];
}

您还可以链式调用获取器的方法,并调整其返回类型。

tycell!{
    {String} 
        [clone_str.clone()->String] 
        [clone_lazy_str.clone()->String{"test"}]
}

➡ 简单(哈希)映射和 Vec

通过在名称后使用,简化从类似 HasmMap 的类型获取值。
如果没有提供键,则类型设置为 Vec<..>。

// uses anythng named TyMap for flaxibility
use std::collections::HashMap as TyMap;
tycell!{
    // same as above, but <keytype> after the specifier
    bool > bool: [bools<u8>] [mut more_bools<u8>] [lazy_bools<u8>{[(1,true)]}];
}
bool::set_bools([(1,true)]);
bool::set_more_bools([(1,true)]);
  • bevy_cell - 将 bevy 处理器和实体附加到类型。

许可证

根据您的选择,许可在 Apache 许可证,版本 2.0MIT 许可证 下。
除非您明确声明,否则您根据Apache-2.0许可证定义的,故意提交以包含在此软件包中的任何贡献,应双许可如上所述,不附加任何额外条款或条件。

依赖项

~51KB