do.call に渡すリストの名前が引数名と一致しないと unused argument になる
do.call(f, args)は、argsという名前付きリストの各要素名をfの引数名として渡します。リストの要素名が関数の引数名と1文字でも違うと、その引数は認識されず「使われない引数」としてエラーになります。
このエラーが出る典型パターン
パターン1
1 connect <- function(host, port) { 2 paste(host, port) 3 } 4 result <- do.call(connect, list(hostname = "local", port = 80)) ^ 5 cat(result, "\n")
do.callはリストの名前を頼りに引数を対応づけるため、hostnameという名前はconnectのどの引数とも一致せずunused argumentになります。
直し方: hostname を host にします。
パターン2
1 greet <- function(name, times) { 2 paste(rep(name, times), collapse = " ") 3 } 4 result <- do.call(greet, list(username = "Ken", times = 2)) ^ 5 cat(result, "\n")
リストの要素名usernameはgreetの引数名nameと一致しないため、do.callはこの引数を渡す先が分からずエラーになります。
直し方: username を name にします。
パターン3
1 build_url <- function(scheme, path) { 2 paste0(scheme, "://", path) 3 } 4 result <- do.call(build_url, list(scheme = "https", url_path = "example.com")) ^ 5 cat(result, "\n")
build_urlはpathという名前の引数しか受け取れず、url_pathという名前では対応する引数が見つからずエラーになります。
直し方: url_path を path にします。
パターン4
1 register <- function(name, plan) { 2 paste(name, plan) 3 } 4 result <- do.call(register, list(name = "taro", tier = "pro")) ^ 5 cat(result, "\n")
リストの要素名tierは関数の引数名planと1文字も一致していないため、do.callはこの値をどの引数にも渡せません。
直し方: tier を plan にします。
パターン5
1 configure <- function(mode, level) { 2 paste(mode, level) 3 } 4 result <- do.call(configure, list(setting = "auto", level = 3)) ^ 5 cat(result, "\n")
do.callに渡すリストの名前は関数の引数名と完全に一致していなければならず、settingという名前はconfigureのどの引数とも合致しません。
直し方: setting を mode にします。
よくある誤解
「do.callはリストの中身を順番通りに引数へ渡してくれるはず」という思い込みは誤りです。argsに名前が付いている場合、do.callは名前を頼りに引数を対応づけるため、名前が一致していなければ正しい引数には渡らずエラーになります。
実務での勘所
do.callが必要になるのは、呼び出す引数の中身が実行時にならないと決まらない場面です。設定ファイルやユーザーの入力に応じて渡すべき引数の組み合わせが毎回変わるような状況では、f(a=1, b=2)のように直接書くことができません。引数をリストとして組み立てておき、do.call(f, args)のようにまとめて渡すことで、プログラム的に呼び出し内容を組み立てられます。この柔軟性と引き換えに、リストの名前と関数の引数名を人間が手作業で一致させる必要があります。