It depends on the context. Do each of your items make sense as part of a homogeneous collection, or are they meant to be used separately?
For example say I need to find the arc that passes through three points, the arc's start
and end
points, and some random point along the arc that isn't an endpoint.
I'd keep the arguments separate:
fn calculate_arc(start: Point, end: Point, middle: Point) -> Arc { ... }
But say I'm calculating the smallest rectangle that can fit around a pentagon. For all intents and purposes, I don't care whether a point is the 2nd or 4th corner, just that it's a point.
In this case the points don't have any individual significance or meaning, so I'd pass them in using some homogeneous collection (i.e. array/slice). I would prefer a slice over an array because that lets me reuse the same function for any number of points (a line, triangle, dynamically sized polyline, point cloud, etc.).
struct BoundingBox { ... }
fn bounding_box_for_points(points: &[Point]) -> BoundingBox {
let mut bounding_box = BoundingBox::empty();
for point in points {
bounding_box = bounding_box.merged_with(point);
}
bounding_box
}
Accepting a slice does require you to already have the items in an array or Vec
(or that you copy them to a temporary one for the calculation), but if items don't have individual meaning you're probably storing them that way anyway.