# \`findmax\` bug?

**URL:** <https://discourse.julialang.org/t/findmax-bug/20818>\
**Category:** General Usage\
**Tags:** bug\
**Created:** [February 15, 2019, 10:25am UTC](https://discourse.julialang.org/t/findmax-bug/20818 "2019-02-15T10:25:58Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 10:25am UTC](https://discourse.julialang.org/t/findmax-bug/20818/1 "2019-02-15T10:25:58Z")

</div>

On Julia v0.6.4 the following worked, but no longer on v0.7, v1.0.x and v1.1.0:

```julia
a = rand(3)
findmax( a[j] for j = 1:3 )

```

results in

```julia
ERROR: MethodError: no method matching keys(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##13#14"))})
Closest candidates are:
  keys(::Cmd) at process.jl:940
  keys(::Core.SimpleVector) at essentials.jl:570
  keys(::Tuple) at tuple.jl:46
  ...
Stacktrace:
 [1] pairs(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##13#14"))}) at ./abstractdict.jl:132
 [2] _findmax(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##13#14"))}, ::Colon) at ./array.jl:2052
 [3] findmax(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##13#14"))}) at ./array.jl:2049
 [4] top-level scope at none:0

```

Bug or intended behaviour? What makes me wonder whether it is a bug is that replacing `findmax` with `maximum` works as expected.

But maybe it isn’t a bug then I suppose the issue is that I’m passing a generator instead of a collection. How do I convert a generator into a collection? I am not sure what to look for in the documentation…

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [February 15, 2019, 10:32am UTC](https://discourse.julialang.org/t/findmax-bug/20818/2 "2019-02-15T10:32:54Z")

</div>

> [@cortner](#):
>
> How do I convert a generator into a collection?

Enclose the generator inside square brackets `[]`:

```julia
julia> findmax( [A[j] for j = 1:3] )
(0.5601650744483095, 1)

```

(note that you have small-caps ‘a’ in stead of a capital ‘A’ in your example)

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [February 15, 2019, 10:55am UTC](https://discourse.julialang.org/t/findmax-bug/20818/3 "2019-02-15T10:55:12Z")

</div>

> [@cortner](#):
>
> How do I convert a generator into a collection?

Using `collect`, or as @yakir12 showed with a comprehension.

However, this is a bit odd as running the code in Julia 0.7 does not give a deprecation warning. I don’t know whether this was removed on purpose (and the deprecation was forgotten) or not (and it’s just a bug).

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 12:12pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/4 "2019-02-15T12:12:05Z")

</div>

Sort about the typo - will fix momentarily.

I don’t want to use collect or since Inwant to avoid the allocation.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 15, 2019, 12:16pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/5 "2019-02-15T12:16:48Z")

</div>

Generators don’t really have indices so what would this return? You can do something like:

```julia
julia> maximum( (a[j], j) for j=1:3)
(0.7026710903900824, 3)

```

to get the number of times the iterator iterated to find the max (and the value).

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [February 15, 2019, 12:30pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/6 "2019-02-15T12:30:51Z")

</div>

If you have a non-indexable iterator (which I presume might be the case since you’re using a generator?), the above solution won’t work:

```julia
julia> itr = Iterators.drop(rand(10), 0);

julia> maximum((itr[j], j) for j=1:length(itr))
ERROR: MethodError: no method matching getindex(::Base.Iterators.Drop{Array{Float64,1}}, ::Int64)

```

In that case, you can use the following (largely allocation free, and about the same performance):

```julia
julia> maximum(reverse, Iterators.enumerate(itr))
(0.9338279491162726, 6)

```

---

<div class="post-metadata">

**Author:** ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)\
**Post date:** [February 15, 2019, 2:34pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/7 "2019-02-15T14:34:55Z")

</div>

I’m not sure if I understand you correctly, but why not simply `findmax(a)`? It is so fast and doesn’t allocate.

```julia
julia> a = rand(3)
3-element Array{Float64,1}:
 0.19843206660329815
 0.1534497798559591
 0.4435263304297765

julia> @btime findmax($a)
  8.467 ns (0 allocations: 0 bytes)
(0.4435263304297765, 3)

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [February 15, 2019, 2:44pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/8 "2019-02-15T14:44:00Z")

</div>

> [@Seif\_Shebl](#):
>
> I’m not sure if I understand you correctly, but why not simply `findmax(a)` ? It is so fast and doesn’t allocate.

Did you read the first post? It shows that `findmax` doesn’t work for a generator.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 3:01pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/9 "2019-02-15T15:01:52Z")

</div>

As @kristoffer.carlsson points out, this is just an MWE. Suppose I have a non-trivial generator, and I really want to avoid allocations (e.g. in a hot inner loop). Further, my main confusion is that `maximum` accepts the generator as an argument but `findmax` does not. So far nobody has offered a justification for this, so I am beginning to think this must be a bug.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 3:02pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/10 "2019-02-15T15:02:38Z")

</div>

interesting, but very ugly 🙂

---

<div class="post-metadata">

**Author:** ![under-Peter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/under-peter/32/3626_2.png) [@under-Peter](https://discourse.julialang.org/u/under-Peter)\
**Post date:** [February 15, 2019, 3:09pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/11 "2019-02-15T15:09:49Z")

</div>

As Kristoffer said, generators in general don’t have indices (there’s no method `getindex` for generators) so `findmax`, which would return an index, doesn’t really make sense here.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 3:10pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/12 "2019-02-15T15:10:41Z")

</div>

thanks for pressing the point - I had completely missed it on my first reading. I guess that makes perfect sense then…

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [February 15, 2019, 3:15pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/13 "2019-02-15T15:15:10Z")

</div>

> [@cortner](#):
>
> interesting, but very ugly 🙂

What do you think is ugly about it? To be clear, the `drop` part was just a way to simulate a non-indexable iterator, it’s not part of finding the maximum. The `reverse` is there to swap around the tuple arguments, completely allocation free. The performance should be about the same as Kristoffer’s solution, but works with any iterator, not just those that you can index into (which I presume could be the case if you’re using the generator form?).

```julia
julia> a = rand(1_000_000);

julia> @btime maximum(($a[j], j) for j=1:length($a))
  2.487 ms (2 allocations: 48 bytes)
(0.9999989093229165, 50243)

julia> @btime maximum(reverse, Iterators.enumerate($a))
  2.465 ms (1 allocation: 16 bytes)
(0.9999989093229165, 50243)

```

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [February 15, 2019, 3:50pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/14 "2019-02-15T15:50:08Z")

</div>

I think this is the same as [https://github.com/JuliaLang/julia/issues/23680](https://github.com/JuliaLang/julia/issues/23680)

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [February 15, 2019, 8:51pm UTC](https://discourse.julialang.org/t/findmax-bug/20818/15 "2019-02-15T20:51:10Z")

</div>

I just can’t parse it - it’s a bit too functional for my taste, but I appreciate that it is a matter of taste.
