Thanks! And if we were to add a Collectable.empty, what would be its implementation for Scrivener.Page?
*José Valim* www.plataformatec.com.br Skype: jv.ptec Founder and Director of R&D On Tue, May 21, 2019 at 7:15 PM Benjamin Milde <[email protected]> wrote: > Take for example https://github.com/drewolson/scrivener_ecto > > With a current version of ecto you can happily do this: > > ``` > Repo.all(query) |> Repo.preload(:user) > Repo.one(query) |> Repo.preload(:user) > ``` > > but not this: > > ``` > Repo.paginate(query) |> Repo.preload(:user) > ``` > > Given that doing some work on results of db calls is quite common I tend > to end up with lot's of functions pattern matching if results are > `%Scrivener.Page{}`, a list or an element. Say you also use > https://github.com/duffelhq/paginator for infinite scrolling pages you > might end up with yet another "collection" type struct, which implements > Enumerable so displaying items in views is super easy, but with no simple > solution on how to handle preloads or mappings. > > I've also tried using `Map.update!(elements, :key_of_items, function)` to > normalize stuff down to handling lists for those places using pagination, > but now I'm wrapping a lot of computation in those updates. > > It's also not just mapping, but I might also e.g. want to intersperse > items with separators or zip some additional data into the resultset and > still not lose the pagination information attached to those entries. > > My naive approach was that I can already use Collectable to fill items > back into lists as well as those pagination structs, but while for list and > maps it's easy to use `Enum.into([])` or `Enum.into(%{})` it's not as easy > to get a hold of an empty version of one of those pagination structs. > > I'm not super into all the theoretic types in functional programming. I > think I understand what a functor is, but I'm also not super certain I > understand what you're pointing at. > > Am Dienstag, 21. Mai 2019 18:36:54 UTC+2 schrieb José Valim: >> >> > All the pagination libs I know for ecto return structs with additional >> metadata besides the actual results of the db query. Currently one needs to >> build around those structs specifically to be able to do preloads or other >> mapping operations or one would loose the metadata. >> >> Can you please provide an example? I am just trying to full understand >> the problem. :) >> >> > Having a `SomeProtocol.empty` protocol we could still use everything >> provided by Enum (even with it returning a list), but have a way to replace >> items in the container with the new modified ones >> >> Wouldn't a functor be better suited then? >> >> >> *José Valim* >> www.plataformatec.com.br >> Skype: jv.ptec >> Founder and Director of R&D >> >> >> On Tue, May 21, 2019 at 6:34 PM Benjamin Milde <[email protected]> >> wrote: >> >>> All the pagination libs I know for ecto return structs with additional >>> metadata besides the actual results of the db query. Currently one needs to >>> build around those structs specifically to be able to do preloads or other >>> mapping operations or one would loose the metadata. Having a >>> `SomeProtocol.empty` protocol we could still use everything provided by >>> Enum (even with it returning a list), but have a way to replace items in >>> the container with the new modified ones without manually pattern matching >>> between single results, lists of results or structs returned because one >>> happens to be using pagination. Monadic collection types basically don't do >>> it much differently. Extract the subject out of the container, do >>> computation and replace the old value when done. I'd imagine `Enumerable` >>> and the potential `SomeProtocol` would solve a lot of usecases, where >>> people usually ask for Enum to retain the outer collection type. >>> >>> Am Dienstag, 21. Mai 2019 18:14:49 UTC+2 schrieb José Valim: >>>> >>>> My concern is that Collectable.empty cannot be implemented by all >>>> structs. For example, what does it mean to call empty() on a IO.stream? >>>> Perhaps it would make sense as a separate protocol? >>>> >>>> Also, can you please expand on how Repo.preload could use >>>> Scrivener.Page in detail? Thanks! >>>> >>>> >>>> *José Valim* >>>> www.plataformatec.com.br >>>> Skype: jv.ptec >>>> Founder and Director of R&D >>>> >>>> >>>> On Tue, May 21, 2019 at 5:46 PM Benjamin Milde <[email protected]> >>>> wrote: >>>> >>>>> I've had quite often needs for doing some computation (mapping) on >>>>> ecto result, but having a flexible function similar to `Repo.preload` >>>>> currently needs a whole bunch of boilerplate in terms of differenciating >>>>> collections from single items and especially returning the same type >>>>> afterwards (e.g. keep it a collection or single item). I know that >>>>> Enumerable and Collectable were split consciously, but it would be great >>>>> to >>>>> have something like `Collectable.empty/1`, so one could do some work using >>>>> `Enum` functions and in the end do: `Enum.into(changed, >>>>> Collectable.empty(initial))` and it would empty the collectable and fill >>>>> it >>>>> up again using the changed data. This way the `Repo.preload` could e.g. >>>>> additionally support custom enumerable and collectable collections as >>>>> first >>>>> argument like e.g. `%Scrivener.Page{}`. >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "elixir-lang-core" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/elixir-lang-core/19c24b83-fc2a-4af3-950e-eba7f767db14%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/elixir-lang-core/19c24b83-fc2a-4af3-950e-eba7f767db14%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "elixir-lang-core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/elixir-lang-core/1498525e-30fd-4cde-92a0-4b2e01cdbdf3%40googlegroups.com >>> <https://groups.google.com/d/msgid/elixir-lang-core/1498525e-30fd-4cde-92a0-4b2e01cdbdf3%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/5dff9895-1921-4794-89b9-d4ff45578880%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/5dff9895-1921-4794-89b9-d4ff45578880%40googlegroups.com?utm_medium=email&utm_source=footer> > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Kueg013YTHmg7jS5o94Qb0YbEjOWRNbKuENKgPiMJK0g%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
