Better explain this with an example:
190 ?- _Ls = [a,b,c], _Rs = [a,a,a,b,b,c,c,c,c], ord_intersect(_Ls,_Rs,Is).
Is = [a, b, c].
191 ?- _Ls = [a,a,b,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, c].
192 ?- _Ls = [a,a,b,b,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, b, c].
193 ?- _Ls = [a,a,b,b,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, b, c, c].
194 ?- _Ls = [a,a,b,b,c,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, b, c, c, c].
195 ?- _Ls = [a,a,b,b,c,c,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, b, c, c, c, c].
196 ?- _Ls = [a,a,b,b,b,c,c,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_intersect(_Ls,_Rs,Is).
Is = [a, a, b, b, c, c, c, c].
In other words, ord_intersect/3 is happy to operate on a sorted list with duplicates (essentially, a multiset), despite the documentation saying that the entire library only operates on ordered sets:
Ordered sets are lists with unique elements sorted to the standard order of terms (see sort/2). Exploiting ordering, many of the set operations can be expressed in order N rather than N^2 when dealing with unordered sets that may contain duplicates.
From: SWI-Prolog -- library(ordsets): Ordered set manipulation
At least some of the other predicates in the library work the same way:
201 ?- _Ls = [a,a,a,b,b,c,c,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_subset(_Ls,_Rs).
true.
202 ?- _Ls = [a,a,b,b,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_subtract(_Ls,_Rs,Ds).
Ds = [].
203 ?- _Ls = [a,a,b,b,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_subtract(_Rs,_Ls,Ds).
Ds = [a, c, c, d, d].
% Ugh, this one may be slightly off!
204 ?- _Ls = [a,a,b,b,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_union(_Ls,_Rs,Ds).
Ds = [a, a, a, b, b, c, c, c, c, d, d].
205 ?- _Ls = [a,a,b,b,c,c], _Rs = [a,a,a,b,b,c,c,c,c,d,d], ord_symdiff(_Ls,_Rs,Ds).
Ds = [a, c, c, d, d].
As it happens I went looking at the implementation because I wanted an intersection predicate operating on lists with duplicates, and I thought that sorting the list would improve performance. I went to look at the implementation of ord_intersect/3 to see if I could cannibalize it for patterns to use in my predicate, and I thought to check, and realised it works on ordered lists with duplicates.
Now, I would like to keep this behaviour, but what is the right thing to do here in terms of the library? Should the documentation change to reflect the true behaviour of the code? Or should the code change to match the informal specification given in the documentation?
I’m for the former: keep the behaviour, change the documentation. After all, the current implementation works with ordered sets just fine, it’s just that it seems to work also with essentially multisets. I don’t think that’s a bad thing, it’s just that the library is less restricted than advertised. I don’t think having multiples changes the performance much either, but haven’t checked to be honest.