# Base.take does not respect that the argument has SizeUnknown()? (0.5.0)

**URL:** <https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 16, 2017, 12:22pm UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509 "2017-01-16T12:22:42Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jpiitula](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpiitula/32/471_2.png) [@jpiitula](https://discourse.julialang.org/u/jpiitula)\
**Post date:** [January 16, 2017, 12:22pm UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/1 "2017-01-16T12:22:42Z")

</div>

At least `Base.take` and `Base.drop` seem to ignore that their argument iterator has `SizeUnknown()`, which in turn makes `collect(take(...))` crash with “MethodError: no method matching length” when there in fact is no length method for the argument. I found [related issues from 2015](https://github.com/JuliaLang/julia/issues/12009), when I think `Base.iteratorsize` was not there yet, but is this still an issue, or am I doing something wrong here?

I’m playing with the precompiled Julia 0.5.0 (64-bit generic Linux) binary to see how well the new generator machinery now works. The point of this test case is that it has random length.

```julia
module GenerationExploration

export Pool
import Base: start, done, next, iteratorsize

immutable Pool ; data end

Base.start(pool::Pool) = nothing
Base.done(pool::Pool, state) = rand(1:10) == 1
Base.next(pool::Pool, state) = rand(pool.data), state
Base.iteratorsize(::Pool) = Base.SizeUnknown()

# julia> using GenerationExploration
# 
# julia> Base.iteratorsize(Pool(['3', '1']))
# Base.SizeUnknown()
# 
# julia> Base.iteratorsize(take(Pool(['3', '1']), 2))
# Base.HasLength()
#
# Why does Base.take think it HasLength() when a Pool clearly tells it
# that it has not?

end # module

```

---

<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:** [January 16, 2017, 1:33pm UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/2 "2017-01-16T13:33:22Z")

</div>

Pretty sure it should be:

```julia
Base.iteratorsize(::Type{Pool}) = Base.SizeUnknown()

```

I did the same mistake before in a package, which got fixed by a PR 🙂 ([fix methods of iterator interface by bicycle1885 · Pull Request #14 · JuliaLang/Tokenize.jl · GitHub](https://github.com/KristofferC/Tokenize.jl/pull/14/files)).

---

<div class="post-metadata">

**Author:** ![jpiitula](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpiitula/32/471_2.png) [@jpiitula](https://discourse.julialang.org/u/jpiitula)\
**Post date:** [January 16, 2017, 2:14pm UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/3 "2017-01-16T14:14:18Z")

</div>

Aha! Yes, that does it! Much thanks indeed.

I added also `eltype` and now things are nice again. (But I do have a feeling that this is not the last time I’m going to be blind to this same mistake. Awkward.)

```julia
module GenerationExploration

export Pool
import Base: start, done, next
import Base: iteratorsize, iteratoreltype, eltype

immutable Pool{T} ; data::Array{T} end

Base.start(pool::Pool) = nothing
Base.done(pool::Pool, state) = rand(1:10) == 1
Base.next(pool::Pool, state) = rand(pool.data), state
Base.iteratorsize{T}(::Type{Pool{T}}) = Base.SizeUnknown()
Base.iteratoreltype{T}(::Type{Pool{T}}) = Base.HasEltype()
Base.eltype{T}(::Type{Pool{T}}) = T

# now it works with Base.take and Base.drop
end # module

```

---

<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:** [January 17, 2017, 7:53am UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/4 "2017-01-17T07:53:53Z")

</div>

As a comment, there is no need for the `{T}` stuff in

`Base.iteratorsize{T}(::Type{Pool{T}}) = Base.SizeUnknown()`

since you are not using `T` either in the function body or for dispatch. `Type{Pool}` will work just as well.

---

<div class="post-metadata">

**Author:** ![jpiitula](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jpiitula/32/471_2.png) [@jpiitula](https://discourse.julialang.org/u/jpiitula)\
**Post date:** [January 17, 2017, 8:36am UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/5 "2017-01-17T08:36:34Z")

</div>

Thanks, but the `{T}` in `iteratorsize` seems necessary. Without it, I observe that `iteratorsize` reports that a `Pool` now `HasLength()`, which is the default.

Am I using the type parameter for dispatch, or am I not?

I can remove `{T}` from my `iteratoreltype` without breaking my current tests. Not sure what the difference is.

---

<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:** [January 17, 2017, 8:37am UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/6 "2017-01-17T08:37:59Z")

</div>

Yes, sorry, my mistake! `Type`s are not covariant so I was indeed wrong.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [January 17, 2017, 7:23pm UTC](https://discourse.julialang.org/t/base-take-does-not-respect-that-the-argument-has-sizeunknown-0-5-0/1509/7 "2017-01-17T19:23:17Z")

</div>

Perhaps

```julia
Base.iteratorsize{T<:Pool}(::Type{T}) = Base.SizeUnknown()

```
