a = convert(UInt, 1)
b= convert(UInt, 2)
maximum(a, b)
fails with
ERROR: MethodError: objects of type UInt64 are not callable
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
[1] mapreduce_first(f::UInt64, op::Function, x::UInt64)
@ Base ./reduce.jl:424
[2] mapreduce(f::UInt64, op::Function, a::UInt64)
@ Base ./reduce.jl:451
[3] maximum(f::UInt64, a::UInt64; kw::@Kwargs{})
@ Base ./reduce.jl:705
[4] top-level scope
@ REPL[8]:1
I could have sworn that used to work. Is there a rationale for this (new) behavior?
Julia Version 1.10.0
Commit 3120989f39 (2023-12-25 18:01 UTC)
Build Info:
Note: This is an unofficial build, please report bugs to the project
responsible for this build and not to the Julia project unless you can
reproduce the issue using official builds available at https://julialang.org/downloads
Platform Info:
OS: macOS (arm64-apple-darwin22.6.0)
CPU: 10 Ă— Apple M1 Max
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 on 8 virtual cores
Environment:
JULIA_PKG_DEVDIR = [...]
help?> maximum
search: maximum maximum!
maximum(f, itr; [init])
Return the largest result of calling function f on each element
of itr.
The value returned for empty itr can be specified by init. It
must be a neutral element for max (i.e. which is less than or
equal to any other element) as it is unspecified whether init is
used for non-empty collections.
your code is equivalent to
julia> a(b)
ERROR: MethodError: objects of type UInt64 are not callable
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
[1] top-level scope
@ REPL[5]:1
Yes it does. I’m just perplexed that a) it used to work and b) it’s not super intuitive that maximum is not the maximum element of an iterable, but instead the maximum reduction over a mapping
It looks like a regression error on my part. I was on 1.9.x when I last ran this code in late Nov and in early Dec I introduced maximum and none of my tests caught it.
I’ve seen this mistake (confounding maximum / minimum with max / min in either way) various times. I think it’s quite a reasonable confusion, so perhaps it would be useful to extend the error message of those functions, with hints such as: Maybe you meant `max`?, etc.
What I’m not sure of is whether it is easy to generalize the sets of input arguments for which such a hint really makes sense. Or might it be simply given whenever there is a MethodError with those functions?
However for exactly 2 arguments you end up with the method that finds the maximum of an iterable after application of a function. So it tried to apply 1 to 2 which gave you the MethodError you saw. Part of that story is also the circumstance that numbers are iterable (so happenend was more like 1(2[1]). Otherwise the error could have been something like “2 is not iterable and maximum expects an iterable”, which maybe would have been more helpful in this specfic case. This is also what makes the suggestion of @heliosdrm difficult I think.
Maybe one could add a method like:
function maximum(too, many, args...)
error("`maximum([f ,] itr)` got too many arguments. For finding the maximum of several elements use `max`.")
end
That still has the unfortunate case of exactly 2 arguments though.
EDIT: Better than a method would probably be setting an error hint via Base.Experimental.register_error_hint but that cannot quite capture the 2-arg case either… As for generalizing: Probably good enough would the case maximum(::Number, ::Number).