Max of a vector

It is quite strange that the max function cannot work in an intuitive way. I just want the maximum value in a vector.

julia> a = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> max(a)
ERROR: MethodError: no method matching max(::Vector{Int64})

Closest candidates are:
  max(::Any, ::Missing)
   @ Base missing.jl:137
  max(::Any, ::Any)
   @ Base operators.jl:467
  max(::Any, ::Any, ::Any, ::Any...)
   @ Base operators.jl:578
  ...

Stacktrace:
 [1] top-level scope
   @ REPL[66]:1

It is ridiculous that max(1,2,3) is ok, but max([1,2,3]) not ok.

julia> max(1,2,3)
3

julia> max([1,2,3])
ERROR: MethodError: no method matching max(::Vector{Int64})

Closest candidates are:
  max(::Any, ::Missing)
   @ Base missing.jl:137
  max(::Any, ::Any)
   @ Base operators.jl:467
  max(::Any, ::Any, ::Any, ::Any...)
   @ Base operators.jl:578
  ...

Stacktrace:
 [1] top-level scope
   @ REPL[68]:1
julia> maximum([1,2,3])
3
18 Likes

As ever, the help is your friend:

help?> max

  max(x, y, ...)

  Return the maximum of the arguments (with respect to isless). See also the maximum function to take the maximum element from a collection.
20 Likes

I think it’s best to not use language like this. The matter has been considered and discussed several times, for example:

It’s not like no one thought about this.

12 Likes

max([1,2,3]...) # OK

1 Like

interesting! what is the mechanism?

Now I understand how max and maximum are different and be fluent to functional programming-reduction, but I couldn’t get that point when I was new to julia too.

Actually, max([1,2,3]...)=max(1,2,3) and maximum([1,2,3]) are both acceptable to newbie if there is only one way. The real problem is , “Why julia has two max function?”.

Imagine that a guy from python or matlab yesterday, but max([1,2,3]) raises error again and again, about 1 hour. He never know why max doesn’t work, and feel very annoying. But if there was no max, he would look for maximum in 30 second and be happy. They can’t consider the existence of maximum because of max. Nobody thinks “This is max, but I can’t use it, then there is other function like max with other name.”.

At least, the existence of max and maximum is not intuive to strangers.

6 Likes

The Julia REPL is your best friend.

For max, it also suggests looking at maximum:

help?> max
search: max maximum maximum! maxintfloat argmax eigmax RowMaximum typemax findmax findmax! Cintmax_t floatmax Cuintmax_t Matrix minmax tf_matrix BitMatrix macroexpand @macroexpand     

  max(x, y, ...)

  Return the maximum of the arguments (with respect to isless).
  See also the maximum function to take the maximum element from a collection.

And for the splatting:

help?> ...
search: ...

  ...

  The "splat" operator, ..., represents a sequence of arguments. ... can be used in function definitions, to indicate that the function accepts an arbitrary number of arguments. ...
  can also be used to apply a function to a sequence of arguments.
1 Like

reduce(max, x) is equivalent to maximum(x).

max compares varargs and returen the maximal element.

4 = max(1,4,1,2)

But vector has no proper order, so max([1,4,1,2]) is nonsense.

reduce is a higher-order function. It works like

max(x[1], max(x[2], ..., max(x[end-1], x[end])...))

, taking max fuction as the first argument.

So, max and maximum is different. But I know how you feel. Welcome to julia, my friend.

1 Like

My two cents: there is here a trade off between elegant implementation and usability.
The points to have separate max/maximum functions relates to how Julia internally treat broadcast, multiple dispatch, etc. Having a single function would make the Julia source code look much more a dirty, overly patched specific implementation for this.
However for a novice Julia user, having this distinction is dramatic.
For how much it is in the doc, this looks to novices like “what’s the hell is wrong with this complicated language?”… not really user friendly…

1 Like

For me more confusing is always that NumPy has exactly the other convention.

That being said, I think an error in the max or maximum function has not stopped anyone from learning a new language.

In [5]: np.maximum(1,2)
Out[5]: 2

In [6]: np.max(np.array([1,2,3]))
Out[6]: 3

In [7]: np.max(1,2)
---------------------------------------------------------------------------
AxisError                                 Traceback (most recent call last)
Cell In[7], line 1
----> 1 np.max(1,2)

File <__array_function__ internals>:200, in amax(*args, **kwargs)


   2703 @array_function_dispatch(_amax_dispatcher)
   2704 def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
   2705          where=np._NoValue):
   2706     """
   2707     Return the maximum of an array or maximum along an axis.
   2708 
   (...)
   2818     5
   2819     """
-> 2820     return _wrapreduction(a, np.maximum, 'max', axis, None, out,
   2821                           keepdims=keepdims, initial=initial, where=where)


     83         else:
     84             return reduction(axis=axis, out=out, **passkwargs)
---> 86 return ufunc.reduce(obj, axis, dtype, out, **passkwargs)

AxisError: axis 2 is out of bounds for array of dimension 0


