2015-08-17 63 views
4

我在可變深度的調用堆棧看起來像通過函數名查找調用堆棧中的父環境

TopLevelFunction 
-> <SomeOtherFunction(s), 1 or more> 
    -> AssignmentFunction 

現在,我的目標是在分配創建AssignmentFunction可變的工作,對環境TopLevelFunction。我知道我可以sys.calls提取棧,所以我目前的做法是

# get the call stack and search for TopLevelFunction 
depth <- which(stringr::str_detect(as.character(sys.calls()), "TopLevelFunction")) 
# assign in TopLevelFunction's environment 
assign(varName, varValue, envir = sys.frame(depth)) 

我有更多或更少的罰款,但我不知道,如果這對通話對象轉換爲特徵向量是一個好主意。這種方法容易出錯嗎?更一般地說,如果僅僅知道函數的名字,你將如何搜索一個特定的父環境?

回答

0

我不知道如果我理解正確,你想做的事,但是,woulnd't它的工作使用parent.env(as.environment(-1))

在這個例子似乎工作。

fn1 <- function() { 

    fn1.1 <- function(){ 
     assign("parentvar", "PARENT", 
       envir = parent.env(as.environment(-1))) 

    } 

    fn1.1() 
    print(parentvar) 
} 

fn1() 

也許其他的可能性是使用<<-,我認爲它在全球環境中分配。但也許這不是你想要的。

+0

好主意,但如果我在'AssignmentFunction'和'TopLevelFunction'之間嵌套更多函數,它將無法正常工作。在我的情況,調用堆棧可能,說,3個或5個功能深,所以我不得不提取出完整的堆棧。至於全球分配,它通常是在因爲會影響全局狀態皺起了眉頭,所以我會盡我所能來避免它。 – tonytonov

+0

啊,我明白了,那麼如果你遞歸地獲得父環境,直到到達全球環境之前呢?。,...,這裏的代碼看起來很糟糕,所以我會發布另一個答案... – elikesprogramming

1

這樣

get_toplevel_env <- function(env) { 

    if (identical(parent.env(env), globalenv())) { 
     env 
    } else { 
     get_toplevel_env(parent.env(env)) 
    } 
} 

和你這樣的嵌套函數的任何級別中使用它FN?

get_toplevel_env(as.environment(-1)) 
+0

我感謝你輸入,但是你有什麼理由可以解釋爲什麼你的解決方案比我更喜歡? – tonytonov

+0

好,一方面,在您的解決方案,你硬編碼的頂級函數的名稱。它的工作原理,但它可能不是你的代碼的可維護性好(如果你的頂級FN變化,你必須改變你的代碼)。此外,它不能立即重用/轉移到其他上下文(它只適用於特定的fn)。我建議的函數是通用的,無論函數的名稱如何,它都可以在任何調用堆棧中找到頂級環境。也許你不關心這一點,但對我來說總是重要的是關心我寫的代碼的可維護性和可重用性 – elikesprogramming

+0

公平點,謝謝。雖然我總是可以把函數名變成一個參數(事實上,我已經這樣做了:)) – tonytonov