Interesting question. I doubt this is the best answer, but:
julia> A × B = (Iterators.Flatten((a, b)) for a in A for b in B)
× (generic function with 1 method)
julia> reduce(×, 0:4 for _ in 1:3)
Base.Iterators.Flatten{Base.Generator{Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}, var"#52#53"{UnitRange{Int64}}}}(Base.Generator{Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}, var"#52#53"{UnitRange{Int64}}}(var"#52#53"{UnitRange{Int64}}(0:4), Base.Iterators.Flatten{Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}}(Base.Generator{UnitRange{Int64}, var"#52#53"{UnitRange{Int64}}}(var"#52#53"{UnitRange{Int64}}(0:4), 0:4))))
julia> collect(collect(i) for i in ans)
125-element Vector{Vector{Int64}}:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
# ...
where the ×
operator defined above might be the rare legitimate use case for defining infix operators as discussed in this other thread from today: Does anybody use the syntax `a <operator> b = ...` to define new methods for operators? - #8 by dylanxyz
This could be a useful feature in Combinatorics.jl.