KarthikRIyer / swiftplot

Swift library for Data Visualization :bar_chart:
Apache License 2.0
398 stars 36 forks source link

Brainstorm solutions to the 'farmer problem' #118

Open karwa opened 4 years ago

karwa commented 4 years ago

There is a bit of API awkwardness when making plots for arbitrary data types, which came up during the review for #116 (CC @odmir). Consider the following example (using a generic bargraph). We want a bargraph of people by their height, with the formatter giving us access to full Person objects from which we can get the name:

struct Person {
  var name: String
  var height: Int
}

let people: [Person] = //...

Copying out the heights isn't great:

let heights = people.map { person in person.height }
var graph = BarGraph(heights) // This is now a BarGraph<[Int]>
graph.xAxisFormatter = { person in // how do we get a `Person` from an `Int`?
  return person.name
}

The same problem applies to lazy-maps and other generic collection transformations.

IMO, the problem is that typical generic collection transformations want to appear as collections of their target values - i.e. people.lazy.map { person in person.height } "is" a collection of Ints, and it loses all information about where that Int came from (in this case, the Person whose height it is).

For many use-cases, that's fine. For our case, we don't just want to be a graph of integers - we want to preserve the providence information. We want that BarGraph to be "a collection of Ints that are each associated with a Person".