///| /// A shape that knows its own area. pub(open) trait Area { fn area(Self) -> Double } ///| /// A circle, by its radius. pub(all) struct Circle { radius : Double } derive(Eq, Debug) ///| /// A rectangle, by its two sides. pub(all) struct Rect { width : Double height : Double } derive(Eq, Debug) ///| pub impl Area for Circle with fn area(self) { 3.141_592_653_589_793 * self.radius * self.radius } ///| pub impl Area for Rect with fn area(self) { self.width * self.height } ///| pub impl Show for Circle with fn output(self, logger) { logger.write_string("Circle(r=\{self.radius})") } ///| pub impl Show for Rect with fn output(self, logger) { logger.write_string("Rect(\{self.width}×\{self.height})") } ///| /// Raised when a measurement is asked of nothing at all. pub suberror NoShapes ///| /// total adds up the areas of every shape given. /// /// It is generic over anything that implements `Area`, so one function serves /// circles, rectangles and whatever else somebody adds later. pub fn[T : Area] total(shapes : Array[T]) -> Double raise NoShapes { guard shapes.length() > 0 else { raise NoShapes } let mut sum = 0.0 for shape in shapes { sum = sum + shape.area() } sum } ///| /// largest returns the shape with the greatest area, or None for an empty list. pub fn[T : Area] largest(shapes : Array[T]) -> T? { let mut best : T? = None for shape in shapes { match best { None => best = Some(shape) Some(current) => if shape.area() > current.area() { best = Some(shape) } } } best }