<p dir="auto">The <code class="notranslate">reduce</code> function should, according to its docstring, "reduce the given collection with the given binary operator." I believe this is also what most programmers would expect a <code class="notranslate">reduce</code> function to do.</p>
<p dir="auto">However, this is not always what it does. Some input types, e.g. <code class="notranslate">Int32</code> are converted before the operator is applied. This can lead to unexpected results.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia&gt; my_op(a::Int32,b::Int32) = max(a,b)
my_op (generic function with 1 method)

julia&gt; reduce(my_op, ones(Int32,42))
ERROR: MethodError: no method matching my_op(::Int64, ::Int64)
 in mapreduce_impl(::Base.#identity, ::#my_op, ::Array{Int32,1}, ::Int64, ::Int64, ::Int64) at ./reduce.jl:101
 in _mapreduce(::Base.#identity, ::#my_op, ::Base.LinearFast, ::Array{Int32,1}) at ./reduce.jl:168
 in mapreduce(::Function, ::Function, ::Array{Int32,1}) at ./reduce.jl:175
 in reduce(::Function, ::Array{Int32,1}) at ./reduce.jl:179"><pre class="notranslate"><code class="notranslate">julia&gt; my_op(a::Int32,b::Int32) = max(a,b)
my_op (generic function with 1 method)

julia&gt; reduce(my_op, ones(Int32,42))
ERROR: MethodError: no method matching my_op(::Int64, ::Int64)
 in mapreduce_impl(::Base.#identity, ::#my_op, ::Array{Int32,1}, ::Int64, ::Int64, ::Int64) at ./reduce.jl:101
 in _mapreduce(::Base.#identity, ::#my_op, ::Base.LinearFast, ::Array{Int32,1}) at ./reduce.jl:168
 in mapreduce(::Function, ::Function, ::Array{Int32,1}) at ./reduce.jl:175
 in reduce(::Function, ::Array{Int32,1}) at ./reduce.jl:179
</code></pre></div>
<p dir="auto">The exact same problem occurs with <code class="notranslate">mapreduce(identity, my_op, ones(Int32,42))</code>.</p>
<p dir="auto">I realize that using an accumulator that is wider than the input could be beneficial in some special circumstances, such as if the <code class="notranslate">sum</code> function didn't exist and one wanted to create it using <code class="notranslate">reduce(+, ...)</code> without risking integer overflow. But in those cases one could supply a <code class="notranslate">v0</code> argument of the desired return type (or there could be an optional <code class="notranslate">accumulator_type</code> argument).</p>
<p dir="auto">I'm running a code similar to following (data: <a href="https://homes.cs.washington.edu/~grechkin/bugreport1.jld" rel="nofollow">https://homes.cs.washington.edu/~grechkin/bugreport1.jld</a>)</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="using JLD

type A1
    v1::String
    v2::String
end
type B1
    val::A1
    tag::String    
end

@load &quot;bugreport1.jld&quot; tmp_data2
Base.hash(x::A1) = hash((x.v1, x.v2))
Base.hash(x::B1) = hash((hash(x.tag), hash(x.val)))
import Base.==
==(x::B1, y::B1) = x.tag == y.tag &amp;&amp; x.val.v1 == y.val.v1 &amp;&amp; x.val.v2 == y.val.v2

@show tmp_data2 # 12 items in the array with last two duplicated

@show unique(tmp_data2[1:12]) # expect here that one of the last two entries will be removed

@show unique(tmp_data2[6:12]) # when I call it like this, last two items are actually deduplicated

# yet:
@show hash(tmp_data2[11]) == hash(tmp_data2[12]) # true
@show tmp_data2[11] == tmp_data2[12] # true"><pre class="notranslate"><span class="pl-k">using</span> JLD

type A1
    v1<span class="pl-k">::</span><span class="pl-c1">String</span>
    v2<span class="pl-k">::</span><span class="pl-c1">String</span>
<span class="pl-k">end</span>
type B1
    val<span class="pl-k">::</span><span class="pl-c1">A1</span>
    tag<span class="pl-k">::</span><span class="pl-c1">String</span>    
<span class="pl-k">end</span>

<span class="pl-c1">@load</span> <span class="pl-s"><span class="pl-pds">"</span>bugreport1.jld<span class="pl-pds">"</span></span> tmp_data2
Base<span class="pl-k">.</span><span class="pl-en">hash</span>(x<span class="pl-k">::</span><span class="pl-c1">A1</span>) <span class="pl-k">=</span> <span class="pl-c1">hash</span>((x<span class="pl-k">.</span>v1, x<span class="pl-k">.</span>v2))
Base<span class="pl-k">.</span><span class="pl-en">hash</span>(x<span class="pl-k">::</span><span class="pl-c1">B1</span>) <span class="pl-k">=</span> <span class="pl-c1">hash</span>((<span class="pl-c1">hash</span>(x<span class="pl-k">.</span>tag), <span class="pl-c1">hash</span>(x<span class="pl-k">.</span>val)))
<span class="pl-k">import</span> Base<span class="pl-k">.==</span>
<span class="pl-k">==</span>(x<span class="pl-k">::</span><span class="pl-c1">B1</span>, y<span class="pl-k">::</span><span class="pl-c1">B1</span>) <span class="pl-k">=</span> x<span class="pl-k">.</span>tag <span class="pl-k">==</span> y<span class="pl-k">.</span>tag <span class="pl-k">&amp;&amp;</span> x<span class="pl-k">.</span>val<span class="pl-k">.</span>v1 <span class="pl-k">==</span> y<span class="pl-k">.</span>val<span class="pl-k">.</span>v1 <span class="pl-k">&amp;&amp;</span> x<span class="pl-k">.</span>val<span class="pl-k">.</span>v2 <span class="pl-k">==</span> y<span class="pl-k">.</span>val<span class="pl-k">.</span>v2

<span class="pl-c1">@show</span> tmp_data2 <span class="pl-c"><span class="pl-c">#</span> 12 items in the array with last two duplicated</span>

<span class="pl-c1">@show</span> <span class="pl-c1">unique</span>(tmp_data2[<span class="pl-c1">1</span><span class="pl-k">:</span><span class="pl-c1">12</span>]) <span class="pl-c"><span class="pl-c">#</span> expect here that one of the last two entries will be removed</span>

<span class="pl-c1">@show</span> <span class="pl-c1">unique</span>(tmp_data2[<span class="pl-c1">6</span><span class="pl-k">:</span><span class="pl-c1">12</span>]) <span class="pl-c"><span class="pl-c">#</span> when I call it like this, last two items are actually deduplicated</span>

<span class="pl-c"><span class="pl-c">#</span> yet:</span>
<span class="pl-c1">@show</span> <span class="pl-c1">hash</span>(tmp_data2[<span class="pl-c1">11</span>]) <span class="pl-k">==</span> <span class="pl-c1">hash</span>(tmp_data2[<span class="pl-c1">12</span>]) <span class="pl-c"><span class="pl-c">#</span> true</span>
<span class="pl-c1">@show</span> tmp_data2[<span class="pl-c1">11</span>] <span class="pl-k">==</span> tmp_data2[<span class="pl-c1">12</span>] <span class="pl-c"><span class="pl-c">#</span> true</span></pre></div>
<p dir="auto">On Julia 0.5 and it looks like <code class="notranslate">unique</code> is not removing elements even though they are equal to each other and hash to the same value.</p>