Skip to content

RFC: Renaming (or removing) the <| family of operators #479

Description

@gfontenot

I'd like to think about at least renaming, or maybe even removing, the <| family of operators in Argo. I think this falls in line with the goals for the (theoretical) next release of Argo, where we're going to be renaming large parts of the lib in order to remove ambiguity or clarify library intent (see #474 and #473). There are a couple of reasons for renaming these operators:

  1. When we first designed Argo, we were unaware of the prior art of using <| for right-to-left function application in languages like F#. Since becoming aware of this, I've seen |> used more and more for left-to-right function application, and the fact that our operator conflicts with this existing expectation bothers me, and seems like it could lead to confusion.
  2. Using an operator for extracting values from JSON instances can to some fairly gnarly code that's really hard to read. Many times, this is due to ambiguous precedence between all of the different operators needed to fully implement a non-trivial decoder.
  3. The <| is incredibly specialized, and only really works with the shape JSON -> String -> Decoded<T>. This means its use is limited, and could probably be replaced by a method on JSON itself.

I'd propose making the drastic change of removing the <| family of operators in the next release of Argo in favor of a named method (JSON.extract). For the sake of discussion, here's a sample of the before/after for one of our decode methods in our test suite:

// before
extension User: Argo.Decodable {
  static func decode(_ json: JSON) -> Decoded<User> {
    return curry(self.init)
      <^> json <| "id"
      <*> (json <| ["userinfo", "name"] <|> json <| "name")
      <*> json <|? "email"
  }
}

// after

extension User: Argo.Decodable {
  static func decode(_ json: JSON) -> Decoded<User> {
    return curry(self.init)
      <^> json.extract("id")
      <*> json.extract(["userinfo", "name"]) <|> json.extract("name")
      <*> json.extractOpt("email")
  }
}

The optional method name is an interesting problem to need to solve, I'm not confident that extractOpt is the right choice there. I'd love to do extract? but that's not valid swift. Also, of note: this will be made simpler by the fact that with Swift 4.1 (which we should target for these changes) we'll be able to remove the collection operators (<||) from the lib anyway.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions