Ray*_*oal 1 parameters keyword-argument julia
在Ruby中,我可以要求参数(1)出现,(2)有参数名称:
>> 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
Run Code Online (Sandbox Code Playgroud)
也就是说,我必须传递参数,并且我必须提供相关的参数名称.
我可以在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
Run Code Online (Sandbox Code Playgroud)
而且,为了更好的衡量,即使是Swift也可以这样做:
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
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何在朱莉娅这样做.似乎关键字参数,因为它们被调用,必须采用默认参数.这是正确的,还是有办法模拟上面的Ruby和Python示例?
它可以与Ruby或Python相同的方式实现.事实上,它可以很简单
julia> f(x, y; z=error()) = 1
f (generic function with 1 method)
julia> f(1, 2)
ERROR:
in f(::Int64, ::Int64) at ./REPL[65]:1
Run Code Online (Sandbox Code Playgroud)
但那个错误信息很糟糕.所以我们可以抛出更好的错误:
julia> f(x, y; z=throw(ArgumentError("z is required"))) = x + y + z
f (generic function with 1 method)
julia> f(1, 2)
ERROR: ArgumentError: z is required
in f(::Int64, ::Int64) at ./REPL[25]:1
julia> f(1, 2, z=3)
6
Run Code Online (Sandbox Code Playgroud)
正如oxinabox所提到的,错误是在运行时而不是编译时发现的,但这与Python或Ruby相同.
如果这太冗长,那么制作一个宏很容易:
macro required(ex)
esc(Expr(:kw, ex, :(throw(ArgumentError("$($("$ex")) is required"))))
end
Run Code Online (Sandbox Code Playgroud)
那么你可以做到
julia> foo(x, y; @required(z), @required(w), n=4) = x + y + z + w + n
foo (generic function with 1 method)
julia> foo(1, 2)
ERROR: ArgumentError: z is required
in foo(::Int64, ::Int64) at ./REPL[59]:1
julia> foo(1, 2, z=3)
ERROR: ArgumentError: w is required
in (::#kw##foo)(::Array{Any,1}, ::#foo, ::Int64, ::Int64) at ./<missing>:0
julia> foo(1, 2, z=3, w=4)
14
julia> foo(1, 2, z=3, w=4, n=5)
15
Run Code Online (Sandbox Code Playgroud)
这样做的原因是在没有传递参数时会计算默认参数.通过阻止成功计算默认参数,这需要用户传递参数.
这是对的.在julia中,您不能拥有必需的关键字参数.关键字参数是一种特殊类型的可选参数 - 一个是按名称设置的,而不是按位置设置的.
(与此相关:您不能按名称设置非关键字参数 - 您可以在Python和C#中执行此操作.)
您可以像@amrods建议的那样在运行时确保这一点.
我会这样做的
function f(; x = nothing)
x===nothing && error("x not set.")
#...
end
Run Code Online (Sandbox Code Playgroud)
如果x
调用者在编译类型中已知(推断)它们的类型,那么该检查将被优化.
但直到运行时才会实际执行.你也可以使用@Fengyang 非常优雅的方式来实现同样的目的.
您可以在编译时通过用生成的函数替换函数来强制执行此操作.但这是一个可怕的黑客.