What's the best way to optimize findmax with a function?

There is a PR for such a findmax that seems to be almost done: https://github.com/JuliaLang/julia/pull/35316. But another thing to consider is that map semantically materializes, while Iterators.map does not. So you can probably get the behavior you want just by findmax(Iterators.map(length, l)). Note that the Iterators submodule of Base provides lazy versions for other functions in Base too (and the package IterTools.jl has some more).

One likely cannot completely remove the materialization as a compiler pass, because sometimes different algorithms are used. For example, given a vector v, sum(map(x -> x^2, v)) will materialize the vector and then apply sum, which will use pairwise summation (since its input is a vector). But sum(Iterators.map(x -> x^2, v)) (or sum(x -> x^2, v)) will apply a naive accumulation, which might have more floating point error. (I did not actually check these statements so please correct me if I’m wrong). So the compiler won’t convert the first into the second, because you might be relying on pairwise summation. A hypothetical super smart compiler might be able to remove details like the actual memory allocation for the vector, etc, but semantically it has to use the vector method/algorithm, since that’s what you told it to do. I’m not sure to what extent this applies to findmax but I hope it helps explain why Julia doesn’t always do these things automatically.

edit: by the way, the findmax code from the PR (by @ColinCaine) is very simple, so it’s easy to just copy it into your own projects until the PR makes it through to a Julia release:

findmax(f, domain) = mapfoldl(x -> (f(x), x), _rf_findmax, domain)
_rf_findmax((fm, m), (fx, x)) = isless(fm, fx) ? (fx, x) : (fm, m)
2 Likes