JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.92k stars 5.49k forks source link

Length, filter and generators #18866

Closed my-little-repository closed 8 years ago

my-little-repository commented 8 years ago

There seems to be a missing method for length when used on a filtered generator.

julia> length(i for i = 1:5)
5
length(filter(i -> i>3, i for i = 1:5))
ERROR: MethodError: no method matching       length(::Filter{##183#185,Base.Generator{UnitRange{Int64},##184#186}})
Closest candidates are:
  length(!Matched::SimpleVector) at essentials.jl:168
  length(!Matched::Base.MethodList) at reflection.jl:256
  length(!Matched::MethodTable) at reflection.jl:322
  ...

This is loosely connected to #16884 which reports a missing method for findfirst.

Note that count(x -> true, filter(i-> i>2, (i for i = 1:5))) works but it is a bit weird to compute the length that way.

Keno commented 8 years ago

length can't be defined on a lazy filter, without evaluating the whole filter (or a theorem prover I suppose). There has been some discussion of making the default filter eager, but for now, use one of length(collect(filter(i -> i>3, i for i = 1:5))) or count(i->i>3, i for i = 1:5) (if you're only interested in the count, the latter is better).

JeffBezanson commented 8 years ago

Yes, this is intentional. length is not too useful if it requires running through the whole iterator, which is why we also have count.

We could add a 1-argument method to count, but I fear it would be unclear whether it counts all elements, or elements equal to true (more like the existing 2-argument method).

TotalVerb commented 8 years ago

In Python, it is idiomatic to do sum(1 for x in xs). This should work in Julia too, at least on nightly since #18695 was merged.