Stream: API design

Topic: ✔ and_then


view this post on Zulip Richard Feldman (Jul 11 2026 at 16:01):

I'd like to see some motivating examples from real code :smile:

view this post on Zulip Richard Feldman (Jul 11 2026 at 16:02):

I'm in general hesitant to add new language syntax or operators for the sake of consistency in the abstract - as opposed to being motivated by pain points in real application or library code

view this post on Zulip Johannes Rubenz (Jul 11 2026 at 16:20):

Sure! :grinning_face_with_smiling_eyes:
So I wrote a little web app with some HTTP handlers like AddProject or ToggleProjectStatus.

What we had was a lot of hand-threading the error through each step – notice the repeated Err(e) => Err(e):

run! = |body| {
    projects = Store.load_projects!()
    target_project_id = Params.parse_post_body(Str.from_utf8_lossy(body), "id")

    validated_id = match target_project_id {
        Ok(id) => U64.from_str(id).map_err(|_| MalformedBody)
        Err(e) => Err(e)
    }

    attempted_target_project = match validated_id {
        Ok(id) => Project.find_by_id(projects, id)
        Err(e) => Err(e)
    }

    match attempted_target_project {
        Ok(p)    => ... # toggle status, save, redirect
        Err(err) => Respond.respond_with(422, view(projects, ShowMessage(Project.validation_error_to_str(err))))
    }
}

What I would have liked is to collapse that threading into a small pipeline (and_then is the little helper from my first message):

attempted_target_project =
    Params.parse_post_body(Str.from_utf8_lossy(body), "id")
    -> and_then(|id_str| U64.from_str(id_str).map_err(|_| MalformedBody))
    -> and_then(|id| Project.find_by_id(projects, id))

match attempted_target_project {
    Ok(p)    => ... # toggle status, save, redirect
    Err(err) => Respond.respond_with(422, view(projects, ShowMessage(Project.validation_error_to_str(err))))
}

Why not ?...? Hmm, the handler returns an HTTP Response, not a Try, so I can't use ? at the top of run! (wrong return type). I can lift the three steps into a separate Try-returning helper and use ? in there, then match on the result, and that works fine. So I'd argue the inline pipeline just read a bit nicer to me than adding a helper whose only job is to host the ?s. But maybe that's not enough to justify anything, though...:laughing:

view this post on Zulip Richard Feldman (Jul 11 2026 at 18:49):

Johannes Rubenz said:

I can lift the three steps into a separate Try-returning helper and use ? in there, then match on the result, and that works fine. So I'd argue the inline pipeline just read a bit nicer to me than adding a helper whose only job is to host the ?s. But maybe that's not enough to justify anything, though...:laughing:

yeah I think the helper that returns Try is the way to go! :smiley:

view this post on Zulip Notification Bot (Jul 12 2026 at 11:19):

Johannes Rubenz has marked this topic as resolved.


Last updated: Jul 23 2026 at 13:15 UTC