Skip to content

← Modules, Visibility, Testing and Docs step 3 of 22

Easy Primitives

Expose a small module API

The ratio module already contains the calculation. Your task is to expose the type and methods that callers need while keeping its fields private.

Required behavior

Keep this function at the crate root:

pub fn parse_ratios(pairs: Vec<(i64, i64)>) -> Vec<Option<f64>>

Each pair is (numerator, denominator). Return one result per pair, preserving order and duplicates:

  • A zero denominator produces None, including for (0, 0).
  • Otherwise, convert each integer to f64, divide the converted numerator by the converted denominator, and return Some(result).
  • Empty input produces an empty vector.

For [(1, 2), (7, -2), (0, 5), (1, 0)], return [Some(0.5), Some(-3.5), Some(0.0), None]. The harness represents None as JSON null.

This is floating-point division, not integer division followed by a cast. Large i64 values may lose precision when converted to f64, and fractions such as 1 / 3 are rounded. The function does not produce an exact rational representation. Converting before division also avoids overflowing integer division for i64::MIN / -1.

Expose the intended interface

Inside ratio, make these three items public:

  • The Ratio struct, keeping num: i64 and den: i64 private.
  • Its associated constructor, pub fn new(num: i64, den: i64) -> Option<Self>.
  • Its method, pub fn value(&self) -> f64.

The constructor must reject zero denominators. parse_ratios then uses Option::map to call value only when construction succeeds.

The ratio module itself can remain private: its parent, the crate root, can access a module declared there. Making the fields public would not replace the need to expose the type and methods used by the caller.

Read the privacy errors

The starter's struct and methods are private. Accessing ratio::Ratio from the parent produces E0603; calling its private new and value methods produces E0624. Use the named item in each diagnostic to identify the visibility that needs changing.

Most items are private by default, with exceptions such as enum variants and items declared in traits. Struct fields have their own visibility: pub struct Ratio does not expose num or den.

Privacy follows the module hierarchy, not file boundaries. A private item is accessible in its declaring module and descendants. A parent cannot access private items declared inside its child. Public items also need an accessible path; public re-exports can supply another path through the module hierarchy.

Preserve the nonzero-denominator invariant

Private fields prevent callers outside ratio and its descendants from directly constructing or changing the stored numerator and denominator. They can use the public constructor, which performs the check. Struct update syntax does not bypass those private-field checks.

The compiler enforces access restrictions, not the arithmetic rule itself. Code inside ratio and its descendants can still construct a zero denominator. Every constructor or mutating method the module exposes must preserve the invariant. A future Default implementation would also need to return a valid value.

The supplied output tests check numerical behavior. They cannot establish whether the fields remain private: a public-field version could produce identical outputs. Keep the fields private as part of this exercise's API requirement.