练习:表达式求值

Let’s write a simple recursive evaluator for arithmetic expressions.

The Box type here is a smart pointer, and will be covered in detail later in the course. An expression can be “boxed” with Box::new as seen in the tests. To evaluate a boxed expression, use the deref operator (*) to “unbox” it: eval(*boxed_expr).

Some expressions cannot be evaluated and will return an error. The standard Result type is an enum that represents either a successful value (Ok(Value)) or an error (Err(String)). We will cover this type in detail later.

将代码复制粘贴到 Rust Playground,然后开始实现 eval。最终结果应能通过测试。使用 todo!() 并使测试逐个通过可能会很有帮助。您还可以使用 #[ignore] 暂时跳过测试:

1. #[test]
2. #[ignore]
3. fn test_value() { .. }

If you finish early, try writing a test that results in division by zero or integer overflow. How could you handle this with Result instead of a panic?

1. #![allow(unused)]
2. fn main() {
3. /// An operation to perform on two subexpressions.
4. #[derive(Debug)]
5. enum Operation {
6. Add,
7. Sub,
8. Mul,
9. Div,
10. }

12. /// An expression, in tree form.
13. #[derive(Debug)]
14. enum Expression {
15. /// An operation on two subexpressions.
16. Op { op: Operation, left: Box<Expression>, right: Box<Expression> },

18. /// A literal value
19. Value(i64),
20. }

22. fn eval(e: Expression) -> Result<i64, String> {
23. todo!()
24. }

26. #[test]
27. fn test_value() {
28. assert_eq!(eval(Expression::Value(19)), Ok(19));
29. }

31. #[test]
32. fn test_sum() {
33. assert_eq!(
34. eval(Expression::Op {
35. op: Operation::Add,
36. left: Box::new(Expression::Value(10)),
37. right: Box::new(Expression::Value(20)),
38. }),
39. Ok(30)
40. );
41. }

43. #[test]
44. fn test_recursion() {
45. let term1 = Expression::Op {
46. op: Operation::Mul,
47. left: Box::new(Expression::Value(10)),
48. right: Box::new(Expression::Value(9)),
49. };
50. let term2 = Expression::Op {
51. op: Operation::Mul,
52. left: Box::new(Expression::Op {
53. op: Operation::Sub,
54. left: Box::new(Expression::Value(3)),
55. right: Box::new(Expression::Value(4)),
56. }),
57. right: Box::new(Expression::Value(5)),
58. };
59. assert_eq!(
60. eval(Expression::Op {
61. op: Operation::Add,
62. left: Box::new(term1),
63. right: Box::new(term2),
64. }),
65. Ok(85)
66. );
67. }

69. #[test]
70. fn test_error() {
71. assert_eq!(
72. eval(Expression::Op {
73. op: Operation::Div,
74. left: Box::new(Expression::Value(99)),
75. right: Box::new(Expression::Value(0)),
76. }),
77. Err(String::from("division by zero"))
78. );
79. }
80. }