-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: iter/sorted: functions on sorted iterators #70140
Comments
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
I'm guessing that iter/sorted functions don't check that their iterator arguments are sorted, and I'm worried that some people will pass them unsorted iterators; the type system can't help us, in this case, since both sorted and unsorted iterators have type If this proposal gets accepted, its documentation should encourage other packages that provide sorted iterators to document them as such. |
I omitted that from the spec so that the implementation could choose to do it if we wanted it to. We don't want to document that it does, because that would force the functions to run slower. In general, Go doesn't perform expensive checks like this. For example, sort functions that take a My hope is that by putting these in a separate package from other iterator functions, users would be reminded of the requirements at the call site: |
You could also introduce |
@Merovius sadly you can still pass an |
Yes, I believe most iterators will be In any case, I’m not saying it’s perfect, or even that we necessarily should do it. But it’s IMO the strongest reasonable thing, has no runtime cost and will catch the overwhelming majority of mistakes. (also, |
Even if we had a |
You said
If there is value in such documentation, than the value of I agree that it doesn't provide an absolute guarantee. And I can understand the position, that the value it would provide is not enough to justify its cost. But it seems absurd to me to claim it has none, after saying that a doc-comment has enough. I was just trying to provide a way in which the type system might actually address your concern. |
Note that moot != none. I'm not dismissing a hypothetical
Not sure I agree. If anything, a |
It is true that If there were some way to capture the specific sort order itself as part of the type or value then that would be interesting, but I can't really think of any good way to do that with Go's current type system:
While I do sympathize with the idea that types often represent a claim about what something is or how it behaves rather than an enforcement of that (e.g. |
I find myself defending an idea I don't even believe that strongly in, but I just find the counter-arguments kind of confusing, TBH. This is a proposal for a package |
@Merovius I'm not sure who you're replying to, but I never claimed that
I only claim that you cannot verify that at compile time. Therefore, there is room for misuse (passing a non-sorted iterator where a sorted one is expected). And I doubt that a |
I apologize if I misunderstood the intent. My assumption was that the goal of introducing a new type to represent "sortedness" was to make it a compile-time error to use a sequence that isn't correctly sorted, and so I was trying to find a way to solve for some way that an API author can encode which specific order they used as part of the type, to reduce the likelihood of using a sequence that is sorted by the wrong comparison function. At the risk of taking this to an unreasonable extreme, it seems to me that any sequence can be said to be "sorted in some way". What these functions seem to require for correct usage is that they be sorted in some specific way -- the way described by the |
@apparentlymart I understood what you where saying. But not, why the same can't be said about a
That is easy: Use methods, instead of passing functions. And yes, I understand the reasons against that as well. Just pointing out again, that there are ways that the type system can address at least some of the concerns y'all bring up, if there is an actual interest in solving them. Here is an API that both prevents accidentally passing in a sequence that the programmer does not know is sorted and makes sure that the sorting is consistent: package sorted
type Comparer[T any] interface { Compare(T) int }
type Seq[E Comparer[E]] iter.Seq[E]
func Union[E Comparer[E]](s1, s2 Seq[E]) Seq[E] Or we can go even one step further than that, by actually preventing you from using a type Seq[E Comparer[E]] struct{ s iter.Seq[E] }
// Make makes a Seq that checks at runtime, that it is actually sorted. If it is not, iterating over it panics.
func Make[E Comparer[E]](s iter.Seq[E]) Seq[E] {
return Seq[E]{func(yield func(E) bool) {
var (
last E
haveLast bool
)
for e := range s {
if haveLast {
if last.Compare(e) > 0 {
panic("sequence not sorted")
}
}
if !yield(e) { return }
last, haveLast = e, true
}
}}
}
// UnsafeMake asserts that s is sorted, without actually providing any guarantee.
func UnsafeMake[E Comparer[E]](s iter.Seq[E]) Seq[E] {
return Seq[E]{s}
} If you are concerned about misuse, we can talk about ways to prevent that misuse. Or we can say "we trust the programmer to be sensible". That's what we do for To me, |
By analogy with |
To be clear, I would prefer to get some more compile-time safety here, and only discarded the idea of using a single-method interface because I recall from earlier discussions about I suppose the way I'd sum up what I was trying to get at is: I would be in favor of a design that makes the comparer part of the type, such as what you've just proposed, but with a I assumed, perhaps incorrectly, that consensus would not favor using a single-method interface for the comparers, even though it would in principle allow that additional safety, based on earlier discussions in this area. (FWIW I also think it would be just fine to put these in the main |
I propose adding a package of functions that operate on iterators whose values are sorted.
Sorted sequences can arise in a number of ways:
Common operations on pairs of sorted sequences include merging them into a single sorted sequence, as well as the set operations union, intersection and set difference. I propose a package with these operations, with the API given below.
As is common in packages like
slices
, there are two functions for each operation, one using the natural ordering of a type and one that accepts a comparison function. We could also consider adding functions that operate on the keys ofiter.Seq2
s, bringing along the corresponding values. I don't know if those sequences would arise enough to make that worthwhile. We could reconsider adding theSeq2
functions if and when we add ordered maps.API
There is a working implementation at github.com/jba/sorted.
The text was updated successfully, but these errors were encountered: