What to name functions that encapsulate destructuring and call callbacks?

I have a few functions in my 7GUIs implementation that are named map[Something] but which clearly do not map in the usual sense. The general idea behind all the functions is that they encapsulate the destructuring logic for a data structure and call callbacks when one of the patterns match. I would like to get your advice on renaming them appropriately.

Examples

I’ve definitely found this approach useful but naming is hard so your help will be greatly appreciated.

1 Like

To me, those functions looks like case-of in disguise.

Instead of:

mapBooking :
    { onOneWay : Date -> a
    , onReturn : Date -> Date -> a
    , default : a
    }
    -> Booking
    -> a
mapBooking { onOneWay, onReturn, default } { flight, start, end } =
    case ( flight, start, end ) of
        ( OneWay, Valid startDate, _ ) ->
            onOneWay startDate

        ( Return, Valid startDate, Valid endDate ) ->
            onReturn startDate endDate

        _ ->
            default


isBookable : Booking -> Bool
isBookable =
    mapBooking
        { onOneWay = always True
        , onReturn =
            \startDate endDate ->
                endDate |> Date.isLaterThan startDate
        , default = False
        }

I would do something like this:

-- Not sure about the names
type ValidBooking
    = ValidOneWay Date
    | ValidReturn Date Date
    | Invalid


-- needs better name than `foo` :)
foo : Booking -> ValidBooking
foo { flight, start, end } =
    case ( flight, start, end ) of
        ( OneWay, Valid startDate, _ ) ->
            ValidOneWay startDate

        ( Return, Valid startDate, Valid endDate ) ->
            ValidReturn startDate endDate

        _ ->
            Invalid


isBookable : Booking -> Bool
isBookable booking =
    case foo booking of
        ValidOneWay _ ->
            True

        ValidReturn startDate endDate ->
            endDate |> Date.isLaterThan startDate

        Invalid ->
            False

I see the idea. Convert the Booking to another data structure that encodes the alternative structure I would want to pattern match over. My way uses functions and your way uses a data structure so it’s a sort of defunctionalization transformation. So what you suggest is another side of the same coin.

I don’t like the name ValidBooking though since it has within it a constructor named Invalid.

But the main question remains: What to name the functions?

One low-hanging improvement would be using a Maybe/Result instead

module Booking exposing (ValidBooking(..), toValid, ...)

type ValidBooking
    = ValidOneWay Date
    | ValidReturn { start : Date, end : Date }


toValid : Booking -> Maybe ValidBooking
toValid booking =
    case ( booking.flight, booking.start, booking.end ) of
        ( OneWay, Valid startDate, _ ) ->
            ValidOneWay startDate |> Just

        ( Return, Valid startDate, Valid endDate ) ->
            ValidReturn { start = startDate, end = endDate } |> Just

        _ ->
            Nothing

For isBookable I’d just case on the |> toValid or if you really need a bool use |> toValid |> Maybe.Extra.isJust

1 Like

@lydell and @lue-bird thanks for the alternative implementation ideas.

As for the naming, I think I’ve settled on withBooking, withSelection, withSelected, and withCell.

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.