Monday, October 03, 2022

Into ZAMs

Previously I wrote about using Zero Arguments Methods (ZAMs) as a work-around for the Rust programming language not yet supporting named arguments.  Here I show how an Into trait implementation can be used as a ZAM.  I start from a conventional unnamed arguments function that I gradually convert into an Into ZAM.

Start with an output structure for your calculation:

pub struct RotationMatrix {
  pub rows: [[f64; 3]; 3],
}

Make an associated function that takes in a number of unnamed arguments, performs the calculations, and then returns the result as the output structure.

let rotation_matrix: RotationMatrix
  = RotationMatrix::from_degrees(-45.0, 90.0, 135.0);

Next, to support named arguments, modify your associated function to accept an input structure as the sole argument:

pub struct RotationDegrees {
  pub x: f64,
  pub y: f64,
  pub z: f64,
}

let rotation_matrix: RotationMatrix
  = RotationMatrix::from_degrees(
    RotationDegrees {
      x: -45.0,
      y: 90.0,
      z: 135.0,
    });

To make a ZAM, you could move the calculation code from an associated function on the output structure to a method on the input structure:

let rotation_degrees = RotationDegrees {
  x: -45.0,
  y: 90.0,
  z: 135.0,
};

let rotation_matrix: RotationMatrix
  = rotation_degrees.to_rotation_matrix();

Instead, however, move the calculation code to a From trait implementation:

impl From<RotationDegrees> for RotationMatrix {
  fn from(rotation_degrees: RotationDegrees) -> Self {
    // [...]
  }
}

let rotation_matrix: RotationMatrix
  = RotationMatrix::from(rotation_degrees);

Implementing the From trait automatically implements the Into trait which now serves as your ZAM:

let rotation_matrix: RotationMatrix
  = rotation_degrees.into();