# Optional elements in vector literal

**URL:** <https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963>\
**Category:** General Usage\
**Created:** [December 21, 2022, 3:45pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963 "2022-12-21T15:45:22Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)\
**Post date:** [December 21, 2022, 3:45pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/1 "2022-12-21T15:45:22Z")

</div>

is there a nice way to optionally include an element in a vector literal construction? something like `foo = [1, 2, @maybe x 3, 4, 5]` where only if `x==true` is 3 included.

---

<div class="post-metadata">

**Author:** ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)\
**Post date:** [December 21, 2022, 3:45pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/2 "2022-12-21T15:45:46Z")

</div>

answering myself, i suppose `insert!` is good enough: `foo=[1,2,4,5]; insert!(foo, 3, 3)`

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 21, 2022, 4:00pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/3 "2022-12-21T16:00:44Z")

</div>

This may depend on what you mean by “literal”. `insert!` is not really a literal syntax because a temporary array is getting constructed and then manipulated. For a true literal, we would want to achieve the result at construction.

```julia
julia> x = true
true

julia> foo = [y for (i,y) in pairs(1:5) if i!=3 || x]
5-element Vector{Int64}:
 1
 2
 3
 4
 5

julia> x = false
false

julia> foo = [y for (i,y) in pairs(1:5) if i!=3 || x]
4-element Vector{Int64}:
 1
 2
 4
 5

julia> f(x) = [y for (i,y) in pairs(1:5) if i!=3 || x]
f (generic function with 2 methods)

julia> @code_lowered f(true)
CodeInfo(
1 ─ #33 = %new(Main.:(var"#33#35"))
│ %2 = #33
│ %3 = Main.:(var"#34#36")
│ %4 = Core.typeof(x)
│ %5 = Core.apply_type(%3, %4)
│ #34 = %new(%5, x)
│ %7 = #34
│ %8 = 1:5
│ %9 = Main.pairs(%8)
│ %10 = Base.Filter(%7, %9)
│ %11 = Base.Generator(%2, %10)
│ %12 = Base.collect(%11)
└── return %12
)

```

The array comprehension syntax gets lowered to several layers of lazy iterators before being collected. Only at collection is the array allocated and formed. Notably see `Iterators.filter` which creates a `Iterators.Filter`.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [December 21, 2022, 4:21pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/4 "2022-12-21T16:21:13Z")

</div>

This also works:

```julia
using Base.Iterators

g(x) = collect(flatten([[1,2],x ? [3] : Int[],[4,5]]))

```

and

```julia
julia> g(false) == [1,2,4,5]
true

julia> g(true) == [1,2,3,4,5]
true

```

With this method, in case `x` is false, the unincluded element is not even materialized or computed (especially important for complex elements).

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 21, 2022, 4:29pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/5 "2022-12-21T16:29:20Z")

</div>

Using `Iterators.flatten` is nice. Do note that a type assertion might be good for the return type since the method is currently type unstable. The array comprehension is type stable.

```julia
julia> f(x) = [y for (i,y) in pairs(1:5) if i!=3 || x]
f (generic function with 2 methods)

julia> @code_warntype f(true)
MethodInstance for f(::Bool)
  from f(x) in Main at REPL[114]:1
Arguments
  #self#::Core.Const(f)
  x::Bool
Locals
  #50::var"#50#52"{Bool}
  #49::var"#49#51"
Body::Vector{Int64}
1 ─ (#49 = %new(Main.:(var"#49#51")))
│ %2 = #49::Core.Const(var"#49#51"())
│ %3 = Main.:(var"#50#52")::Core.Const(var"#50#52")
│ %4 = Core.typeof(x)::Core.Const(Bool)
│ %5 = Core.apply_type(%3, %4)::Core.Const(var"#50#52"{Bool})
│ (#50 = %new(%5, x))
│ %7 = #50::var"#50#52"{Bool}
│ %8 = (1:5)::Core.Const(1:5)
│ %9 = Main.pairs(%8)::Core.Const(Base.Pairs(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5))
│ %10 = Base.Filter(%7, %9)::Core.PartialStruct(Base.Iterators.Filter{var"#50#52"{Bool}, Base.Pairs{Int64, Int64, LinearIndices{1, Tuple{Base.OneTo{Int64}}}, UnitRange{Int64}}}, Any[var"#50#52"{Bool}, Core.Const(Base.Pairs(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5))])
│ %11 = Base.Generator(%2, %10)::Core.PartialStruct(Base.Generator{Base.Iterators.Filter{var"#50#52"{Bool}, Base.Pairs{Int64, Int64, LinearIndices{1, Tuple{Base.OneTo{Int64}}}, UnitRange{Int64}}}, var"#49#51"}, Any[Core.Const(var"#49#51"()), Core.PartialStruct(Base.Iterators.Filter{var"#50#52"{Bool}, Base.Pairs{Int64, Int64, LinearIndices{1, Tuple{Base.OneTo{Int64}}}, UnitRange{Int64}}}, Any[var"#50#52"{Bool}, Core.Const(Base.Pairs(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5))])])
│ %12 = Base.collect(%11)::Vector{Int64}
└── return %12

julia> g(x) = collect(flatten(( (1,2), x ? (3,) : (), (4,5) )))
g (generic function with 1 method)

julia> @code_warntype g(true)
MethodInstance for g(::Bool)
  from g(x) in Main at REPL[116]:1
Arguments
  #self#::Core.Const(g)
  x::Bool
Locals
  @_3::Union{Tuple{}, Tuple{Int64}}
Body::Any
1 ─ %1 = Core.tuple(1, 2)::Core.Const((1, 2))
└── goto #3 if not x
2 ─ (@_3 = Core.tuple(3))
└── goto #4
3 ─ (@_3 = ())
4 ┄ %6 = @_3::Union{Tuple{}, Tuple{Int64}}
│ %7 = Core.tuple(4, 5)::Core.Const((4, 5))
│ %8 = Core.tuple(%1, %6, %7)::Core.PartialStruct(Tuple{Tuple{Int64, Int64}, Union{Tuple{}, Tuple{Int64}}, Tuple{Int64, Int64}}, Any[Core.Const((1, 2)), Union{Tuple{}, Tuple{Int64}}, Core.Const((4, 5))])
│ %9 = Main.flatten(%8)::Base.Iterators.Flatten
│ %10 = Main.collect(%9)::Any
└── return %10

```

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [December 21, 2022, 4:33pm UTC](https://discourse.julialang.org/t/optional-elements-in-vector-literal/91963/6 "2022-12-21T16:33:27Z")

</div>

Yes, you’re right, I thought the `Int[]` in the definition would be enough for inference, but adding `Vector{Int}` is enough:

```julia
g(x) = collect(flatten(Vector{Int}[[1,2],x ? [3] : Int[],[4,5]]))

```

and:

```julia
julia> @code_warntype g(false)
...
│ %11 = Main.collect(%10)::Vector{Int64}
└── return %11

```

Actually, the problem was with the tuples, which made `flatten` unstable. Perhaps a good compromise is:

```julia
g(x) = collect(flatten(( (1,2), x ? [3] : Int[], (4,5) )))

```

which is type stable.
