-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PoC] Add the Container
module for stable and finite collections
#12092
base: master
Are you sure you want to change the base?
[PoC] Add the Container
module for stable and finite collections
#12092
Conversation
Yes, I feel like this might be going a bit too far. I'd rather have a bit of code duplication in standard library than imposing too many generic container'ish interfaces onto users. I also think pushing some necessary conversion onto the caller sides is fine. It may actually make code easier to reason about, albeit a bit more verbose, compared to hiding them behind stdlib interfaces. |
Maybe the name |
So it would be something like this:
|
What benefits could we gain from finiteness alone if all the stability guarantees are gone? #10075? |
Just in case, I'm just proposing renaming |
Regarding names, |
How can you guarantee stability from just a name? There's no way to guarantee that. I'd rather not introduce a type that says "this guarantees X" without having a way to check that. |
That's why I also don't understand why stability matters, an which collections aren't stable (which ones are these?) |
There is no way to validate or enforce intrinsic properties such as stability. The type represents a semantic convention. But this is practically very valuable. I think the same argument can be applied to |
I'm taking a look at the code... so for cartesian product to work, I'm seeing that it converts each container to an Array if it's not already an Array. I'm failing to understand why not, instead, just force the caller to convert things to an Array before calling that. Also, if things are converted to Array, I don't understand where this "stability" concept comes into play. After all the collection is traversed just once. Well, I see some I just think that the usefulness of this is very tiny compared to the complexity of introducing an unclear abstraction. |
This is a proof of concept for #3790 (comment). It relaxes
Indexable.cartesian_product
's requirement from anIndexable(Indexable)
to aContainer(Container)
. SinceSet
has a finite size and provides stable iteration, it satisfiesContainer
and one can now do:This can be easily generalized to the instance methods and the
Iterator
-returning variants.Compared to the existing implementation,
Container.each_cartesian
simply converts all the innerSet
s intoArray
s (containers = containers.map { |c| dup_as_array(c) }
), because we can now assert thatContainer#to_a
is always safe to call.Some afterthoughts:
Container
can be safely converted to anArray
, that means all methods inIndexable
can be moved toContainer
if every method does this conversion. For example, it becomes possible to callSet#bsearch
, and the result is "meaningful" provided that theSet
's members are sorted with respect to the iteration order. Do we want this?Container
if and only if it makes sense in an unordered container.#sample
is one such method, and so is.cartesian_product
if we conceptually view its return value as a set. Perhaps the requirement on stable iteration order can be dropped, i.e. multiple calls to#each(&)
are allowed to permute the elements, but not add or remove any.#index
can be moved intoContainer
if we interpret the return value as one that is consistent with#each_with_index
:Set
satisfiesIndexable
, which is definitely unexpected. How do we tell that aContainer
is notIndexable
?Indexable#unsafe_fetch
, which is most certainly not the case forSet
. This is more apparent withXML::Attributes
, a container backed by a singly linked list. Its#size
is exactly the one fromEnumerable
, and is O(n); same for#[](Int)
.IMHO this
Container
is too powerful and the waycartesian_product
works onHash
es is rather confusing. Maybe it is fine that we don't supportSet
arguments after all?