# Initialize multiple variables in one line

Hello,
I would like to initialize multiple variables in one line.
The following code does not work:

``````a = b = c = Set{Symbol}()
``````

If I do:

``````push!(a, :test)
``````

all three variables get the same value.
I just want to initialize all of them as empty set of Symbols, but later they shall contain different values.
Any idea how to achieve this in one line?

``````a = Set{Symbol}(); b = Set{Symbol}(); c = Set{Symbol}()
``````
4 Likes

This should work too:

``````a, b, c = Set{Symbol}(), Set{Symbol}(), Set{Symbol}()
``````

Perhaps this might work as well

``````a, b, c = repeat([Set{Symbol}()], 3)
``````

Edit: Nope 1 Like

Well, in reality I do not have to initialize three variables, but more. So a shorter notation would be nice to have.

This would be nice. Any idea for a solution that is as short as this one, but works?

``````a, b, c = [Set{Symbol}() for _ = 1:3]
``````
5 Likes

This doesn not work:

``````a,b,c =Tuple(repeat([Set{Symbol}()], 3))
``````

Same problem, if I change on of the variables the others get changed too.

``````a, b, c = [Set{Symbol}() for _ = 1:3]
``````

Looks good! Thank you!

2 Likes

Works for me on v1.0.3 and v1.2.0?

``````julia> a, b, c = repeat([Set{Symbol}()], 3)
3-element Array{Set{Symbol},1}:
Set([])
Set([])
Set([])

julia> a
Set(Symbol[])

julia> b
Set(Symbol[])

julia> c
Set(Symbol[])

julia>
``````

But if you change one variable, you change all. So not a valid solution.

Save an allocation by not using an array:

``````a, b, c = (Set{Symbol}() for _ = 1:3)
``````

or

``````a, b, c = ntuple(_->Set{Symbol}(), 3)
``````
4 Likes

Thank you for your advanced suggestions! The proposed solutions still seem to violate DRY (a bit ) because the number of the variables on the left-hand side of the assignment must match the number on the right-hand side. Unfortunately I don’t see a way to fix this without a macro. Perhaps the following:

``````macro multidef(ex)
@assert(ex isa Expr)
vars = ex.args.args
what = ex.args
rex = quote end
for var in vars
push!(rex.args, :(\$(esc(var)) = \$what))
end
rex
end
``````

It can be used as follows:

``````@multidef a, b, c = Set{Symbol}()
``````

Which has the right outcome:

``````julia> a,b,c
(Set(Symbol[]), Set(Symbol[]), Set(Symbol[]))

julia> a===b
false
``````
6 Likes

Thanks for this beautiful macro!
But it is only useful if you really use it a lot, otherwise it has too much overhead.

just curious, why didn’t you have the `esc` around `what`?

1 Like

You’re right, it probably makes sense to `esc` the `what` as well.

Here it is for the record. I find it super useful, also to learn about writing macros, thanks for sharing!

``````macro multidef(ex)
@assert(ex isa Expr)
vars = ex.args.args
what = ex.args
rex = quote end
for var in vars
push!(rex.args, :( \$(esc(var)) = \$(esc(what)) ))
end
rex
end
``````
3 Likes

What is the benefit of using the second approach, tuple comprehension? How allocation is saved?

``````julia> testarray() = [Set{Symbol}() for _ = 1:3]

julia> testtuple() = (Set{Symbol}() for _ = 1:3)

julia> (vector = (@allocated testarray()), tuple = (@allocated testtuple()))
(vector = 1552, tuple = 0)
``````

Vectors are not of an unchangeable length, so we can add elements to them; they are stored indirectly. Tuples are fixed in size and other ways, so they are stored directly (immediately in very fast microprocessor-accessible memory).

3 Likes