Optional arguments in Julia v0.6

question

#1

Is there any trick to handle optional arguments in Julia? Sometimes I want to setup some of the arguments of a function for the user, however; this setup is not necessarily straightforward that I could just pass a default value in a keyword argument. Consider the function below:

function f(; b=nothing)
  if b != nothing
    # assertions to make sure b is of the right type
  end
  println(b)
end

If the user specifies b, I need to assert its type, but it seems that I am reinventing the wheel here. There is probably a better way of handling this situation? I was thinking of something like Nullable in Julia v0.6, but I am not very familiar with it. In C++, I would use Boost.Optional.


#2

You can just do b::Union{T, Void}, with T the type you would like to assert.


#3

If speed is a concern on v0.6, you might also consider using b::Nullable{T} = Nullable{T}(). I think this the same as an optional in C++.

(Note: the Union approach will be fast on v0.7/v1.0)


#4

Thank you all, could you please elaborate on the differences between Union{T,Void} and Nullable{T}? What is the advantage/disadvantage of each approach when modeling optional arguments?


#5

b::Nullable{T} is a container - you will need to check if it contains data with isnull(b) and then use get (or getindex) to extract the data of type T. Also, the code calling the function may need to explicitly wrap the data in a Nullable{T}

b::Union{T, Void} will be an “unboxed” T or else a nothing. You can check if b === nothing (or b isa Void) and if not you can assume that b is the data (of type T) you want. Your code example in the OP more-or-less does this already (maybe you want !== rather than != to help inference? not sure…)

Really, it’s just a difference in style. In a static language like C++ the container is quite necessary. In a dynamic language like Julia, both options are available and arguably the Union approach is somewhat simpler to work with. The upcoming Union performance improvements (as fast as Nullable) will mean that Unions will probably be the preferred approach in the future - but both options will remain open to you. If your function isn’t performance critical (say, called in an inner loop of a numeric algorithm), feel free to use the Union approach now - it won’t slow you down by that much, really (and inference on v0.6 seems good enough that type instabilities won’t propagate).


#6

Thank you for the very clear explanation @andyferris :thumbsup: I personally like the Union type more and the fact that by using it instead of Nullable we don’t need to wrap the input in the call site.