1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
///|
/// 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
}
|