Der Grund dafür ist, dass Splatted-Keyword-Argumente standardmäßig nicht in einem benannten Tupel gespeichert werden. Wir können sehen, wie sie so gespeichert sind:
julia> g(;kwargs...) = kwargs
g (generic function with 1 method)
julia> g(a=1)
pairs(::NamedTuple) with 1 entry:
:a => 1
julia> g(a=1) |> typeof
Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:a,),Tuple{Int64}}}
Die bespritzten Warwar werden stattdessen als eine Art Iteratorobjekt gespeichert. Wir können diesen kwargs
Iterator jedoch problemlos wie folgt in ein NamedTuple konvertieren : (;kwargs...)
und dann wie erwartet darauf zugreifen, sodass Ihr Beispiel in übersetzt wird
julia> f(args...; kwargs...) = (;kwargs...).x
f (generic function with 1 method)
julia> f(x=1, y=2)
1
Der idiomatischere Weg, dies zu tun, wäre natürlich, stattdessen die Funktion als zu schreiben
julia> f(args...; x, kwargs...) = x
f (generic function with 1 method)
julia> f(x=1, y=2)
1
Dies setzt jedoch voraus, dass Sie den Namen kennen, auf den Sie zugreifen möchten ( x
), wenn Sie die Funktion schreiben.
Eine kurze Randnotiz: Wenn wir zu unserem Beispiel von zurückkehren g(;kwargs...) = kwargs
, können wir nach den Feldnamen des Iteratorobjekts fragen, das wie folgt zurückgegeben wurde:
julia> g(x=1, y=2) |> typeof |> fieldnames
(:data, :itr)
Hm, was ist das für ein data
Feld?
julia> g(x=1, y=2).data
(x = 1, y = 2)
Aha! Damit können wir die kwargs tatsächlich als benanntes Tupel erhalten, dh es f(;kwargs...) = kwargs.data.x
würde funktionieren, aber ich würde diesen Ansatz nicht empfehlen, da er auf undokumentiertem Verhalten zu beruhen scheint, sodass es sich möglicherweise nur um ein Implementierungsdetail handelt, dessen Stabilität nicht garantiert ist über Julia Versionen.