Interesting question!

While there are many structures for which an 'empty' might make sense, 
there are some (probably more) for which it does not. To be more formal 
about this: `Collectable` is essentially an implementation of what is known 
as a `SemiGroup` in Category Theory terms (pedantically speaking, it 
implements the concatenation function ('Collectable.into') directly rather 
than having a binary combining operator that the concatenation function is 
built on top of).
If you have a SemiGroup that happens to also have a well-defined 
empty/default value, we end up with what is known as a `Monoid`.

While Elixir does not have a protocol or behaviour in place to work with 
things that are Monoids directly, there are still two ways you can make it 
work:

1. By allowing the user to provide the desired 'default' data structure 
directly (rather than the module it is defined in). This is what we already 
do when writing `into: %{}` for instance. The nice thing about this 
approach is that it allows the user to specify *any* data structure, not 
only empty ones. (There are many data structures for which there is more 
than one reasonable default, and there are also cases in which the user 
might want to collect multiple enumerables in the same collection. Both of 
these use cases are covered by this).
2. If you happen to write something where it is difficult for the user to 
provide a datastructure and they only give you a module atom, you can still 
look if the module has a `new/0` method: While not standardized, this is a 
convention which a very large amount of libraries as well as Elixir's 
standard library seem to follow.

~Qqwy/Marten

On Tuesday, May 21, 2019 at 5:46:29 PM UTC+2, Benjamin Milde 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/e98aeb01-b04b-4f0f-acec-bbf24fb95b88%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to