使用Rust Add trait引入副作用

时间:2014-10-25 08:49:06

标签: rust

我正在学习Rust,并且为了练习,尝试实现Instrumented<T>类型:

  • 拥有value类型的T字段;
  • 支持T支持的所有基本操作,例如,相等,排序,算术;
  • 将所有这些操作委托给T并计算调用次数;
  • 打印好报告。

这个想法借鉴了Alexander Stepanov的编程课程,在那里他用C ++实现了这个东西。使用Instrumented<T>,可以使用Rust的特征系统,以非常通用的方式,在基本操作方面轻松测量T类型上任何算法的复杂性。

首先,我正在尝试实施具有InstrumentedInt特征的非通用Add并计算additions字段中的所有添加内容。完整代码:http://is.gd/AnF3Rf

这就是特质本身:

impl Add<InstrumentedInt, InstrumentedInt> for InstrumentedInt {
    fn add(&self, rhs: &InstrumentedInt) -> InstrumentedInt {
        self.additions += 1;
        InstrumentedInt {value: self.value + rhs.value, additions: 0}
    }
}

当然它不起作用,因为&self是一个不可变的指针,并且其字段无法分配。

  • 试图声明add函数的参数是可变的,但编译器说它与特征定义不兼容。
  • add中声明impl InstrumentedInt没有Add特征,这不支持添加(没有鸭子输入)。
  • 将操作数定义为可变,不起作用。

这一切都可能吗?

P上。 S。之后,我要去:

  • 使用指向additions可变数组的指针替换uint,以计算许多操作,而不仅仅是添加;
  • InstrumentedInt的所有实例之间共享此指针,可能只是在构造函数中提供参数,
  • 将类型概括为Instrumented<T>;
  • 理想情况下,尝试为不同的专业化制作隐式和不同的计数器。例如,如果算法同时使用intf32Instrumented<int>Instrumented<f32>应该有不同的计数器。

也许这些对解决我当前的问题很重要。

谢谢!

1 个答案:

答案 0 :(得分:2)

这正是various kinds of cells的用例。单元提供了实现内部可变性的工具,即&引用后的可变性。例如,在您的情况下,InstrumentedInt可能如下所示:

struct InstrumentedInt {
    value: int,
    additions: Cell<uint>
}

impl Add<InstrumentedInt, InstrumentedInt> for InstrumentedInt {
    fn add(&self, rhs: &InstrumentedInt) -> InstrumentedInt {
        self.additions.set(self.additions.get()+1);
        InstrumentedInt {value: self.value + rhs.value, additions: Cell::new(0)}
    }
}

至于你之后要做的事情,你可能很难实现它们。他们似乎有可能实施,但并不容易。例如,如果没有unsafe,您将无法使用可变全局数据(可能使用ArcMutex等同步工具来使用不带unsafe的全局变量,但我从来没有这样做,所以我现在不确定)。对于不同专业化的不同计数器,您可以再次使用AnyMapTypeMap等库,使用某种全局变量。