2017-01-10 1 views
0

내 글로벌 환경 변수가 myList입니다. myList을 수정하고이를 myFunction이라는 글로벌 환경에 다시 할당하는 기능이 있습니다. myListmyFunction으로 수정하면됩니다. 다른 기능이 수정되지 않도록 할 방법이 있습니까 myList?개체를 수정할 수있는 기능 제한

배경으로 R 사용자를위한 일반적인 도구를 작성합니다. 나는 도구의 사용자가 myList을 수정할 자신의 기능을 정의 할 수 없도록하고 싶다. 나는 또한 앞으로 쓸 수있는 기능으로 myList을 수정할 수 있기를 바라지 않습니다.

나는 잠재적 인 해결책이 있지만 나는 그것을 좋아하지 않는다. 도구가 실행되면 사용자가 정의한 모든 함수의 텍스트를 검토하고 myList을 글로벌 환경에 할당 할 텍스트를 검색 할 수 있습니다. 나는 모든 기능을 검색해야한다는 사실을 싫어한다.

내가 찾고있는 것이 R에서 구현 가능한지 아는 사람이 있습니까? 제공 할 수있는 모든 도움에 감사드립니다.

재현 가능한 예입니다.

assign('myList', list(), envir = globalenv()) 
myFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 
userFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 
myFunction() # I need some code that will allow this function to run successfully 
userFunction() # and cause an error when this function runs 
+0

나는 그렇게 제한적이어서는 안된다고 생각합니다. S3 클래스를 살펴 봐야하며 아마도 가장 좋은 솔루션은 그 클래스에 고유 한 데이터 구조와 메소드를 거의 가지고있을 것입니다. 데이터가 함수에 의해 생성되지는 않고 수정 되었기 때문에 초기 입력은 항상 자유롭게 수행됩니다. – zacdav

답변

1

당신이 modules 패키지가 필요 같은 소리 : 나는 가능한 다음 예제를 만들 것입니다 코드가 필요합니다.

기본적으로 각 코드 단위에는 자체 범위가 있습니다.

# install.packages("modules") 
# Load library 
library("modules") 

# Create a basic module 
m <- module({ 
    .myList <- list() 
    myFunction <- function() { 
     .myList <<- c(.myList, 'test') 
    } 

    get <- function() .myList 
}) 
# Accessor 
m$get() 
# list() 

# Your function 
m$myFunction() 

# Modification 
m$get() 
# [[1]] 
# [1] "test" 

주, 우리는 myList에서 .myList에 변수 이름을 변경하여 약간의 예를 쥐게. 그래서, 우리는이 프로그램 실행 userfunction()

userFunction <- function() { 
    .myList <- c(.myList, 'test') 
} 

에 그를 업데이트해야합니다, 우리는 지금 얻을 : 원하는대로

userFunction() 
# Error in userFunction() : object '.myList' not found 

합니다.

더 자세한 예는 modules vignette을 참조하십시오.

다른 방법으로 환경 (new.env())을 정의한 다음 myList을로드 한 후에 잠글 수 있습니다.

1

이것은 모두 나쁜 생각입니다. 지구 환경에 대한 할당부터 (나는 이것을하는 패키지를 결코 사용하지 않는다) 놀랄만한 사용자에게. 당신은 아마 그냥 S4 또는 참조 클래스를 사용해야합니다.

어쨌든 바인딩 (또는 더 나은 방법을 따랐다면 환경)을 잠글 수 있습니다. 당신은 고급 사용자를 그만 두지는 않겠지 만, 적어도 그들이 당신이 객체를 변경하기를 원하지 않는다는 것을 알 것입니다.

createLocked <- function(x, name, env) { 
    assign(name, x, envir = env) 
    lockBinding(name, env) 
    invisible(NULL) 
} 

createLocked(list(), "myList", globalenv()) 


myFunction <- function() { 
    unlockBinding("myList", globalenv()) 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
    lockBinding("myList", globalenv()) 
    invisible(NULL) 
} 

userFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 

myFunction() # runs successfully 
userFunction() 
#Error in assign("myList", myList, envir = globalenv()) : 
# cannot change value of locked binding for 'myList'