Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![allow(dead_code)]
- // A variable has a name and a value.
- struct Variable {
- name: String,
- value: f64,
- }
- // Represents a mathematical expression with a single variable.
- trait Expression {
- fn show(&self);
- fn eval(&self) -> f64;
- fn var(&self) -> &Variable;
- fn var_mut(&mut self) -> &mut Variable;
- }
- // An expression that raises the variable to some power.
- struct Power {
- var: Variable,
- power: i32,
- }
- // It's easy to implement `Expression` for `Power`.
- impl Expression for Power {
- fn show(&self) { println!("{}^{}", self.var.name, self.power); }
- fn eval(&self) -> f64 { self.var.value.powi(self.power) }
- fn var(&self) -> &Variable { &self.var }
- fn var_mut(&mut self) -> &mut Variable { &mut self.var }
- }
- // A collection that semantically contains a list of `Powers`.
- struct PowerList {
- // Internally, the variables and powers are stored separately.
- vars: Vec<Variable>,
- powers: Vec<i32>,
- }
- // Use reference analogs to access the `Powers`.
- impl PowerList {
- // Both an immutable reference analog...
- fn get<'a>(&'a self, index: usize) -> &'a mut PowerMut<'a> {
- PowerRef<'a> { list: self, index: index }
- }
- }
- struct PowerMut<'a> {
- list: &'a mut PowerList,
- index: usize,
- }
- // The `PowerRef` and `PowerRefMut` types should look just like `&Power` and
- // `&mut Power` from the outside, so lets implement `Expression` for them.
- impl<'a> Expression for PowerRef<'a> {
- fn show(&self) {
- let var = &self.list.vars[self.index];
- let power = self.list.powers[self.index];
- println!("{}^{}", var.name, power);
- }
- fn eval(&self) -> f64 {
- let var = &self.list.vars[self.index];
- let power = self.list.powers[self.index];
- var.value.powi(power)
- }
- fn var(&self) -> &Variable {
- &self.list.vars[self.index]
- }
- // Problem 2: This method has to be implemented, but it doesn't make any
- // sense to call it on an immutable reference analog!
- fn var_mut(&mut self) -> &mut Variable {
- panic!("Cannot call `var_mut` on `PowerRef`");
- }
- }
- impl<'a> Expression for PowerRefMut<'a> {
- // Problem 3: There is a lot of duplicated code here.
- fn show(&self) {
- // Cannot call `into` because that would consume `self`.
- // self.into().show();
- // An unsafe conversion into `PowerRef` could reduce the duplication.
- let var = &self.list.vars[self.index];
- let power = self.list.powers[self.index];
- println!("{}^{}", var.name, power);
- }
- fn eval(&self) -> f64 {
- let var = &self.list.vars[self.index];
- let power = self.list.powers[self.index];
- var.value.powi(power)
- }
- fn var(&self) -> &Variable {
- &self.list.vars[self.index]
- }
- fn var_mut(&mut self) -> &mut Variable {
- &mut self.list.vars[self.index]
- }
- }
- fn main() {
- let mut list = PowerList {
- vars: vec![Variable { name: "x".to_string(), value: 4.0 }],
- powers: vec![3],
- };
- {
- let power_ref = list.get(0);
- power_ref.show();
- }
- {
- let mut _power_ref = list.get(0);
- // The next line leads to a panic at runtime.
- // _power_ref.var_mut();
- }
- {
- let _power_ref_mut = list.get_mut(0);
- // Problem 4: The next line won't compile because `power_ref_mut` isn't
- // mutable. This is equivalent to requiring a `mut &mut i32` to change
- // an integer.
- // _power_ref_mut.var_mut();
- }
- {
- let mut power_ref_mut = list.get_mut(0);
- println!("Expression evaluates to {}", power_ref_mut.eval());
- power_ref_mut.var_mut().value = 5.0;
- println!("Changed variable to 5.0");
- println!("Now expression evaluates to {}", power_ref_mut.eval());
- }
- }
Add Comment
Please, Sign In to add comment