1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-03-20 14:31:15 +02:00

Remove error handling from expression evaluation exercise (#2517)

I think it would be good to simplify the expression evaluation exercise
by removing the error handling around the divide-by-zero case. I think
it overcomplicates the exercise and and adds confusion since at this
point we haven't introduced `Result` (or at least not in any detail).
This allows the students to just focus on writing the pattern matches on
`Expression` and `Op`, and allows the exercise to be shorter (and I
think we need to free up some time where we can, my classes often run
long and cut into how much time students have for exercises).
This commit is contained in:
Nicole L 2024-12-16 13:36:27 -08:00 committed by GitHub
parent f60513ebe2
commit 2bae363d16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 14 additions and 43 deletions

View File

@ -1,5 +1,5 @@
--- ---
minutes: 30 minutes: 20
--- ---
# Exercise: Expression Evaluation # Exercise: Expression Evaluation
@ -57,11 +57,6 @@ 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: To evaluate a boxed expression, use the deref operator (`*`) to "unbox" it:
`eval(*boxed_expr)`. `eval(*boxed_expr)`.
Some expressions cannot be evaluated and will return an error. The standard
[`Result<Value, String>`](https://doc.rust-lang.org/std/result/enum.Result.html)
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.
Copy and paste the code into the Rust playground, and begin implementing `eval`. Copy and paste the code into the Rust playground, and begin implementing `eval`.
The final product should pass the tests. It may be helpful to use `todo!()` and The final product should pass the tests. It may be helpful to use `todo!()` and
get the tests to pass one-by-one. You can also skip a test temporarily with get the tests to pass one-by-one. You can also skip a test temporarily with

View File

@ -38,39 +38,27 @@ enum Expression {
// ANCHOR_END: Expression // ANCHOR_END: Expression
// ANCHOR: eval // ANCHOR: eval
fn eval(e: Expression) -> Result<i64, String> { fn eval(e: Expression) -> i64 {
// ANCHOR_END: eval // ANCHOR_END: eval
match e { match e {
Expression::Op { op, left, right } => { Expression::Op { op, left, right } => {
let left = match eval(*left) { let left = eval(*left);
Ok(v) => v, let right = eval(*right);
Err(e) => return Err(e), match op {
};
let right = match eval(*right) {
Ok(v) => v,
Err(e) => return Err(e),
};
Ok(match op {
Operation::Add => left + right, Operation::Add => left + right,
Operation::Sub => left - right, Operation::Sub => left - right,
Operation::Mul => left * right, Operation::Mul => left * right,
Operation::Div => { Operation::Div => left / right,
if right == 0 { }
return Err(String::from("division by zero"));
} else {
left / right
}
}
})
} }
Expression::Value(v) => Ok(v), Expression::Value(v) => v,
} }
} }
// ANCHOR: tests // ANCHOR: tests
#[test] #[test]
fn test_value() { fn test_value() {
assert_eq!(eval(Expression::Value(19)), Ok(19)); assert_eq!(eval(Expression::Value(19)), 19);
} }
#[test] #[test]
@ -81,7 +69,7 @@ fn test_sum() {
left: Box::new(Expression::Value(10)), left: Box::new(Expression::Value(10)),
right: Box::new(Expression::Value(20)), right: Box::new(Expression::Value(20)),
}), }),
Ok(30) 30
); );
} }
@ -107,7 +95,7 @@ fn test_recursion() {
left: Box::new(term1), left: Box::new(term1),
right: Box::new(term2), right: Box::new(term2),
}), }),
Ok(85) 85
); );
} }
@ -119,7 +107,7 @@ fn test_zeros() {
left: Box::new(Expression::Value(0)), left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0)) right: Box::new(Expression::Value(0))
}), }),
Ok(0) 0
); );
assert_eq!( assert_eq!(
eval(Expression::Op { eval(Expression::Op {
@ -127,7 +115,7 @@ fn test_zeros() {
left: Box::new(Expression::Value(0)), left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0)) right: Box::new(Expression::Value(0))
}), }),
Ok(0) 0
); );
assert_eq!( assert_eq!(
eval(Expression::Op { eval(Expression::Op {
@ -135,19 +123,7 @@ fn test_zeros() {
left: Box::new(Expression::Value(0)), left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0)) right: Box::new(Expression::Value(0))
}), }),
Ok(0) 0
);
}
#[test]
fn test_error() {
assert_eq!(
eval(Expression::Op {
op: Operation::Div,
left: Box::new(Expression::Value(99)),
right: Box::new(Expression::Value(0)),
}),
Err(String::from("division by zero"))
); );
} }
// ANCHOR_END: tests // ANCHOR_END: tests