Code readability after fixing deprecation warnings

I understand a lot of discussion preceded this release but I just wanted to supply some real life examples of changes in code. I received deprecation warnings like the ones below:

┌ Warning: `findfirst(A, v)` is deprecated, use `something(findfirst(isequal(v), A), 0)` instead.
│   caller = (::getfield(CompScienceMeshes, Symbol("##2#3")))(::Int64) at none:0
└ @ CompScienceMeshes .\none:0
┌ Warning: `find(f::Function, A::AbstractArray)` is deprecated, use `(LinearIndices(A))[findall(f, A)]` instead.
│   caller = boundary(::CompScienceMeshes.Mesh{3,3,Float64}) at mesh.jl:326

This leads to the following changes in code:

#i = findfirst(simplex, v)                                    # 0.6
 i = something(findfirst(isequal(v), simplex),0)              # 0.7

#i = find(x -> x < 2, sum(abs.(conn), dims=1))      # 0.6
 sums = sum(abs.(conn), dims=1)                     # 0.7
 i = (LinearIndices(sums))[findall(x->x<2, sums)]   # 0.7

Especially the second example sticks out as it forces the array to be bound to a named variable. Are there convenience functions for this?

When using the new findfirst API idiomatically, one should check for nothing rather than converting nothing to 0 and then checking for 0. That change requires manual refactoring generally, however; the deprecation just gives you an equivalent expression that will get your code working. You’ll have to refactor it later to make better use of the new patterns and idioms.

In the second case you probably don’t want to convert to linear indices at all since you’ll most likely just use them to index back into sums or some other array with the same shape (but we can’t know that for sure in the deprecation warning). Both the conversion to linear indices and the use of a linear index to index into an array can be expensive for general arrays; linear indexing is only efficient in the very particular case of dense, contiguous arrays. The new API can be efficient for completely general kinds of arrays. Instead, you can just index into sums directly with the cartesian indices returned by findall:

julia> sums = randn(3, 2)
3×2 Array{Float64,2}:
  2.71005  -0.450136
  1.11099  -0.703645
 -2.03338   0.578714

julia> findall(x->x > 0, sums)
3-element Array{CartesianIndex{2},1}:
 CartesianIndex(1, 1)
 CartesianIndex(2, 1)
 CartesianIndex(3, 2)

julia> sums[findall(x->x > 0, sums)]
3-element Array{Float64,1}:
 2.7100515660945628
 1.110985776756928
 0.5787139720528632

Again, this kind of refactoring is not really plausible to do automatically and requires manual intervention.

2 Likes