1个不稳定版本
0.1.0 | 2024年6月7日 |
---|
#1131 in Rust模式
每月下载量 138
28KB
428 行
n-functor
你发现自己正在为15种不同的递归类型编写相同的map
函数,这些类型有6个类型参数。为MyData<A,B,C,D,E,F>
编写map_all
的时间是不值得的。这应该比这简单,肯定有一些派生模式?啊,但是Rust的类型系统不支持高阶类型。这是你因为虚度年华而知道的一段信息。
相反,你像许多人一样希望有人为你编写一个宏来完成这项工作。啊,但是这里有复杂因素,比如孤儿规则等。你当然不会自己编写这个。过程宏很可怕,你对它们的实验是徒劳的,也是压力的来源。
总会有另一个人已经使用我们的基础设施完成了这项工作,最终你会发现你就是那个人。也许成为那个人会让你更受雇用,也许它将是你的毕业设计,也许它将是你的学术生涯,一个好处,下一个技术聚会的破冰者。但是成为那个人是痛苦的,你不觉得当那个人是“另一个人”时你会感到解脱吗?
这无关紧要,你现在需要的是编写一个对复杂类型来说简单但重复起来痛苦的对映射函数。你不想在这类项目上浪费自己的血汗。别担心,亲爱的、最受爱戴的软件工程师,我今天作为“另一个人”为你流了血。
#[derive(...)]
// optional: setting a name for the type parameters, doesn't affect the structure
// of the data in any way, just the variable names.
#[derive_n_functor(B = second_type_param)]
// We can also choose a different map name, the default being `map`.
// This will recurse down to child elements without a custom `map_with` declaration.
// #[derive_n_functor(map_name = different_map)]
struct Data<A, B> {
a: A,
// The map_with argument is an arbitrary expression.
#[map_with(Option::map)]
b: Option<B>
}
// Expands to this, merely at the cost of the soul of the author.
impl <A, B> Data<A, B> {
pub fn map<A2, B2>(self, map_A: impl Fn(A) -> A2, map_second_type_param: impl Fn(B) -> B2) -> Data<A2, B2> {
let Data {a, b} = self;
Data {
a: map_A(a),
b: (Option::map)(b, map_second_type_param),
}
}
}
特性
- 支持结构体和枚举,包括命名和无命名的字段(包括枚举变体中的字段)。
- 通过形式
#[derive_n_functor(T = name_for_t)]
为map函数中的类型参数提供自定义名称。 - 通过`#[derive_n_functor(map_name = custom_map)]`为实现的map函数提供自定义名称。
- 对于具有非平凡类型的字段,通过
#[map_with(...)]
属性进行自定义映射,您可以在此处放置任何函数(包括lambda函数)以处理复杂情况。 - 对具有适用类型参数的字段进行递归调用。
- 请参阅示例,以了解我的边缘情况测试的可怕后果(截至编写时,所有这些都能编译)。
限制
目前不支持以下内容
- 具有非类型参数的类型,例如const泛型和生命周期。
- 难以处理的元组,请参阅examples/n-functor.rs,了解如何格式化元组的
#[map_with(...)]
。
其他限制
- 目前仅生成自消耗的映射函数。目前没有
map_ref(&self, ...)
,目前没有承诺。但这可能与未来支持生命周期参数相矛盾。
设计
这并不基于任何特质的任何方式工作,这是由于当前rust类型系统的限制。这在纯粹函数编程的角度上留下了一些遗憾,但这确实是rust自身限制的固有特性。要求一个不造成用户极大压力的特质绑定系统,可能是一个名为n-functor
的crate的公平要求,但我为您提供下一个最佳选择。
许可证
该项目受MIT许可证保护。我不喜欢将其置于MIT许可证之下,我一生中花费了太多的时间,感觉以这种方式为开源贡献使我负有责任。如果我编写了一个具有广泛影响力的简单实用程序,那么当有人将其用于导弹软件时,这意味着什么?有多少其他人被这种想法所困扰?在哲学层面上,需要多少层次才能让您摆脱困境?
那么,关于机器学习系统吞噬这些源代码,然后在别人的代码库中呕吐出来呢?我的工作、我的痛苦在我的声音中响起,在微软最不高效的数据库中被索引,为别人的利益而唱出恶意的回声,而没有任何形式的认可?向开源贡献曾经是一种获得社会资本的方式,是一种让人们用自己的时间换取联系、机会和影响力的方式,当然,最后你还能免费获得软件,在认识论层面上,很难使软件变得恶意。《在一定程度上》。这是一种不完美的生产方式,但在这里人们找到了社区,这证明了人们只是喜欢一起工作,而且利润动机,就像其他所有所谓的公理一样,是可塑的,并且受肉体的约束,就像所有修辞一样。但现在,它被每个软件公司所包围,它们追逐着一个不断失败的机器神,但它们坚持认为这个神已经带来了一个新世界。
我请求您用它来建设一个更美好的世界。我请求您辞去在雷神公司的工作。我请求您从政治层面质疑您公司在世界上的位置。我请求您将您的硅谷收入投入到下层人民的生活中。我请求一个自由的巴勒斯坦。我请求一个真正和平的世界,而不是那种将不平衡的帝国殖民暴力称为和平的世界。我请求自我意识,并希望您不要停滞不前。我请求您阅读。我请求您交谈。我请求您参与一种可以使世界真正成为每一个仍跳动的心脏的更好地方,让每一个曾经停止跳动的心脏都能在其他人中间茁壮成长。这是一个软件。
依赖项
~295–750KB
~18K SLoC