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()
函数都应被视为不可更改。我不想包装任何一个与不同接口。相反,我在这里寻找一种编写拟议的params()
函数的通用方法,在运行时重写参数列表,以便可以使用parent()
和child()
直接使用安全但非冗长的语法。
赏金后澄清: 尽管反转父子关系并使用do.call()是一种有用的技术,但这不是我在这里寻找的技术。相反,我正在寻找一种方式来接受“...”参数,将其修改为带有命名参数,然后以封闭函数可以接受的形式返回它。可能正如其他人所建议的那样,这是真正不可能的。就个人而言,我目前认为这需要一个C级扩展,而且我希望这个扩展已经存在。也许程序包做我想要的事情? https://github.com/crowding/vadr#dot-dot-dot-lists-and-missing-values
部分信用: 我觉得只是让赏金过期很傻。如果没有完整的解决方案,我将授予任何提供至少一项必要步骤概念验证的人。例如,在函数内修改'...'参数,然后在不使用do.call()的情况下将其传递给另一个函数。或以父母可以使用的方式返回未修改的'...'参数。或者任何最好指向直接解决方案的方法,甚至是一些有用的链接:http://r.789695.n4.nabble.com/internal-manipulation-of-td4682090.html 但我不愿把它授予以“你不想这样做”或“那是不可能的,所以这里是替代方案”的前提开始的答案。
奖励赏金: 有几个非常有用和实用的答案,但我选择将赏金颁发给@crowding。他(可能是正确的)断言我想要的是不可能的,但我认为他的答案最接近我所追求的“理想”方法。我还认为他的vadr软件包可能是一个很好的起点,无论它是否符合我的(潜在的不切实际的)设计目标。如果有人发现了实现不可能的方法,“接受的答案”仍然可获得。感谢其他回答和建议,希望它们能帮助某人组合更强大的R语法。
do.call
和match.call
不能满足你的所有需求,但我认为仔细研究这些函数可能会对你有所帮助。顺便说一下,你的问题让我想起了我之前问过的一个问题(https://dev59.com/5l0b5IYBdhLWcg3wUP0X),不幸的是没有得到答复。 - CL.parent
和child
不可更改”,但是在您自己的示例中,通过使用child(params(...))
您已经更改了parent
。我认为这与例如params(child)
相同程度的更改,这基本上就是Mnel /我的答案的内容。 - BrodieG