gpt4 book ai didi

julia - 如何编写一个将任意数量的参数传递给另一个函数的 Julia 函数?

转载 作者:行者123 更新时间:2023-12-04 16:24:44 26 4
gpt4 key购买 nike

我是 Julia 新手,并且在 R 方面经验丰富,因此对于熟悉这两者的人来说,这里是我尝试在 Julia 中复制的 R 代码片段。

f = function(a, b = 1, c = 2) a + 2*b = 3*c
g = function(d, ...) 5 + f(d, ...)

这样调用 g(1) 是有效的,它将使用 f 的默认值进行计算,或者您可以指定 g(1, b = 3)g(1, c = 4, b = 2) 或其他。重点当然是,只要指定了名称,您就可以将可选参数的任何排列传递给 f,而不用考虑顺序。

在 Julia 中,我在执行此操作时遇到了一些麻烦,因为可变参数的工作方式有所不同。我知道您可以将无限的参数列表以元组的形式传递给函数(例如,function g(d::Number, f_args::NamedTuple),但看起来像它不适用于可选的关键字参数。几乎就好像 f_args 元组在某处丢失了它的名称,并且 f 感到困惑,因为它看到了 3 个没有名称的参数不知道选择哪种方法?

如果确实有可能,如果有人能告诉我如何在 Julia 中执行此操作,我将不胜感激。我想保留这些参数的可选性以及它们的名称。我还希望能够保留它们的类型(即,我希望 f 的每个参数只有在它们适合正确的类型时才可以接受,这当然通常在 Julia 中完成在标题中使用 :: 运算符)。

PS - 就我的问题而言,重写 g 使其具有 cb 作为可选参数对我来说是不够的。为了简单起见,我展示了 fg 的示例,但实际上我希望将这些原则应用于具有许多参数的更复杂的函数。

最佳答案

在 julia 中,可选的位置参数和关键字参数的处理方式不同。

如果我们想在函数中允许任意参数顺序,我们必须指定 keyword arguments .与 R 不同,julia 坚持我们在参数列表中使用分号来区分位置参数和关键字参数。我们可以在 julia 中编写您的函数 fg 以通过简单地添加适当的分号来实现这一点:

f(a; b=1, c=2) = a + 2*b + 3*c
g(d; kwargs...) = 5 + f(d; kwargs...)

这定义了一个方法 f 带有一个必需的位置参数和两个可选的关键字参数,另一个方法 g 带有一个必需的位置参数和 any number of keyword arguments这将被传递给 f。这意味着我们可以这样做:

g(1)             # 14
g(1) == 5 + f(1) # true
g(1, b=3) # 18
g(1, c=4, b=2) # 22

同样,与 R 不同,关键字参数与位置参数不同,所以我们不能这样做:

f(1, 2, 4)
# ERROR: MethodError: no method matching f(::Int64, ::Int64, ::Int64)
# Closest candidates are:
# f(::Any; b, c) at REPL[1]:1

这是因为我们定义的方法签名只接受一个位置参数。如果你想要一个可以接受位置参数或关键字参数的函数,我们必须定义一个新的函数签名,如下所示:

f(a, x=1, y=2) = f(a; b=x, c=y)

在这里,我们正在创建一些与原始方法具有相同名称 f 的新方法,它们所做的只是将它们的位置参数作为关键字参数传递。现在我们可以这样做了:

f(1, 2, 4) == 17  # true

如果我们希望 g 以类似的方式运行,记住 julia 区分位置参数和关键字参数,我们需要指定 两个 可变参数:一个用于位置参数和关键字参数:

g(d, args...; kwargs...) = 5 + f(d, args...; kwargs...)

现在我们可以这样做了:

g(1, 2) == g(1, b=2)         # true
g(1, 2, 4) == g(1, c=4, b=2) # true

但是当我们尝试组合这些类型的签名时,事情会变得一团糟:

g(1, 2, c=4)
# ERROR: MethodError: no method matching f(::Int64, ::Int64; c=4)
# Closest candidates are:
# f(::Any, ::Any) at REPL[18]:1 got unsupported keyword argument "c"
# f(::Any, ::Any, ::Any) at REPL[18]:1 got unsupported keyword argument "c"
# f(::Any; b, c) at REPL[18]:1

为什么不允许这样做?错误消息提示我们定义 optional positional arguments 的内容。在引擎盖下做。当我们定义一个带有 n 个可选位置参数的方法时,julia 只会创建 n+1 个方法,每个方法都有 0 到 n 个参数标记到签名的结尾。像这样:

h(a, b=1, c=2, d=3) = nothing
# h (generic function with 4 methods)

methods(h)
# 4 methods for generic function "h":
#[1] h(a) in Main at REPL[32]:1
#[2] h(a, b) in Main at REPL[32]:1
#[3] h(a, b, c) in Main at REPL[32]:1
#[4] h(a, b, c, d) in Main at REPL[32]:1

这意味着当我们定义 f 的可选位置参数版本时,julia 制作了签名 f(a, b)f(a, b, c) 对我们来说,但它确实没有创建一个带有签名 f(a, b; c) 的方法。

关于julia - 如何编写一个将任意数量的参数传递给另一个函数的 Julia 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67132592/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com