JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.89k stars 5.49k forks source link

The method `findall(in(a), b)` treats `a` as iterable not as a set #52639

Open eliascarv opened 11 months ago

eliascarv commented 11 months ago

In Meshes.jl, we use in function to check if a point (element) is in geometry (set), e.g. point in geometry. But the method findall(in(geometry), vector_of_points) treats geometry as a finite iterable.

MWE:

using Meshes
box = Box((0, 0), (1, 1))
points = rand(Point2, 10)
inds = findall(p -> p ∈ box, points) # works
inds = findall(∈(box), points) # breaks

This error occurs due to the following method definitions:

image link: https://github.com/JuliaLang/julia/blob/master/base/array.jl#L2783-L2784

image link: https://github.com/JuliaLang/julia/blob/master/base/array.jl#L2720-L2727

A possible solution would be to restrict these methods to just AbstractArrays and Tuples:

findall(pred::Fix2{typeof(in), <:Union{AbstractArray, Tuple}}, x::AbstractArray) = _findin(x, pred.x)
findall(pred::Fix2{typeof(in), <:Union{AbstractArray, Tuple}}, x::Tuple) = _findin(x, pred.x)
stevengj commented 11 months ago

A possible solution would be to restrict these methods to just AbstractArrays and Tuples:

That would be breaking, because it would kill findall for other iterables.

Maybe we should change it to

bset = AbstractSet(b)

defaulting to Set(b). That way, if b is already a subtype of AbstractSet (or if you define an AbstractSet constructor for your geometry type), you'll get bset === b.