That’s a good point that touches the corner of Julia I wish I can ignore Basically, the code without tuple-wrapping is working “by accident” (in some sense). It’s actually nothing to do with parallelism. Consider the implementations of collect
with and without the tuple-wrapping;
julia> function collect1(xs)
ys = Any[]
for x in xs
append!(ys, x) # no tuple
end
return ys
end;
julia> function collect2(xs)
ys = Any[]
for x in xs
append!(ys, (x,)) # tuple
end
return ys
end;
As you’ve observed, there is no difference if the input is a collection of numbers (which is a singleton collection of itself):
julia> collect1(1:3)
3-element Vector{Any}:
1
2
3
julia> collect2(1:3)
3-element Vector{Any}:
1
2
3
However, your version won’t work when each element is also a collection (note: Base.collect(1 => 2) == [1, 2]
):
julia> collect1(x => x^2 for x in 1:3)
6-element Vector{Any}:
1
1
2
4
3
9
julia> collect2(x => x^2 for x in 1:3)
3-element Vector{Any}:
1 => 1
2 => 4
3 => 9
In other words, you are observing that
for e in x
...
end
and
for e in (x,)
...
end
are equivalent if x isa Number
.
So, in the examples using Int
, you are correct that there is no need to use a tuple. However, since this is a tutorial, it is important to demonstrate the fundamental pattern in parallel computing:
- Create a singleton solution (e.g., the singleton tuple)
- Combine the solutions (e.g.,
append!
)
I was hoping that explicitly constructing the singleton solution like (x,)
helps the readers to familiarize themselves with this pattern.