Optional argument is a struct

Hello,
I have a function that takes say 3 arguments fun(a,b,c), where they are all structs I defined and the third one is optional.
If the third one is present, then I’ll need to call fun2.
What’s a clean way to do this? I could simply do

fun(a,b,c=nothing)
    if !c==nothing
        fun2()
    end
...

But that would be type unstable, right? I could also have c be a struct with default values, maybe one of them being exists and defaulting to true and do

fun(a,b,c=Struct3(defined=false))
    if c.defined
        fun2()
    end
...

But that forces me to set defaults to c, which I’d rather not have.
Any ideas?
Thanks a lot!

Define your fun2 as a method of fun:

fun(a, b, c) = ...
fun(a, b) = .... # this is your fun2

That is what Julia is all about: multiple dispatch!

5 Likes

Yep, that would work, but fun is actually a pretty long function that I’d rather not duplicate.

Can you not factor out what is needed by both methods into, say, _fun, and then call that from both methods?

3 Likes

No, it’s totally fine. Just make sure you use === or !== (its opposite) for checking for nothing. Only one possible value is === nothing, and that’s nothing itself, so the compiler will be able to figure out which branch of the if statement is taken just from the type of c alone (by checking if that type is Nothing or something else).

Having an optional argument default to nothing and then checking if c !== nothing in the body of the function is a totally reasonable thing to do in Julia.

4 Likes

I’ll share some advice I was given.

  1. Define a function _fun that does the bulk of the work. Then have methods fun(a, b, c) and fun(a, b) both call _fun internally but with different pre- and post-processing above and below respectively.
  2. You can use a distinct struct rather than nothing to define methods for your different cases: Application Code Organization - #15 by lmiq.
2 Likes

Thanks, folks. I’ll stick to the nothing approach for now.