@@ -251,16 +251,15 @@ true
251
251
issubset, ⊆ , ⊇
252
252
253
253
function issubset (l, r)
254
- if haslength (r)
255
- rlen = length (r)
256
- if isa (l, AbstractSet)
257
- # check l for too many unique elements
258
- length (l) > rlen && return false
254
+ if haslength (r) && ( isa (l, AbstractSet) || ! hasfastin (r))
255
+ rlen = length (r) # conditions above make this length computed only when needed
256
+ # check l for too many unique elements
257
+ if isa (l, AbstractSet) && length (l) > rlen
258
+ return false
259
259
end
260
- # if r is big enough, convert it to a Set
261
- # threshold empirically determined by repeatedly
262
- # sampling using these two methods (see #26198)
263
- if rlen > 70 && ! isa (r, AbstractSet)
260
+ # when `in` would be too slow and r is big enough, convert it to a Set
261
+ # this threshold was empirically determined (cf. #26198)
262
+ if ! hasfastin (r) && rlen > 70
264
263
return issubset (l, Set (r))
265
264
end
266
265
end
@@ -270,6 +269,19 @@ function issubset(l, r)
270
269
return true
271
270
end
272
271
272
+ """
273
+ hasfastin(T)
274
+
275
+ Determine whether the computation `x ∈ collection` where `collection::T` can be considered
276
+ as a "fast" operation (typically constant or logarithmic complexity).
277
+ The definition `hasfastin(x) = hasfastin(typeof(x))` is provided for convenience so that instances
278
+ can be passed instead of types.
279
+ However the form that accepts a type argument should be defined for new types.
280
+ """
281
+ hasfastin (:: Type ) = false
282
+ hasfastin (:: Union{Type{<:AbstractSet},Type{<:AbstractDict},Type{<:AbstractRange}} ) = true
283
+ hasfastin (x) = hasfastin (typeof (x))
284
+
273
285
⊇ (l, r) = r ⊆ l
274
286
275
287
# # strict subset comparison
0 commit comments