# Avoid ugly 'isempty' pattern

**URL:** <https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 29, 2021, 7:40am UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601 "2021-10-29T07:40:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [October 29, 2021, 7:40am UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/1 "2021-10-29T07:40:29Z")

</div>

Hello!

Through some Discourse posts and my own personal experience, I’ve seen a pattern for `isempty` that repeats a lot, but there is no easy way around it. It is the case for when the result of a function call returns an empty array (it may happen with `nothing` also), and a “default” return is desired instead in that case.

Here is a MWE:

```julia
# 'f' is a computationally expensive function, so it should not be called twice.
# f(x)::Vector{Int64}
default_ = [-1, 1, 0]

# Call to function
a = f(t)

# Return a or 'default' if a is empty
a = isempty(a) ? default_ : a

```

I cannot use `map` because it does not work for empty collections. Is there an easier way to do this?  
Or at least, a way to do it idiomatically (in one line/function call).

Thanks!

---

<div class="post-metadata">

**Author:** ![akb](https://avatars.discourse-cdn.com/v4/letter/a/5daacb/32.png) [@akb](https://discourse.julialang.org/u/akb)\
**Post date:** [October 29, 2021, 7:45am UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/2 "2021-10-29T07:45:53Z")

</div>

For the case of `nothing`, there is

```julia
julia> x=nothing; something(x, 5)
5

```

---

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [October 29, 2021, 9:03am UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/3 "2021-10-29T09:03:23Z")

</div>

I didn’t know about `something`, that’s great!!

Unfortunately, it is still missing the `isempty` case 🙁

---

<div class="post-metadata">

**Author:** ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)\
**Post date:** [October 29, 2021, 11:25am UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/4 "2021-10-29T11:25:25Z")

</div>

You could define your own helper function for the isempty case, analogue to `something`.

```julia
my_something(x,y) = (x === nothing || isempty(x)) ? y : x

```

Note that it is not best practice in Julia to have a function return different types depending on run-time information (different output types for different input types is fine) because this is not type-stable.  
Thus, better write your function `f` such that it always returns the same type, i.e. an array which might be empty.

---

<div class="post-metadata">

**Author:** ![non-Jedi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/non-jedi/32/3645_2.png) [@non-Jedi](https://discourse.julialang.org/u/non-Jedi)\
**Post date:** [October 29, 2021, 12:36pm UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/5 "2021-10-29T12:36:23Z")

</div>

It’s not quite what you’re asking for, but Maybe.jl addresses a similar concern. More often than not, the reason you care about emptiness of an array is because you want to use functions like `first` which assume a nonempty array, and Maybe helps with that problem.

[https://github.com/tkf/Maybe.jl](https://github.com/tkf/Maybe.jl)

On a different note, this topic should be in the Usage discourse category rather than Internals.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 29, 2021, 2:40pm UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/6 "2021-10-29T14:40:28Z")

</div>

I’m not sure how useful is this, but this is an alternative:

```julia
julia> Base.@kwdef mutable struct F
           called::Bool = false
           default::Vector{Int} = [-1,1,0]
       end
F

julia> function (f::F)(t)
           f.called && return f.default
           f.called = true
           # expensive stuff
           return t
       end

julia> f = F()
F(false, [-1, 1, 0])

julia> a = f(1.0)
1.0

julia> a = f(1.0)
3-element Vector{Int64}:
 -1
  1
  0

```

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 29, 2021, 3:28pm UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/7 "2021-10-29T15:28:53Z")

</div>

Is there a reason `f` can’t be modified to return the default value rather than an empty vector?

---

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [October 30, 2021, 4:35pm UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/8 "2021-10-30T16:35:31Z")

</div>

Sometimes the function is not owned by the caller ☹

---

<div class="post-metadata">

**Author:** ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)\
**Post date:** [October 30, 2021, 4:37pm UTC](https://discourse.julialang.org/t/avoid-ugly-isempty-pattern/70601/9 "2021-10-30T16:37:22Z")

</div>

This is close to what I meant, yeah. Thanks!!

On a side note, I put it in Internals because I thought it could spark a conversation about it and maybe push it further down to Base, but yeah, I agree that General Usage is better.
