Skip to content

Consider adding builder methods that take Options #115

Open
@Jayonas

Description

@Jayonas

In general the new API in 0.11 works nicely, but one pain point I had was mapping Option<Foo> values (which I either calculate on the fly or have stored in a data structure) to optional builder method calls. For example, I'll have an expression which results in an Option<&str> for the origin of a Snippet, where None means that it won't have one. This worked great in the 0.10.x API because I could just assign my value to the relevant field of the annotate-snippets data structure, since it was also an Option. In the new 0.11.1 API I now either need to call Snippet.origin(...) (if my value is Some) or not call it (if my value is None), which really breaks the nice ergonomics of chaining all of the needed builder method calls.

For example:

let mut snippet = Snippet::source(buffer)
    .line_start(1)
    .fold(true)
    .annotations(...)
;
if let Some(origin) = my_optional_origin_expression {
    snippet = snippet.origin(origin);
}

Consider the potential improvement if there was a builder method that took an Option:

Snippet::source(buffer)
    .line_start(1)
    .fold(true)
    .annotations(...)
    .maybe_origin(my_optional_origin_expression)

Now the entire thing is a single expression -- which could e.g. be passed straight to another builder function -- instead of requiring a temporary mutable variable and conditional logic.

It's also interesting to consider the inconsistency with the Snippet::fold method, which doesn't have this problem. I can have a bool value (or expression) that controls whether folding should be enabled or disabled and pass it straight to fold rather than needing logic to either call fold (in the true case) or not call it (in the false) case. If fold were consistent with the other builder methods as they currently are, then it would take no parameters and always turn folding on when called. To be clear, though, I'm not advocating that you should change fold to be that way; I'm actually advocating the opposite, that you change the other builder methods (or add additional ones) for consistency with how fold currently is, i.e. allow them to be used to explicitly specify the default value.

My workaround for this was to make little extension traits and add my own maybe_* versions of relevant builder methods (so far just Snippet::maybe_origin and Annotation::maybe_label). While that's an entirely technically valid solution, I feel like there's a pretty good chance that such builder methods would end up being used often enough as to warrant their inclusion in the crate's API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-enhancementCategory: enhancementM-breaking-changeMeta: Implementing or merging this will introduce a breaking change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions