functional-programming - 如何创建没有样板代码的只读结构?

标签 functional-programming rust

尽管 Rust 吸收了许多优秀的现代编程思想,但似乎没有呈现一个非常基本的特性。

现代(伪)函数式代码基于大量以下类型的类:

pub struct NamedTuple {
    a: i8,
    b: char,
}
impl NamedTuple {
    fn new(a: i8, b: char) -> NamedTuple {
        NamedTuple { a: a, b: b }
    }
    fn a(&self) -> i8 {
        self.a
    }
    fn b(&self) -> char {
        self.b
    }
}

如您所见,这里有很多样板代码。如果没有样板代码,真的没有办法紧凑地描述这些类型吗?

最佳答案

当你有样板时,想想:

macro_rules! ro {
    (
        pub struct $name:ident {
            $($fname:ident : $ftype:ty),*
        }
    ) => {
        pub struct $name {
            $($fname : $ftype),*
        }

        impl $name {
            fn new($($fname : $ftype),*) -> $name {
                $name { $($fname),* }
            }

            $(fn $fname(&self) -> $ftype {
                self.$fname
            })*
        }
    }
}

ro!(pub struct NamedTuple {
    a: i8,
    b: char
});

fn main() {
    let n = NamedTuple::new(42, 'c');
    println!("{}", n.a());
    println!("{}", n.b());
}

这是一个基本宏,可以扩展以处理指定可见性以及结构和字段上的属性/文档。

我会质疑您拥有的样板文件与您认为的一样多。例如,您只显示 Copy 类型。一旦您将 StringVec 添加到您的结构中,这就会分崩离析,您需要返回一个引用或获取 self .


在编辑方面,我不认为这是好的或惯用的 Rust 代码。如果您有一个人们需要深入研究的值类型,只需将字段公开:

pub struct NamedTuple {
    pub a: i8,
    pub b: char,
}

fn main() {
    let n = NamedTuple { a: 42, b: 'c' };
    println!("{}", n.a);
    println!("{}", n.b);
}

现有的 Rust 功能可以防止 getter 方法首先尝试解决的大多数问题。

基于变量绑定(bind)的可变性

n.a = 43;
error[E0594]: cannot assign to field `n.a` of immutable binding

引用规则

struct Something;

impl Something {
    fn value(&self) -> &NamedTuple { /* ... */ }
}

fn main() {
    let s = Something;
    let n = s.value();
    n.a = 43;
}
error[E0594]: cannot assign to field `n.a` of immutable binding

如果您已将值类型的所有权转让给其他人,谁在乎他们是否更改了它?

请注意,我正在对 值类型 进行区分,如 Growing Object-Oriented Software Guided by Tests 所述,它们区别于对象。对象不应有暴露的内部结构。

关于functional-programming - 如何创建没有样板代码的只读结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50929898/

相关文章:

Ruby Map/Reduce 函数必须高效吗?

functional-programming - 检查列表中的所有元素是否都有 :ok element

rust - cargo 单据中的下标和上标字符?

rust - 仅构建 `lib` 目标

rust - 有没有更简单的方法在我的构建脚本上运行 clippy?

list - 为什么 "and"和 "or"在收到列表后会提供这些结果?

scala - 案例类的复制方法是否使用结构共享?

generics - 枚举通用结构

serialization - 如何在不包含枚举变体名称的情况下序列化枚举?

haskell - "error"函数的存在如何影响 Haskell 的纯度?