Thank you all for the engaging discussion and thoughtful insights!
I want to clarify and emphasize the practical value of the proposed removeFirst(where:) and removeAll(where:) methods, particularly for real-world use cases where collections are used for dynamic indexing and manipulation.
On removeFirst(where:):
The use case for removeFirst(where:) aligns well with scenarios involving collections that serve as dynamic indices or canonical tables. For example:
Nested Dictionaries or Data Fragmentation: While it's true that better data structures may exist for specific edge cases, the removeFirst(where:) API offers an ergonomic and immediate solution for developers who need to handle these scenarios efficiently without overengineering.
Dynamic Updates: A common real-world scenario involves primary-secondary key tables where a single match must be identified and removed in an efficient manner. The responsibility of ensuring uniqueness (or handling undefined behavior) can be left to the developer while still providing a flexible API.
On removeAll(where:):
This method, in contrast, is a well-defined operation and caters to common patterns in collection manipulation, particularly for sets and dictionaries. Swift developers already leverage similar patterns in extensions due to their utility. Making this part of the standard library eliminates boilerplate code and ensures consistency with naming conventions (removeAll(where:) is intuitive, especially given the existing removeAll(where:) for arrays).
Addressing Concerns:
While concerns about "undefined behavior" for removeFirst(where:) in unordered collections like Set are valid, they may stem from a misunderstanding of the method's intention. The focus is on iteration order, not an inherent order, which is deterministic for a given instance of Set or Dictionary. Documenting this behavior explicitly mitigates ambiguity and equips developers to make informed choices.
In conclusion, I see removeFirst(where:) and removeAll(where:) as complementary tools that balance utility and simplicity, empowering developers to work effectively within the standard library's constraints. While advanced use cases might suggest alternative data structures, the inclusion of these APIs in the standard library would address a broader range of common scenarios, improve ergonomics, and align with Swift's commitment to practical, readable code.
I hope this clears up any doubts and sparks further discussion on how we can refine these proposals for maximum value.
What is "iteration order" at abstract (mathematical) level? I load a Set from external data, which is not required to be ordered, and then I call removeFirst. How do you define this operation mathematically? If you introduce the details of loading mechanism or the internal implementation of Set in order to define it, it is not a Set anymore, it is something more specific and more detailed. Is "iteration order" guaranteed to be stable after changes in Set implementation?
It is not enough for this operation to be repeatable in this program execution, or with this compiler/library version. If its behavior may change in a future version, I would consider it as random operation. Maybe it has use cases, but I wouldn't use it in deterministic programs.
Please note, in case it isnât immediately obvious, that @krishpranavâs âcontributionsâ both in this discussion and the pull request itself are the output of a large language model. The motivations behind doing such a thing remain unclear to me, but it doesnât seem like behavior that should be tolerated here.
IIRC It's a bit more nuanced than that. Iteration order is deterministic when iterating multiple times on an unmodified Set. However, the intitial order, or the order after mutation, is non-deterministic. The docs could be improved to be clearer in this matter.
Disregarding the merits of using LLMs to pitch, the obvious change would be to not name it removeFirst, but removeOne, removeSome or similar to address the unordered nature.
That being said, I really never have felt any need for that, so wonder on what a concrete application really would be.
I'm not sure personally I see the value in removeFirst(where:) for cases where the order is undefined (even if it is stable for one case). It may cause confusion by promoting the idea that a Set or Dictionaries order is consistently defined and stable between mutations. That said, that ship may have already sailed with removeFirst() which is already valid on Set so perhaps for consistency, it makes sense to add these on?
removeAll(where:) on the other hand seems like a great addition. Being able to performantly remove items without having to create a side Set to then subtract would be great. If the underlying implementation can avoid multiple loops and additional allocation in this case, sounds like a great addition that those outside the type could not otherwise perform.
Agree that would be useful. A variant that also would return the resulting Set of removed items could also be useful (with different performance characteristics of course).
I think it is OK to let them work for us. We can keep what we like and we can ignore what is gibberish. At the moment their creators do not seem to have a strategy, maybe they are satisfied if they pass a PR through a model. Eventually they will teach their model higher skills, like adding a disclaimer in their posts.
It would seem that removeFirst(where: would be used in the case where the author knows that there will only be one match (or none) to the predicate. In that case removeFirst(where: and removeAll(where: will give the same result but removeFirst(where: may be more efficient.
The author seems to have deleted their PR, so I'm going to close this thread. The Swift project as a whole does need a policy on using generative AI to make contributions (whether code or just posts of these forums), and we've started those conversations. In the meantime, I regret that folks have had a bit of their time wasted, but maybe it'll inspire someone to work on this for real â it seems like a great little project for someone who wants to get into standard library development and writing evolution proposals.