Several people, including myself, have tried to raise this issue during last months. There were multiple posts on slack, and even a GH issue (https://github.com/JuliaLang/julia/issues/39203). I’ll try to raise it once more, here on discourse, hoping that it gets more traction.
The findmax(A)
function, which everyone is used to, returns the maximum value in the array A
and its index. However, Julia 1.7 will introduce a findmax(f, A)
version, that doesn’t return any index at all:
julia> A = [5, 1, 3, 8, 0];
julia> maxval, maxix = findmax(A)
(8, 4)
julia> A[maxix]
8
# but:
julia> findmax(identity, A)
(8, 8)
There are at least two independent reasons why this feels really weird, confusing, and even surprising (as evidenced by multiple questions on slack).
First: we still have no effecient way to find array index of the maximal value wrt some function! That is, something like (imaginary) findmax(["a", "bc", "d"], by=length)
. For arrays and many other collections, obtaining index is a more fundamental operation: easy to go from index to value, hard to go the other way.
Second: the findmax(f, A)
form, to be introduced in 1.7, is completely inconsistent with both findmax(A)
and with other reductions that take a function and an array:
julia> findfirst([false, false, true])
3
julia> findfirst(identity, [false, false, true])
3 # same as above
# but:
julia> findmax([false, false, true])
(true, 3)
julia> findmax(identity, [false, false, true])
(true, true) # definitely not the same
Even the docstrings for these two forms have literally nothing in common:
findmax(A): Return the maximal element of the collection itr and its index or key.
findmax(f, A): Returns a pair of a value in the codomain (outputs of f) and the corresponding value in the domain (inputs to f) such that f(x) is maximised.
Currently, any (?) reduction of the form r(f, A)
in base julia is just a more efficient form of r(map(f, A))
.
Several different solutions were suggested in the linked GH issue.
I believe the findmax(f, A)
form to-appear-in-1.7 should be removed anyway while it’s not released, and one of those suggested approaches implemented instead, either in 1.7 or later.
NB: discussion above applies to the whole findmax, findmin, argmax, argmin
function family.
As I understand PR https://github.com/JuliaLang/julia/pull/35316, the motivation for the soon-to-be-released findmax(f, A)
form is based on the mathematical interpretation of argmax(f, A) == argmax f(x) over x in A
. This is, however, not the meaning currently attached to this function family in julia. No optimization package overrides argmax
to perform maximization of f
over some domain, like argmax(f, 0..Inf)
. And findmax(f, A)
doesn’t even have this similarity to any mathematical notation.