| In some languages, especially many ahead-of-time compiled languages, this will be a part of the signature so that it’s at least much more difficult to get wrong¹. In Rust, for example: • `fn filter(self, P²) -> A` consumes self and returns a new thing of type A; • `fn filter(&mut self, P)` mutates in-place; • `fn filter(&self, P) -> B<'_>` doesn’t mutate self, but produces a new thing of type B containing references to the contents of self. As a concrete example, Rust has `Vec::retain(&mut self, P)` to filter a list/array in place, and `Iterator::filter(self, P) -> Filter<Self, P>` to filter an iterator, consuming that iterator object and wrapping it in another. This is a sterling example of the point of the original article: Rust pushes you to thinking about ownership, and it’s really great and I miss it when working in other languages, where I have to stop and think whether I’m allowed to mutate this object or whether I should make a copy, and the cost of getting it wrong is bad performance in one direction and bugs that can be a nightmare to diagnose in the other direction. —⁂— ¹ You need linear types to make it just about impossible to get wrong by accident. Rust has a weaker substitute that you can annotate functions with, #[must_use], which says “warn the user if they neglect to use the return value, because they’re almost certainly doing the wrong thing”. ² I’ve omitted the filter predicate P from the signatures to reduce distraction; in each case it’d probably be something like `<P: FnMut(&Self::Item) -> bool>`: a function that is passed a reference to an item and returns true or false. |