我不認爲喬希的回答是正確的。
那麼,它將是正確的,如果<-
是在你的例子中的調用堆棧。 但它不是。
小回顧:正常的R功能評估將參數作爲承諾,在訪問時會延遲評估。這意味着,在下面的調用:
foo(bar(baz))
bar(baz)
評估內foo
(如果有的話)。因此,如果我們檢查裏面bar
調用堆棧,就像這樣:
bar = function (x) {
sys.calls()
}
...那麼,它看起來如下:
[[1]]
foo(bar(baz))
[[2]]
bar(baz)
可惜的是,正如你指出,<-
(和=
)不是正常功能,這是一個原始(BUILTINSXP
)。事實上,它是defined in the R source如下:
{"<-", do_set, 1, 100, -1, {PP_ASSIGN, PREC_LEFT, 1}},
看看第四個參數:100
。此代碼之前的註釋解釋了數字的含義。下面是相關的部分,解釋了最左邊的數字:
Z = 1表示調用(BUILTINSXP
)
這意味着下面的代碼調用bar(baz)
是轉讓前評估之前評估參數:
`<-`(x, bar(baz))
這就是爲什麼<-
不會在sys.calls()
列表中出現:它不是當前呼叫。它在bar
完成評估後被調用。
有解決此限制的方法:你可以在R代碼裏面重新定義<-
/=
。如果你這樣做,它的行爲像一個正常的一個R函數:
`<-` = function (lhs, rhs) {
name = as.name(deparse(substitute(lhs), backtick = true))
rhs # evaluate expression before passing it to `bquote`, for a cleaner call stack
eval.parent(bquote(base::`<-`(.(name), .(rhs))))
}
但是,要小心,這將在那裏<-
被重新定義範圍內承擔不可忽略的性能損失爲每隨後指派:事實上,它使得分配大致成爲因子1000(!!!)較慢。這通常不被接受。
+1表示一個非常有趣和明確的問題。 R Internals指南中的鏈接部分也很有趣:我以前沒有考慮過使用Primitive函數的各種動機。 '<-','log'和'UseMethod'都是原語,但原因很不一樣。 –
@ JoshO'Brien我不認爲這些動機必然是正確的 - 他們都可以用'完成。內部函數 – hadley