hrldcpr / pcollections

A Persistent Java Collections Library
Other
765 stars 79 forks source link

add a utility method for deep conversion from java collections #89

Open viebel opened 3 years ago

viebel commented 3 years ago

Thank you for this great library that makes good stuff from Clojure available to Java developers.

In the context of my book Data-Oriented programming, I am considering to use pcollections to illustrate to Java developers the power of data immutability when building a software system.

A fundamental principle of Data-Oriented programming is to represent data with generic immutable data structures instead of instances of classes.

As an example, a book in a library management system (that's the example I use in the book) is represented with a nested map combining maps and lists:

Map watchmen = Map.of(
                      "isbn", "978-1779501127",
                      "title", "Watchmen",
                      "publicationYear", 1987,
                      "authors", List.of("alan-moore", "dave-gibbons"),
                      "bookItems", List.of(
                                           Map.of(
                                                  "id", "book-item-1",
                                                  "rackId", "rack-17",
                                                  "isLent", true
                                                  ),
                                           Map.of (
                                                   "id", "book-item-2",
                                                   "rackId", "rack-17",
                                                   "isLent", false
                                                   )
                                           )
                      );

Now, I'd like to represent the same data as an immutable collection.

The only way I found to recursively convert my nested map into persistent collection is by explicitly converting every map and list.

Map watchmen = HashTreePMap.from(Map.of(
                      "isbn", "978-1779501127",
                      "title", "Watchmen",
                      "publicationYear", 1987,
                      "authors", TreePVector.from(List.of("alan-moore", "dave-gibbons")),
                      "bookItems", TreePVector.from(List.of(
                                           HashTreePMap.from(Map.of(
                                                  "id", "book-item-1",
                                                  "rackId", "rack-17",
                                                  "isLent", true
                                                  )),
                                           HashTreePMap.from(Map.of(
                                                   "id", "book-item-2",
                                                   "rackId", "rack-17",
                                                   "isLent", false
                                                   ))
                                           ))
                      ));

Two questions:

  1. Is there a way to make this conversion less verbose?
  2. Is there a way to recursively converts a map into a pmap?
hrldcpr commented 3 years ago

Hey thanks for the question. Currently HashTreePMap and TreePVector only have singleton() convenience methods, nothing for more entries.

I think adding multi-entry methods a la Map.of and List.of is a good idea, so I've opened an issue specifically for that #90 (PRs welcome!)

As for automatically converting nested maps, I'm less certain if that warrants being built in to the library, so I'll close this for now but feel free to argue for it being reopened 😉

Sorry that functionality isn't already in the library, good luck with your project!

viebel commented 3 years ago

Thank you @hrldcpr.

Regarding converting nested maps, do you think it's feasible to write code that does that? What would it take? Probably kind of dynamic castings to check whether an entry is a collection or not? Am I correct?

On a related note: what would it take to parse a (deeply nested JSON) into a pcollection?

hrldcpr commented 3 years ago

Yeah I guess in both cases you'd write a recursive function, something like PCollection deepCopy(Collection c) which checks the type of c to decide what type of PCollection to make, then iterates through the elements of c adding them to the new PCollection—but calling deepCopy first if the element is a Collection, otherwise just adding it directly

Wouldn't be that much code, just a case for each collection type (List, Map, Set). I guess given the popularity of JSON maybe this is a useful thing to have built-in to the library… So I'll rename this issue accordingly. To be honest though I probably won't get to it any time soon, but I'll mark it as "good first issue" and maybe someone else will!

viebel commented 3 years ago

That makes sense. Thank you!