Skip to content

The parameter ordering of Option::map_or_else is unintuitive. #1025

Closed
@abonander

Description

@abonander

The signature of Option<T>::map_or_else is as follows:

fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -> U

This is highly unintuitive as the two closure parameters are in the reverse order of that suggested by the function's name. This means that anyone who tries to invoke it from memory, including myself earlier today, is going to run into a compiler error on the first try.

Example:

let first_word_letter_count = "hello world".words().next().map_or_else(
    |word| word.len(),
    || 0
);

The above makes sense, logically. If the value is there, map it and return the result. Otherwise (implying a secondary operation), call a closure which will produce a substitute value. Even the documentation supports this logical progression:

Applies a function to the contained value or computes a default.

However, trying to invoke the method this way will result in a compiler error because the no-arg closure is required to be first. The particular reasoning behind this design is not given, but I have found precedent in Haskell's maybe function:

maybe :: b -> (a -> b) -> Maybe a -> b

However, I don't think Haskell's intuition for parameter ordering can extend to Rust because Rust doesn't have currying, partial application, or (global) lazy evaluation. And even in Haskell the ordering isn't necessarily intuitive.

I am aware that this method and Option itself have both been marked as Stable. However, I believe minor unintuities like this add up and ultimately reflect poorly on the user experience of the language as a whole, and should be addressed before Rust hits 1.0.

I would like to note that I am willing to apply the effort to adjust this myself, as it's relatively trivial. However, because it's trivial, I am not sure if it requires an RFC or just a general community agreement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions