下面是一个例子:
def(f::Function) = f
f1 = def() do x
x
end
f2 = def() do x, y
x, y
end
f3 = def() do x, y; z # this syntax is accepted
x, y, z
end
f1(1)
f2(1, 2)
f3(1, 2, z=3) # ERROR: LoadError: function #13 does not accept keyword arguments
下面的例子不是我的实际用例,但它说明了问题。我应该如何处理 do 块中的 kwargs?
据我所知这是不可能的。如果你查看 /src/julia-parser.scm 文件,你会发现 do 块的解析是在
parse-do
here中定义的。您可以看到 do
块被重写为匿名函数,该函数只能接受 doargs
变量中以逗号分隔的位置参数。
在 this 行中,您可以看到
;
显式终止对 do
块的参数的解析。这意味着:
julia> z = "hello"
"hello"
julia> f3 = def() do x, y; println(z) # this syntax is accepted
x, y, z
end
#24 (generic function with 1 method)
julia> f3(100, 1000)
hello
(100, 1000, "hello")
将工作,因为
;
之后的代码被视为do
块体的一部分。
您可以尝试将
(
和 )
放在参数周围,如下所示:
julia> f3 = def() do (x, y; z)
x, y, z
end
ERROR: syntax: invalid assignment location "; z"
julia> f3 = def() do (y; z)
y, z
end
ERROR: syntax: "begin
y
# REPL[52], line 1
z
end" is not a valid function argument name
这将通过解析器,但随后 julia-syntax.scm 将抛出错误。这可能可以改进为:
f3 = def(function(x, y; z)
x, y, z
end)
工作正常(您可以考虑在 https://github.com/JuliaLang/julia/issues 上为此打开一个问题)。
在解决此问题之前,您唯一能做的就是使用我上面给出的匿名函数定义方法(尽管它不是很干净)。
你可以这样做,你只需要在
kwargs
之前传递do
:
julia> f(g, xs; kwargs...) = begin
println(kwargs...)
map(g,xs)
end
f (generic function with 1 method)
julia> f(1:5; thisworks=true) do x x^2 end
:thisworks => true
5-element Array{Int64,1}:
1
4
9
16
25
我想这就是你要找的.. 我使用一个小技巧通过 Julia 的 Do-Block 参数来封装关键字参数。
请参考: 我的 GitHub 答案 我的 GitHub 答案