簡體   English   中英

當原始調用包含在 function 中時,為什么 match.call 不起作用?

[英]Why does match.call not work when the original call is wrapped in a function?

我想通過 function arguments 在其內部遞歸調用 function (當然,通常具有中斷條件)。

我了解到match.call應該可以捕獲所有 arguments,並且它可以工作 - 直到我將原始調用包裝在另一個 function 中。

inner <- function(my_arg) {
    message(my_arg)
    do.call("inner", as.list(match.call()[-1]))
}

# this yields an error ... (unexpected)
outer <- function() {
    mydata <- data.frame(1)
    inner(mydata)
}
outer()

# ... while this yields an infinite loop (expected)
mydata <- data.frame(1)
inner(mydata)

這輸出:

1
Error in is.data.frame(my_arg) : object 'mydata' not found

這是為什么? 這是故意的嗎? 我怎樣才能解決這個問題?

這個錯誤真的很難解釋,因為它是do.callmatch.call和遞歸相互作用的結果。 當嵌套調用inner(my_arg = mydata)的承諾被強制執行時,就會出現問題。 message被調用時,R 搜索 function scope,如果 ZA8CFDE6331BD49EB2AC96F8 未找到封閉環境。 當嵌套調用中的 promise 未被強制(由於您的do.call("inner", as.list(match.call()[-1]))構造)時,這似乎失敗了。

> traceback()
5: message(my_arg) at #2
4: inner(my_arg = mydata)
3: do.call("inner", as.list(match.call()[-1])) at #4
2: inner(mydata) at #4
1: outer()

我建議你研究一下語言定義,例如 Section 4.3.3

另外,為什么你需要match.call這里? 只需使用inner(my_arg)而不是do.callmatch.call構造。 這立即迫使 promise 一切正常。

這是因為范圍界定而發生的。 希望對您的兩個函數的這種修改能夠清楚地了解正在發生的事情(沒有無限循環)。 以及如何解決它。

inner <- function(my_arg)
{
  mc <- match.call()
  cat("Call to inner:\n")
  print(mc)
  cat("\nSymbol to be evaluated within \"inner\":\n")
  print(as.list(mc)$my_arg)
  cat("\nSymbol evaluated in scope of \"inner\":\n")
  tryCatch(print(eval(as.list(mc)$my_arg)),
           error = function(e) cat("**Error** - symbol not found\n"))
  cat("\nSymbol evaluated in parent frame of \"inner\":\n")
  tryCatch(print(eval(as.list(mc)$my_arg, envir = parent.frame())),
           error = function(e) cat("**Error** - symbol not found\n"))
}

outer <- function()
{
  my_data <- "outer test string"
  inner(my_data)
}

我們可以測試如下:

inner("inner test string")
#> Call to inner:
#> inner(my_arg = "inner test string")
#> 
#> Symbol to be evaluated within "inner":
#> [1] "inner test string"
#> 
#> Symbol evaluated in scope of "inner":
#> [1] "inner test string"
#> 
#> Symbol evaluated in parent frame of "inner":
#> [1] "inner test string"

outer()
#> Call to inner:
#> inner(my_arg = my_data)
#> 
#> Symbol to be evaluated within "inner":
#> my_data
#> 
#> Symbol evaluated in scope of "inner":
#> **Error** - symbol not found
#> 
#> Symbol evaluated in parent frame of "inner":
#> [1] "outer test string"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM