gpt4 book ai didi

r - 在R函数中基于变量名称将位置参数转换为命名参数

转载 作者:行者123 更新时间:2023-12-03 19:45:10 27 4
gpt4 key购买 nike

在R中,常见的函数调用模式如下所示:

child = function(a, b, c) {
a * b - c
}

parent = function(a, b, c) {
result = child(a=a, b=b, c=c)
}

名称的这种重复是有帮助的,因为如果子参数的顺序要更改,或者如果要向列表中添加其他变量,则可以避免潜在的隐患:
childReordered = function(c, b, a) {  # same args in different order
a * b - c
}

parent = function(a, b, c) {
result = childReordered(a, b, c) # probably an error
}

但是,当参数名称变长时,这变得很麻烦:
child = function(longVariableNameA, longVariableNameB, longVariableNameC) {
longVariableNameA * longVariableNameB - longVariableNameC
}

parent = function(longVariableNameA, longVariableNameB, longVariableNameC) {
child(longVariableNameA=longVariableNameA, longVariableNameB=longVariableNameB, longVariableNameC=longVariableNameB)
}

我想有一种方法来获得命名参数的安全性,而无需再次实际键入名称。当我只能修改父级而不修改子级时,我希望能够执行此操作。我设想这样的事情:
parent = function(a, b, c) {
result = child(params(a, b, c))
}

其中 params()是一个新函数,它将基于变量的名称将未命名的参数转换为命名的参数。例如:
child(params(c,b,a)) == child(a=a, b=b, c=c)

“pryr”中有几个函数与此相似,但是我还没有弄清楚如何将它们组合起来以完全实现我想要的功能。 named_dots(c,b,a)返回 list(c=c, b=b, a=a),而 standardise_call()具有类似的操作,但是我还没有弄清楚如何将结果转换为可以传递给未修改的 child()的内容。

我希望能够混合使用隐式和显式命名的参数:
child(params(b=3, c=a, a)) == child(b=3, c=a, a=a)

能够混入一些未命名的常量(而不是变量),并在将其传递给子对象时将它们视为命名参数,也将是一件很好的事情。
child(params(7, c, b=x)) == child(a=7, c=c, b=x)  # desired
named_dots(7, c, b=x) == list("7"=7, c=c, b=x) # undesired

但是以非R的方式,我更愿意引发错误,而不是试图弄清楚程序员可能犯的错误:
child(params(c, 7, b=x)) # ERROR: unnamed parameters must be first

是否已经存在执行此操作的工具?将现有功能组合在一起做我想要的简单方法?在改变参数列表的情况下,又能实现相同目标的安全性的更好方法,而又不会繁琐地重复?改进了我建议的语法,使其更安全?

赏金前澄清: parent()child()函数均应视为不可更改。我对使用其他接口(interface)包装都不感兴趣。而是,我在这里寻找一种以通用方式编写建议的 params()函数的方法,该函数可以即时重写参数列表,以便 parent()child()都可以直接使用安全但不冗长的语法使用。

赏金后澄清:反转父子关系并使用do.call()是一种有用的技术,但这不是我在这里寻找的技术。相反,我正在寻找一种接受“...”参数的方法,将其修改为具有命名参数,然后以封装函数将接受的形式返回它。正如其他人所暗示的那样,这确实是不可能的。就我个人而言,我目前认为可以使用C级扩展,并且我希望该扩展已经存在。也许 vadr包符合我的要求? https://github.com/crowding/vadr#dot-dot-dot-lists-and-missing-values

部分信贷:我只是让赏金过期而感到愚蠢。如果没有完整的解决方案,我将把它颁发给任何提供有关至少一个必要步骤的概念证明的人。例如,修改一个函数中的“...”参数,然后将其传递给另一个函数,而无需使用do.call()。或以 parent 可以使用的方式返回未修改的“...”参数。或最能指出直接解决方案的方法,甚至是一些有用的链接: http://r.789695.n4.nabble.com/internal-manipulation-of-td4682090.html但我不愿意将其授予以(否则完全合理)前提为前提的答案,即“您不想这样做” ”或“那是不可能的,所以这是一个替代方案”。

赏金授予:有几个非常有用和实用的答案,但是我选择将赏金授予 @crowding。尽管他(可能是正确的)断言我想要的是不可能的,但我认为他的答案与我所追求的“理想”方法最接近。我还认为,无论它是否符合我的(可能不现实的)设计目标,他的 vadr软件包都可能是解决方案的一个很好的起点。如果有人想出办法解决不可能的事情,那么“可接受的答案”仍然值得商grab。感谢您提供其他答案和建议,希望它们能帮助某人拼凑出更强大的R语法。

最佳答案

我认为尝试覆盖R的内置参数匹配功能有些危险,因此这是一种使用do.call的解决方案。

目前尚不清楚parent有多少可更改

# This ensures that only named arguments to formals get passed through
parent = function(a, b, c) {
do.call("child", mget(names(formals(child))))
}

第二种选择,基于 write.csv的“魔力”
# this second option replaces the call to parent with child and passes the 
# named arguments that have been matched within the call to parent
#

parent2 <- function(a,b,c){
Call <- match.call()
Call[[1]] <- quote(child)
eval(Call)
}

关于r - 在R函数中基于变量名称将位置参数转换为命名参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32160753/

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