I am trying to change all NA
passed to the function to NULL
. What I want is not to treat each arg separatedly, by name, but to capture all of them, filter those which are NA
and change them to NULL.
foo <- function(a, b = NA, c = NA) {
print(a)
print(b)
print(c)
# do something to capture all args and change NAs to NULL
print(a)
print(b)
print(c)
}
# expected output
> foo(a = 1)
[1] 1
[1] NA
[1] NA
[1] 1
[1] NULL
[1] NULL
edit: included an argument without a default value
CodePudding user response:
To access a function's arguments, use formals
.
foo <- function(a = 1, b = NA, c = NA) {
print(a)
print(b)
print(c)
# do something to capture all args and change NAs to NULL
frm <- formals()
cat("-----------\n")
print(frm)
frm <- lapply(frm, \(x) {
if(is.na(x)) NULL else x
})
cat("-----------\n")
with(frm, {
print(a)
print(b)
print(c)
})
}
foo()
#> [1] 1
#> [1] NA
#> [1] NA
#> -----------
#> $a
#> [1] 1
#>
#> $b
#> [1] NA
#>
#> $c
#> [1] NA
#>
#> -----------
#> [1] 1
#> NULL
#> NULL
Created on 2022-03-28 by the reprex package (v2.0.1)
Edit
The comments suggest that the question is also asking for match.call
. But its return values must be coerced to list.
check_arrays <- function(a, b, c, d) {
print(as.list(match.call()))
}
check_arrays(a = 'teststring', b = 1, c = NA, d = NA)
#> [[1]]
#> check_arrays
#>
#> $a
#> [1] "teststring"
#>
#> $b
#> [1] 1
#>
#> $c
#> [1] NA
#>
#> $d
#> [1] NA
Created on 2022-03-28 by the reprex package (v2.0.1)
And an example changing all NA
arguments to NULL
, just like the first function above is the following.
check_arrays <- function(a, b, c, d) {
print(a)
print(b)
print(c)
print(d)
# do something to capture all args and change NAs to NULL
# note that the first element of the list is the function
# name, remove it
args_list <- as.list(match.call())[-1]
cat("-----------\n")
print(args_list)
args_list <- lapply(args_list, \(x) {
if(is.na(x)) NULL else x
})
cat("-----------\n")
with(args_list, {
print(a)
print(b)
print(c)
print(d)
})
}
check_arrays(a = 'teststring', b = 1, c = NA, d = NA)
#> [1] "teststring"
#> [1] 1
#> [1] NA
#> [1] NA
#> -----------
#> $a
#> [1] "teststring"
#>
#> $b
#> [1] 1
#>
#> $c
#> [1] NA
#>
#> $d
#> [1] NA
#>
#> -----------
#> [1] "teststring"
#> [1] 1
#> NULL
#> NULL
Created on 2022-03-28 by the reprex package (v2.0.1)
CodePudding user response:
Quick disclaimer: the solutions offered here will work if your arguments are scalars. If they are vectors or other objects, the outcome may be quite a bit different.
You can use a ls
and assign
within a loop and avoid having to refer to the arguments from a list after the conversion.
foo <- function(a = 1, b = NA, c = NA) {
print(a)
print(b)
print(c)
arg_names <- ls()
for (arg in arg_names){
tmp <- if (is.na(get(arg))) NULL else get(arg)
assign(arg, tmp)
}
print(a)
print(b)
print(c)
}
foo()
Alternatively, if you'd rather work with lists, you can use mget
and list2env
foo <- function(a = 1, b = NA, c = NA) {
print(a)
print(b)
print(c)
arg_names <- ls()
arg <- mget(arg_names)
arg <- lapply(arg,
function(a) if (is.na(a)) NULL else a)
list2env(arg, envir = environment())
print(a)
print(b)
print(c)
}
foo()