Parameters 是否需要提供一个命名参数?

Parameters 是否需要提供一个命名参数?,parameters,julia,keyword-argument,Parameters,Julia,Keyword Argument,在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 也就是说,我必须传递参数,并且必须提供关联

在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
也就是说,我必须传递参数,并且必须提供关联的参数名

我可以在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
而且,即使是斯威夫特也能做到这一点:

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
但我不知道如何在朱莉娅身上做到这一点。似乎关键字参数在被调用时必须采用默认参数。这是正确的,还是有办法模拟上面的Ruby和Python示例?

这样行吗

function f(; x = nothing)
    x + 1
end
实际上,您提供了一个默认的初始值

编辑:将默认值设置为nothing。

可以吗

function f(; x = nothing)
    x + 1
end
实际上,您提供了一个默认的初始值

编辑:将默认值设置为无。

0.7和1.x Julia 0.7是与所有1.0功能兼容的版本,添加了此功能

要指定所需的关键字参数,请在;但不提供默认值:

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及以下版本 这是正确的。 在julia中,不能有必需的关键字参数。 关键字参数是一种特殊类型的可选参数,它是按名称而不是按位置设置的

与此相关:您不能按名称设置非关键字参数——这可以在Python和C中实现

正如@amrods建议的那样,您可以在运行时确保这一点

我会和你一起做的

function f(; x = nothing)
    x===nothing && error("x not set.")
    #...
end
如果调用方在编译类型推断出x的类型,则该检查将被优化

但在运行时之前,它实际上不会被强制执行。 你也可以用@Fengyang

您可以在编译时通过用生成的函数替换函数来强制执行此操作。但这是一个可怕的黑客行为。

Julia 0.7和1.x Julia 0.7是与所有1.0功能兼容的版本,添加了此功能

要指定所需的关键字参数,请在;但不提供默认值:

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及以下版本 这是正确的。 在julia中,不能有必需的关键字参数。 关键字参数是一种特殊类型的可选参数,它是按名称而不是按位置设置的

与此相关:您不能按名称设置非关键字参数——这可以在Python和C中实现

正如@amrods建议的那样,您可以在运行时确保这一点

我会和你一起做的

function f(; x = nothing)
    x===nothing && error("x not set.")
    #...
end
如果调用方在编译类型推断出x的类型,则该检查将被优化

但在运行时之前,它实际上不会被强制执行。 你也可以用@Fengyang


您可以在编译时通过用生成的函数替换函数来强制执行此操作。但这是一个可怕的黑客行为。

它可能与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
但这个错误信息是可怕的。所以我们可以抛出一个更好的错误:

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
正如Oxiabox提到的,错误是在运行时而不是编译时发现的,但Python或Ruby也是如此

如果这太冗长,则很容易生成宏:

macro required(ex)
    esc(Expr(:kw, ex, :(throw(ArgumentError("$($("$ex")) is required"))))
end
那你就可以了

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

这样做的原因是,在没有传递任何参数的情况下,会对默认参数进行求值。通过阻止成功计算默认参数,这需要用户传递一个参数。

这可能与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
但这个错误信息是可怕的。所以我们可以抛出一个更好的错误:

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
正如Oxiabox提到的,错误是在运行时而不是编译时发现的,但Python或Ruby也是如此

如果这太冗长,则很容易生成宏:

macro required(ex)
    esc(Expr(:kw, ex, :(throw(ArgumentError("$($("$ex")) is required"))))
end
那你就可以了

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

这样做的原因是,在没有传递任何参数的情况下,会对默认参数进行求值。通过阻止成功计算默认参数,这要求用户传递一个参数。

可能由于版本漂移,这与1.5.3中的预期效果相同。以Swift为例:


julia> f(;x::Int64) = x + 1

julia> f()
ERROR: UndefKeywordError: keyword argument x not assigned

julia> f(3)
ERROR: MethodError: no method matching f(::Int64)

julia> f(x=3)
4

f3案例中的错误消息可能需要改进。

可能是由于版本漂移,这与1.5.3中的预期一样有效。以Swift为例:


julia> f(;x::Int64) = x + 1

julia> f()
ERROR: UndefKeywordError: keyword argument x not assigned

julia> f(3)
ERROR: MethodError: no method matching f(::Int64)

julia> f(x=3)
4

f3案例中的错误消息可能需要改进。

当然,Python和Ruby都不能保证运行时的正确性,因为它们是动态语言。当然,Python和Ruby都不能保证运行时的正确性,作为动态语言。这是一个非常聪明的方法,可以使用这样一个事实,即如果没有给出默认值,则会计算默认参数的RHS。确实非常聪明。刷新,直到运行时才计算默认值。很早以前,就像许多其他人一样,Python对默认参数的奇怪规则,特别是那些可变参数的规则被烧毁了。可爱的宏顺便说一句。这是一个非常聪明的方法来使用一个事实,即默认参数的RHS是在没有给出默认值的情况下计算的。确实非常聪明。刷新,直到runtim才计算默认值
E很早以前,就像许多其他人一样,Python对默认参数的奇怪规则,特别是那些可变参数的规则被烧毁了。可爱的宏顺便说一句。热爱语言的发展和改进:热爱语言的发展和改进: