We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 3 of 26
Convert distances with tuple and unit structs
Repair the feet-to-metres conversion in this function:
pub fn normalise_distances(values: Vec<f64>, units: Vec<String>) -> Vec<f64>
Pair each value with the unit at the same position and return converted values in that order. Stop at the shorter vector. If either input is empty, return an empty vector.
| Unit string | Conversion |
|---|---|
m |
Keep the value |
ft |
Multiply by 0.3048 |
| Anything else | Return 0.0 for that pair |
Match unit strings exactly. Uppercase or whitespace-padded strings are unrecognized. Negative measurements are allowed and retain their sign for recognized units. Inputs are finite floating-point values. Return the computed values without extra rounding; grading uses a numeric tolerance.
For example, values [10.0, -3.0, 8.0] with units ["m", "ft", "yd"]
produce [10.0, -0.9144, 0.0]. One foot is defined as 0.3048 metres, but
storing that factor and multiplying in f64 involves floating-point rounding.
The starter already handles pairing, unknown units and collecting the
results. Fix the field access inside From<Feet> for Meters while keeping
the provided types and conversion structure.
Tuple structs give values distinct types
struct Meters(f64);
struct Feet(f64);
These are two distinct types, each containing one f64 field. This use of
a single-field wrapper is called the newtype pattern. A function expecting
Meters cannot directly accept Feet, even though their fields have the
same numeric type.
Fields in tuple structs are numbered. Read the first field as feet.0.
The starter uses feet.value, but no field named value exists, so it
fails with E0609.
The types prevent an accidental interchange at typed call sites. They do not verify the conversion factor, reject negative values, or validate the incoming unit strings automatically. Those behaviors come from your code. The default struct representation also supplies no general foreign-function ABI promise; a type distinction and a layout guarantee are separate matters.
From also supplies Into in the same direction
Implementing From<Feet> for Meters supports both
Meters::from(feet) and feet.into() when the destination type is known.
Both convert feet to metres. Neither supplies the reverse conversion.
In this exercise the implementation reads feet.0, multiplies it by the
factor and constructs Meters from the result.
A unit struct represents the fallback case
struct Unknown;
Unknown has no fields and its size is zero. It is still a distinct type
that can have methods and trait implementations. Here its From conversion
produces Meters(0.0).
Zero-sized does not mean every use of a type has zero runtime cost: methods and trait implementations can do work. This particular conversion simply creates the fallback value.
Mapping an unrecognized unit to zero is this exercise's policy. It loses
the distinction between an unknown unit and a real zero-length measurement;
another API might preserve that information in a Result or enum.
Constructors and patterns
A tuple-struct constructor can be passed to an iterator's map:
let raw = vec![1.0, 2.0];
let metres: Vec<Meters> = raw.into_iter().map(Meters).collect();
assert_eq!(metres[0].0, 1.0);
It is callable like a function that accepts the fields and builds the struct.
A closure such as |value| Meters(value) has the same construction behavior.
A pattern extracts the field again:
let converted = Meters::from(Feet(10.0));
let Meters(value) = converted;
assert!((value - 3.048).abs() < 1e-12);
The starter uses this pattern to return plain f64 values after conversion.
Submissions must compile, pass the cases and pass the Rust Clippy gate.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.