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 :cry:

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?

How about

a, b, c = [Set{Symbol}() for _ = 1:3]
4 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! :slight_smile:

Thank you!

1 Like

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! :smiley:

The proposed solutions still seem to violate DRY (a bit :wink:) 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)
   @assert(ex.head == :(=))
   vars = ex.args[1].args
   what = ex.args[2]
   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
4 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)
    @assert(ex.head == :(=))
    vars = ex.args[1].args
    what = ex.args[2]
    rex = quote end
    for var in vars
       push!(rex.args, :( $(esc(var)) = $(esc(what)) ))
    end
    rex
end
1 Like

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