In [8]: np.maximum(np.array([1,2,3]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 np.maximum(np.array([1,2,3]))

TypeError: maximum() takes from 2 to 3 positional arguments but 1 were given

6 Likes

Oh, please, do not suggest that…

@jiang_ming_zhang , yes there are these two functions. Use and abuse os the REPL help, and feel free to ask anything here, we are glad to help. I would just suggest not being dismissive in your questions. Many of the difficulties you are experiencing are result from tradeoffs that were discussed to exhaustion, so there are good reasons for the language work as it does. In some aspects, these tradeoffs make Julia appear less friendly than other languages, that’s true. On other aspects is the opposite. At the end, after some experience with Julia, you’ll know if the tradeoffs are to your benefit or not. But one needs to start open minded and not expect the language to be necessarily similar to what one is experienced in.

9 Likes

For small arrays should be fine? Some related warning here.

Even for small arrays you have dynamic dispatch. (As opposed to tuples.) Of course, if you have lots of few-element arrays in performance-critical code then you might want to re-think your code structure anyway.

But it’s better (faster, cleaner, more idiomatic) to use the maximum function to find the maximum element of a collection. That’s what it’s there for.

5 Likes
julia> max(a)
ERROR: MethodError: no method matching max(::Vector{Int64})
Finding the minimum or maximum element of an array is performed with `minimum` and `maximum` respectively.
30 Likes

While Python itself uses max for both multi-arguments and lists.

1 Like

Julia is a lot more consistent, generic and general than Matlab and this is a pretty good example of that. Let’s look at what Matlab has for max—the core “methods” ignoring weird flags are these:

  • M = max(A)
  • M = max(A,[],"all")
  • M = max(A,[],dim)
  • M = max(A,[],vecdim)
  • C = max(A,B)

Even just the first “method” is actually a pretty wild amalgam of behaviors. To quote:

  • If A is a vector, then max(A) returns the maximum of A.
  • If A is a matrix, then max(A) is a row vector containing the maximum value of each column of A.
  • If A is a multidimensional array, then max(A) operates along the first dimension of A whose size is greater than 1, treating the elements as vectors. The size of M in this dimension becomes 1, while the sizes of all other dimensions remain the same as in A. If A is an empty array whose first dimension has zero length, then M is an empty array with the same size as A.
  • If A is a table or timetable, then max(A) returns a one-row table containing the maximum of each variable.

Uhh, what? Is there, like, a function that just gives me the maximum value of an array, regardless of how many dimensions it has? Ah, ok, there it is, it’s the next method—the delightfully named max(A,[],"all") method. I’m really seeing everyone’s point here—writing max(A,[],"all") really is much nicer than maximum(A). I’m kidding, of course, that’s awful, but that is how maximum is spelled in Matlab.

Ok, what if we come at it from the other end and compare Julia’s max with Matlab’s? Matlab only documents supporting pairwise max(A, B) not n-ary max(A, B, C…) like Julia. Also, it assumes that A and B are some kind of array and you want to do an elementwise max operation. That’s fine for Matlab’s world view, but what if you have objects that aren’t arrays? Shocking concept, I know, but in that case, you might want to compare n values using something besides elementwise scalar comparison. For example, it’s often useful to compare arrays or tuples as objects themselves using lexicographical ordering. In fact, this is what Julia does when you apply max to arrays:

julia> max([1,2,3], [2,3], [])
2-element Vector{Int64}:
 2
 3

This can be confusing to Matlab users, but it’s a very useful general programming behavior and is similar to how strings work:

julia> max("apple", "zoo", "cat")
"zoo"

Of course Matlab only got strings in 2016, so that was hardly a consideration for them, but Julia has had them from the start. In Julia, if you want to do elementwise max you use broadcasting:

julia> max.([1,2,3],[3,2,1])
3-element Vector{Int64}:
 3
 2
 3

Give the existence of generic n-ary max in Julia, people wanting max([1, 3, 2]) to return 3 should consider that a general n-ary max should actually just return its argument when called with a single argument, i.e. max([1, 3, 2]) should return its argument, which is [1, 3, 2]. We don’t actually define a 1-ary max because it would be too much of a potential footgun for unsuspecting Matlab refugees, but that’s what the method should do if it existed.

Anyway, I too find it slightly annoying when I occasionally forget and try to do max(v) and it doesn’t work, but you should keep in mind that Matlab’s max function is a byzantine mess and that the since max and maximum are fundamentally different concepts, any attempt to fuse them in a language that wants to be consistent, general and generic is bound to end badly.

26 Likes

To be fair, MATLAB started at the end of the 70’s and functions like max had to be compatible with the original design since then. Basing everything on 2-d matrices (multi-dimensional came later) was great compared to FORTRAN 77, we thought at that time. max(max(A)) would return the maximum element over the whole matrix, I believe.

To get also the index of the maximum element in Matlab the same function max

[m, idx] = max(A)

is used, while in Julia another function findmax needs to be remembered.

5 Likes

argmax is also possible and very easy to remember since this is the conventional mathematical notation

1 Like