I have run into a strange behavior if a function has an argument and the ellipse and the two start with the same letter. A toy example is this
> testfun=function(aa=0, ...) {print(aa); list(...)}
> testfun(b=1)
[1] 0
$b
[1] 1
> testfun(a=1)
[1] 1
list()
So when I call testfun(b=1)
everything works fine, aa
is printed as 0 and a list with element b=1 is returned. However, if I call testfun(a=1)
, aa is now 1 and an empty list is returned. Apparently if there is an argument that starts with the same letter as the one passed to ..., this argument gets changed and the ...
is lost.
Any idea why this is? Any way to avoid this? In my real problem the ... is supplied by users, who might use any name for the argument (except the ones that are already arguments for the function like aa here)
CodePudding user response:
As others have mentioned, R uses partial argument matching, so if the user enters a
, it will match formal argument aa
in your function. But I don't think anyone has mentioned that R uses exact matching for formal arguments that follow the ellipsis. For example,
testfun <- function(..., aa = 0) {
print(aa)
list(...)
}
testfun(a = 1)
#> [1] 0
#> $a
#> [1] 1
Created on 2022-10-19 with reprex v2.0.2
CodePudding user response:
Try make the aa
variable assigned in the function :
testfun=function(...){
if(any("aa" == names(list(...)))) {
stop("Invalid argument")
}
aa = 0
print(aa)
print(names(list(...)))
print(list(...))
}
> testfun(aa = , b=1)
[1] 0
[1] "b"
$b
[1] 1
> testfun(aa = , a = 1)
[1] 0
[1] "a"
$a
[1] 1
> testfun(aa = 1)
Error in testfun(aa = 1) : Invalid argument
The post mentioned that the users will entere only the ... part. Since the aa
argument is a fixed one, just take it out of the function's arguments. To avoid from entering a preassigned argument, you can raise an error if found an invalid argument name.