1 个不稳定版本

0.1.1 2019年2月21日
0.1.0 2019年2月12日

9#street

MIT 许可证

52KB
322

本软件包的目的是以方便、高效、函数式和 Rust 友好的方式提供访问和更新嵌套不可变数据结构(容器)内部字段的光学。

虽然 photonix 受到函数式透镜库的启发,但它采取了不同的方法。在这里,您拥有单方法类型类,它提供了使用灵活性,并使目标数据结构成为自己的透镜,这将遵守 透镜定律

这种方法有一些后果。首先,您不需要在内存中存储透镜对象。其次,为了拥有这种功能,您不需要定义和处理闭包。第三,与传统的透镜(依赖于函数组合)相比,组合是以不同的方式实现的。

组合功能是通过在 composites 模块中定义的附加特性提供的。通过使用组合特性,您可以深入到实现数据结构的几个级别。这些特性具有默认实现,因此如果您想使用它们,您只需要编写一个空的 impl 块(或使用 zoom!zoom_all! 宏)。

然而,photonix的真正实力在于其元编程功能。该库包含大多数它定义的基本特质的自动推导(photonix_derive)。自动推导的实现默认避免了数据的克隆。此外,zoom!zoom_all!宏可以帮助您以简洁、直接和易于阅读的方式获得多个组合特质的实现。

示例

一个快速示例(受Monocle启发)。

 // We have a complex data structure

 # use photonix::*;
 #[derive(Get, GetRef, Set, Modify)]
 pub struct Employee { pub name: String, pub company: Company }

 #[derive(Get, GetRef, Set, Modify)]
 pub struct Company { pub name: String, pub address: Address }

 #[derive(Get, GetRef, Set, Modify)]
 pub struct Address { pub city: String, pub street: Street }

 #[derive(Get, GetRef, Set, Modify)]
 pub struct Street { pub number: u16, pub name: String }

 // We create an immutable variable

 let john = Employee {                               // Parent type
     name: String::from("john"),
     company: Company {                              // Level 1
         name: String::from("awesome inc"),
         address: Address {                          // Level 2
             city: String::from("london"),
             street: Street {                        // Level 3
                 number: 23,
                 name: String::from("high street"),  // Level 4
             },
         },
     },
 };

 // Using zoom_all! is going to combine the derived Set, Get, GetRef, and Modify of each level

 zoom_all![Employee => Company => Address => Street => String];

 // Let's change the name of the street, which is at the fourth level

 let john_at_low_street = john.set_fourth(String::from("low street"));

 // We can retrieve the info by reference

 assert_eq!(
     "low street",
     john_at_low_street.get_ref_fourth().as_str()
 );

 // With modify, we can apply a function to the target field

 let john_at_high_again =
     john_at_low_street.modify_fourth(|street_name| street_name.replace("low", "high"));

 // We can retrieve the info by value as well

 assert_eq!(
     "high street",
     john_at_high_again.get_fourth().as_str()
 );

依赖项

~2MB
~46K SLoC