trace函數: 修改既有的R function內容

今天為了追一個安裝套件的bug,我需要追蹤tools:::.install_packages這個程式碼在if (test_load) {以後的行為。

在追蹤R語言函數的行為時,我常用的是在原始碼中插入browser()debug(tools:::.install_packages)兩種方法。trace函式我一直不太懂。有興趣的讀者可以在查閱我過去寫的:R的除錯功能

在追tools:::.install_packages這個函數時,一來我懶的去研究如何修改tools這個內建套件的函數原始碼,二來這個函數很複雜,如果用debug需要瘋狂的next step...

trace這個函數,是用來編輯已經存在的R函數。第一種用法是直接在指定的行數插入給定的expression。這裡的行數,是以list(body(tools:::.install_packages))的輸出為準。有興趣的讀者直接查閱examples(trace)就可以看到範例了。

另外一種作法,是直接設定edit = TRUE,R就會打開預設的編輯器(效果應該等同於file.edit)後,讓我們直接編輯原始碼,儲存退出後生效。以我手上的例子,我需要輸入:trace(".install_packages, where = loadNamespace("tools"), edit = TRUE)

以下的附加說明是寫給沒這麼熟R套件系統的讀者。tools:::.install_packages是tools套件的內部函數(有三個:),所以即使我library(tools)之後,直接在console輸入.install_packages,R仍然會回報錯誤:找不到.install_packages物件。因此我需要指定where參數,告訴R.install_packages在哪裡。tools套件的內部函數,在R中是放在<environment: namespace:tools>這個環境中,我們可以使用loadNamespace("tools")的輸出來取得這個環境。

輸入以後,我就可以手動編輯原始碼,直接找到test_load這段程式之後,在下一行插入browser(),就可以在執行tools:::.install_packages時直接中斷在我要的地方。