Why is this snippet of code type instable

Hello, I have the following very “simple” code

f(Λ, inds) where {T,N} = Λ[inds...] *= -1 
x = [1,2,3,4]
@code_warntype f(x, [1:2])

But this seams to be type unstable:

Variables:
  #self# <optimized out>
  Λ::Array{Int64,1}
  inds::Array{UnitRange{Int64},1}

Body:
  begin
      (Core._apply)(test.setindex!, (Core.tuple)(Λ::Array{Int64,1}, -1)::Tuple{Array{Int64,1},Int64}, inds::Array{UnitRange{Int64},1})::Any
      return -1
  end::Int64
nothing

Why is it so? And what would be the right way to multiply (apply a function) on some values of an Array without allocation and with type stability… I cannot figure it out.

Must be some other method that is left over from an earlier experiment, since

julia> f(Λ, inds) where {T,N} = Λ[inds...] *= -1
WARNING: static parameter T does not occur in signature for f at REPL[5]:1.
The method will not be callable.
WARNING: static parameter N does not occur in signature for f at REPL[5]:1.
The method will not be callable.
f (generic function with 1 method)

julia> x = [1,2,3,4]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> f(x, [1:2])
ERROR: MethodError: no method matching f(::Array{Int64,1}, ::Array{UnitRange{Int64},1})
Closest candidates are:
  f(::Any, ::Any) where {T, N} at REPL[5]:1

However, I think that the crux of the issue (if you remove the where clause) is that you are splicing (...) an ex ante unknown number of indices to the arguments of getindex ([]), so the signature cannot be determined in advance.

Ah, yeah, the where argument was indeed from the test before…

I understand the issue but is there another way of doing it?

How about a loop?

julia> function f(x, inds)
         for i in inds
           x[i] *= -1
         end
       end
f (generic function with 1 method)

julia> using BenchmarkTools

julia> @btime f($[1,2,3,4], 1:2)
  3.713 ns (0 allocations: 0 bytes)

or a view(), which should be pretty fast in v0.7.

1 Like