Keyword vs Optional Function Arguments?

What is the difference between a keyword and an optional argument? Arguments with default values on the left of the semi-colon are optional, but the same arguments on the right are keys. Do they behave differently? When do you use each? Thank you!

function f(a1, opta2=2; key="keyy")
   println("normal argument: $a1")
   println("optional argument: $opta2")
   println("keyword argument: $key")
end
f (generic function with 2 methods)

There are a variety of differences, but I’d start by answering the question: do you want the caller to specify the name of the argument or not? If you want them to write out the name, use a keyword argument. If you want them to not write out the name, use an optional positional argument.

2 Likes

Firstly, note that the divide is between keyword arguments and positional arguments. Keyword arguments can be made mandatory (by not giving them a default value) or optional, and the examples in your question show optional keyword arguments and optional positional arguments.

As for the difference,

  • In terms of interface, optional positional arguments are generally values that are part of the core operation of the function, that happen to have sane default values. They are things that you would expect to be part of the function signature. Keyword arguments are more likely to be used for tweaks and enhancements to the core task of the function, that are useful only in specific scenarios. This is a general guideline with a lot of exceptions though.
  • In terms of the language and performance, keyword arguments don’t participate in multiple dispatch. So, you can’t specialize on their type, and cannot create different methods based on them.
julia> fun(positional::Int) = 42
fun (generic function with 1 method)

julia> fun(positional::Float64) = 42.0
fun (generic function with 2 methods)

With a positional argument (whether it’s optional or not), specializing for a different type (Int and Float64 above) creates a new method, so fun above has 2 methods now. (This is the core of Julia’s multiple dispatch and allows very efficient compiled code to be generated, so can matter a lot for performance.)

julia> func(; keyword::Int) = 42
func (generic function with 1 method)

julia> func(; keyword::Float64) = 42.0
func (generic function with 1 method)

With a keyword argument (again, whether optional or not), specifying a new type for the keyword argument just redefines the function, so we only have 1 method for func in the end.

8 Likes