Why does this not work?

I wanted to find the first line of a matrix which is all -1 s. I am surprised the following does not work.
What is going on here?

julia> findfirst(l->all(y->y==-1,l),eachrow([1 1;-1 -1]))
ERROR: MethodError: no method matching keys(::Base.Generator{Base.OneTo{Int64},Base.var"#192#193"{Array{Int64,2}}})
Closest candidates are:
  keys(::Cmd) at process.jl:638
  keys(::Core.SimpleVector) at essentials.jl:603
  keys(::LibGit2.GitTree) at /home/jmichel/.julia/packages/Revise/nWJXk/src/git.jl:52
  ...
Stacktrace:
 [1] pairs(::Base.Generator{Base.OneTo{Int64},Base.var"#192#193"{Array{Int64,2}}}) at ./abstractdict.jl:134
 [2] findfirst(::var"#5#7", ::Base.Generator{Base.OneTo{Int64},Base.var"#192#193"{Array{Int64,2}}}) at ./array.jl:1854
 [3] top-level scope at REPL[1]:1

Broadcast?

julia> findfirst.(l->all(y->y==-1,l),eachrow([1 1;-1 -1]))
2-element Vector{Union{Nothing, Int64}}:
  nothing
 1
1 Like

The question is not how to do it differently, but why does it not work? By the way, your solution is less efficient than the desired one, since it checks all lines of the matrix (and allocates a vector of booleans).

Sorry: the reason is that findfirst doesn’t work with generators, as the error message suggests: Define `findfirst` for generators · Issue #16884 · JuliaLang/julia · GitHub

julia> findfirst(x -> x > 5, (i for i ∈ 1:10))
ERROR: MethodError: no method matching keys(::Base.Generator{UnitRange{Int64}, typeof(identity)})

Hence one other way (but again presumably less efficient than it could theoretically be if we iterated over the generator) is to collect:

julia> findfirst(l->all(y->y==-1,l),collect(eachrow([1 1;-1 -1])))
2

I’m sure someone will be along soon to provide an efficient solution…

1 Like

Thank for the pointer to the ticket. It does not seem too difficult to implement findfirst just relying on the
iteration protocol, just having a counter, so I do not understand why it has not been implemented for all iterators…