基于命名参数的 Julia 多重分派?

Ale*_*hin 4 julia

我正在尝试创建允许多种用途的灵活功能:

save(image_url = "http://...")
save(image_url = "http://...", title = "Cats", id = "cats")
save(text = "Some text", comments = "Some comments")
save(text = "Another text", title = "News", compression = true)
Run Code Online (Sandbox Code Playgroud)

基本上它是 3 个(或更多)函数 ( save_image_url, save_image_path, save_text) 组合。

它们都有 3 个相同的可选参数title, descriptions, compression。每个都可以有任意数量的特定参数。

我不想使用位置参数,因为很难记住参数的顺序。此外,第一个参数与and 的String类型相同。image_urlimage_pathtext

不幸的是,multiple dispatch似乎不适用于命名参数。那么处理这种情况的模式是什么?

不工作的实施

function save(;
  image_url::   String,

  title::       Union{String, Nothing} = nothing,
  description:: Union{String, Nothing} = nothing,
  compression:: Union{Bool, Nothing}   = nothing
)::Nothing
  nothing
end


function save(;
  image_path::  String,

  title::       Union{String, Nothing} = nothing,
  description:: Union{String, Nothing} = nothing,
  compression:: Union{Bool, Nothing}   = nothing
)::Nothing
  nothing
end

function save(;
  text::        String,
  comments::    Union{String, Nothing} = nothing,

  title::       Union{String, Nothing} = nothing,
  description:: Union{String, Nothing} = nothing,
  compression:: Union{Bool, Nothing}   = nothing
)::Nothing
  nothing
end
Run Code Online (Sandbox Code Playgroud)

Dav*_*ela 7

多次分派很棒,但有时它是工作的错误工具。在这种情况下,对函数名称的基本调度既简单又足够。如果可能的话,我更喜欢这个选项。但是,如果需要一致的函数名称,那么您始终可以对自定义类型进行调度。

不同的函数名称

function save_image_url(url::String; kwargs...)
    handle_general_options(; kwargs...)
    # url specific code
end

function save_image_path(path::String; kwargs...)
    handle_general_options(; kwargs...)
    # path specific code
end

function handle_general_options(; title=nothing, description=nothing)
    # shared code
end
Run Code Online (Sandbox Code Playgroud)

自定义类型

struct ImageURL
   val::String
end

function save(url::ImageURL; kwargs...)
    handle_metadata(; kwargs...)
    # url specific code
end

function handle_general_options(; title=nothing, description=nothing)
    # shared code
end
Run Code Online (Sandbox Code Playgroud)

您可以通过立即创建要分派的对象来在调用站点明确分派:

save(ImageURL("https://..."); title="SomeTitle")
Run Code Online (Sandbox Code Playgroud)


Jun*_*ian 6

我建议像这样拆分用户界面和实现细节:

function save(;
    image_url=nothing,
    image_path=nothing,
    text=nothing,

    title=nothing,
    description=nothing,
    compression=nothing
)
    save(image_url, image_path, text, title, description, compression)
end

function save(image_url::String, ::Nothing, ::Nothing, title, description, compression)
    # do something
end

function save(::Nothing, image_path::String, ::Nothing, title, description, compression)
    # do something
end

function save(::Nothing, ::Nothing, text::String, title, description, compression)
    # do something
end

function save(image_url, image_path, text, title, description, compression)
    @error "only one of image_url, image_path, text are acceptable"
end
Run Code Online (Sandbox Code Playgroud)

当事情变得太复杂时,你总是可以从关键字参数创建一个新的结构体,并使用特征来调度它。