Search code examples
parametersjuliakeyword-argument

Can a Julia named parameter be required to be present?


In Ruby, I can require an argument both (1) appear, and (2) have a parameter name:

>> def f(x:)
>>   x + 1
>> end

>> f()
ArgumentError: missing keyword: x 
>> f(2)
ArgumentError: wrong number of arguments (given 1, expected 0)
>> f(x:7)
=> 8

That is, I have to pass the argument, and I have to supply the associated parameter name.

I can do the same in Python:

>>> def f(*, x):
...   return x + 1
... 
>>> f()
TypeError: f() missing 1 required keyword-only argument: 'x'
>>> f(3)
TypeError: f() takes 0 positional arguments but 1 was given
>>> f(x=7)
8

And, for good measure, even Swift can do this:

1> func f(x: Int) -> Int {return x + 1}
2> f()
error: missing argument for parameter 'x' in call
2> f(3)
error: missing argument label 'x:' in call
2> f(x:7)
$R0: Int = 8

But I cannot figure out how to do this in Julia. It seems that keyword arguments, as they are called, must take default parameters. Is this correct, or is there a way to simulate the Ruby and Python examples above?


Solution

  • Julia 0.7 and 1.x

    In Julia 0.7 (which was the compatibility release with all 1.0 features), this ability was added PR #25830.

    To specify a required keyword argument list it after the ; but do not provide a default value:

    julia> f(; x) = x + 1
    f (generic function with 1 method)
    
    julia> f(;x=3)
    4
    
    julia> f()
    ERROR: UndefKeywordError: keyword argument x not assigned
    

    Julia 0.6 and earlier

    This is correct. In julia you cannot have required keyword arguments. Key word arguments are a special type of optional argument -- one which is set by by name, rather than by position.

    (Related to this: you cannot set a non-keyword argument by name -- which you can do in Python and C#.)

    You can, as @amrods suggested ensure this at runtime.

    I would do that with

    function f(; x = nothing)
        x===nothing && error("x not set.")
        #...
    end
    

    That check will be optimized out, if they type of x is known (inferred) at the caller, at compile type.

    but it won't actually be enforced until run-time. You also could use @Fengyang very elegant way to achieve the same.

    You could probably enforce this at compile time by replacing your function with a generated function. But it is an awful hack.