Guest User

Untitled

a guest
Jun 25th, 2018
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.71 KB | None | 0 0
  1. #![allow(dead_code)]
  2.  
  3. // A variable has a name and a value.
  4. struct Variable {
  5. name: String,
  6. value: f64,
  7. }
  8.  
  9. // Represents a mathematical expression with a single variable.
  10. trait Expression {
  11. fn show(&self);
  12. fn eval(&self) -> f64;
  13. fn var(&self) -> &Variable;
  14. fn var_mut(&mut self) -> &mut Variable;
  15. }
  16.  
  17. // An expression that raises the variable to some power.
  18. struct Power {
  19. var: Variable,
  20. power: i32,
  21. }
  22.  
  23. // It's easy to implement `Expression` for `Power`.
  24. impl Expression for Power {
  25. fn show(&self) { println!("{}^{}", self.var.name, self.power); }
  26. fn eval(&self) -> f64 { self.var.value.powi(self.power) }
  27. fn var(&self) -> &Variable { &self.var }
  28. fn var_mut(&mut self) -> &mut Variable { &mut self.var }
  29. }
  30.  
  31. // A collection that semantically contains a list of `Powers`.
  32. struct PowerList {
  33. // Internally, the variables and powers are stored separately.
  34. vars: Vec<Variable>,
  35. powers: Vec<i32>,
  36. }
  37.  
  38. // Use reference analogs to access the `Powers`.
  39. impl PowerList {
  40. // Both an immutable reference analog...
  41. fn get<'a>(&'a self, index: usize) -> &'a mut PowerMut<'a> {
  42. PowerRef<'a> { list: self, index: index }
  43. }
  44. }
  45.  
  46. struct PowerMut<'a> {
  47. list: &'a mut PowerList,
  48. index: usize,
  49. }
  50.  
  51. // The `PowerRef` and `PowerRefMut` types should look just like `&Power` and
  52. // `&mut Power` from the outside, so lets implement `Expression` for them.
  53. impl<'a> Expression for PowerRef<'a> {
  54. fn show(&self) {
  55. let var = &self.list.vars[self.index];
  56. let power = self.list.powers[self.index];
  57. println!("{}^{}", var.name, power);
  58. }
  59. fn eval(&self) -> f64 {
  60. let var = &self.list.vars[self.index];
  61. let power = self.list.powers[self.index];
  62. var.value.powi(power)
  63. }
  64. fn var(&self) -> &Variable {
  65. &self.list.vars[self.index]
  66. }
  67. // Problem 2: This method has to be implemented, but it doesn't make any
  68. // sense to call it on an immutable reference analog!
  69. fn var_mut(&mut self) -> &mut Variable {
  70. panic!("Cannot call `var_mut` on `PowerRef`");
  71. }
  72. }
  73.  
  74. impl<'a> Expression for PowerRefMut<'a> {
  75. // Problem 3: There is a lot of duplicated code here.
  76. fn show(&self) {
  77. // Cannot call `into` because that would consume `self`.
  78. // self.into().show();
  79. // An unsafe conversion into `PowerRef` could reduce the duplication.
  80. let var = &self.list.vars[self.index];
  81. let power = self.list.powers[self.index];
  82. println!("{}^{}", var.name, power);
  83. }
  84. fn eval(&self) -> f64 {
  85. let var = &self.list.vars[self.index];
  86. let power = self.list.powers[self.index];
  87. var.value.powi(power)
  88. }
  89. fn var(&self) -> &Variable {
  90. &self.list.vars[self.index]
  91. }
  92. fn var_mut(&mut self) -> &mut Variable {
  93. &mut self.list.vars[self.index]
  94. }
  95. }
  96.  
  97. fn main() {
  98. let mut list = PowerList {
  99. vars: vec![Variable { name: "x".to_string(), value: 4.0 }],
  100. powers: vec![3],
  101. };
  102. {
  103. let power_ref = list.get(0);
  104. power_ref.show();
  105. }
  106. {
  107. let mut _power_ref = list.get(0);
  108. // The next line leads to a panic at runtime.
  109. // _power_ref.var_mut();
  110. }
  111. {
  112. let _power_ref_mut = list.get_mut(0);
  113. // Problem 4: The next line won't compile because `power_ref_mut` isn't
  114. // mutable. This is equivalent to requiring a `mut &mut i32` to change
  115. // an integer.
  116. // _power_ref_mut.var_mut();
  117. }
  118. {
  119. let mut power_ref_mut = list.get_mut(0);
  120. println!("Expression evaluates to {}", power_ref_mut.eval());
  121. power_ref_mut.var_mut().value = 5.0;
  122. println!("Changed variable to 5.0");
  123. println!("Now expression evaluates to {}", power_ref_mut.eval());
  124. }
  125. }
Add Comment
Please, Sign In to add comment