How namespace of Base.Iterators works

I like to code using more functional-like style working with iterators, so Base.Iterators comes in handy, but I have problem understanding how its namespace is structured.

  • It is part of the Base, yet it is not by default loaded in your namespace.
  • If you load it you need full name Base.Iterators not just Iterators.
  • Some commands are always available (zip, enumerate), others do not.
  • Even you write using Base.Iterators some commands still need a full name (Iterators.peel), others do not.

I am just confused. Is there any rule to this? The documentation of Iterators seems not to be helping much. I mix this all the time, it is hard to remember what exactly I need to write in each case.

1 Like

Iterators is a submodule of Base. While Iterators exports some symbols, they are not reexported by Base, therefore they are not automatically in scope. You can bring them in scope by writing

using Base.Iterators

This will only bring these symbols into scope that are exported by Iterators. (To see which ones, write names(Iterators)). Non-exported symbols can then be accessed by writing Iterators.some_name.

Maybe looking at the code of Iterators will help you understand: julia/iterators.jl at master · JuliaLang/julia · GitHub.

1 Like

I think the mechanism that causes these inconveniences is not the object of the question, but why some things are reexported, why some are just exported, and why some are not exported nor reexported. Why different decisions were taken for each function, the rhyme and reason for it, and if it is some convention that can be easily remembered.

3 Likes

I agree that that is confusing.

Apparently some of the things that are not re-exported are that way because they have names that would conflict with things from base, for example Base.Iterators.map or Base.Iterators.filter
See this discussion as an example
https://github.com/JuliaLang/julia/pull/34352

And this one from when Base.Iterators was created

https://github.com/JuliaLang/julia/pull/18839

1 Like

Yes, I was asking for some reason/rule or at least where it is written in the documentation. Looking into source code is not very convenient, but at least gives this info.

1 Like

Note that you can use using .Iterators, because it is in fact in your namespace by default, you just don’t have its exports imported (aside from those that are reexported in Base). I think the selection of what is (re)exported and what not is just one of convenience and not set in stone. (I’d vote for an export of peel for example, and maybe reexported flatten, but knowing what is where comes fairly quickly. I’d just always use Iterators.whatever for anything not zip or enumerate.)

1 Like

I forgot about .ModuleName, it’s more elegant, thanks. I guess it is indeed best to always write Iterators.f

I also like peel, often you have a need to do something special during first iteration.