[r] 모든 소스 함수 가져 오기

R에서는 source()일부 함수를로드 하는 데 사용하고 있습니다.

source("functions.R")

이 파일에 정의 된 모든 함수 목록을 얻을 수 있습니까? 함수 이름으로. (어쩌면 source()스스로가 그것을 반환 할 수 있습니까?).

추신 : 마지막 수단은 source()두 번째 로 전화를 local({ source(); })한 다음 ls()내부 및 필터 기능 을 수행하는 것이지만 너무 복잡합니다. 더 쉽고 덜 어설픈 해결책이 있습니까?



답변

가장 좋은 방법은 파일을 임시 환경으로 소싱하는 것입니다. 모든 기능에 대해 해당 환경을 조회 한 후 해당 값을 상위 환경에 복사하십시오.

my_source <- function(..., local=NULL) {
  tmp <- new.env(parent=parent.frame())
  source(..., local = tmp)
  funs <- names(tmp)[unlist(eapply(tmp, is.function))]
  for(x in names(tmp)) {
    assign(x, tmp[[x]], envir = parent.frame())
  }
  list(functions=funs)
}

my_source("script.R")


답변

약간 어색하지만 source호출 전후에 객체의 변경 사항을 볼 수 있습니다.

    # optionally delete all variables
    #rm(list=ls())

    before <- ls()
    cat("f1 <- function(){}\nf2 <- function(){}\n", file = 'define_function.R')
    # defines these
    #f1 <- function() {}
    #f2 <- function() {}
    source('define_function.R')
    after <- ls()

    changed <- setdiff(after, before)
    changed_objects <- mget(changed, inherits = T)
    changed_function <- do.call(rbind, lapply(changed_objects, is.function))
    new_functions <- changed[changed_function]

    new_functions
    # [1] "f1" "f2"


답변

이 정규 표현식은 거의 모든 유효한 유형의 함수 (이진 연산자, 할당 함수)와 함수 이름의 모든 유효한 문자를 포착한다고 생각하지만 가장자리가 빠졌을 수 있습니다.

# lines <- readLines("functions.R")

lines <- c(
  "`%in%` <- function",
  "foo <- function",
  "foo2bar <- function",
  "`%in%`<-function",
  "foo<-function",
  ".foo <-function",
  "foo2bar<-function",
  "`foo2bar<-`<-function",
  "`foo3bar<-`=function",
  "`foo4bar<-` = function",
  "` d d` <- function",
  "lapply(x, function)"
)
grep("^`?%?[.a-zA-Z][._a-zA-Z0-9 ]+%?(<-`)?`?\\s*(<-|=)\\s*function", lines)
#>  [1]  1  2  3  4  5  6  7  8  9 10
funs <- grep("^`?%?[.a-zA-Z][._a-zA-Z0-9 ]+%?(<-`)?`?\\s*(<-|=)\\s*function", lines, value = TRUE)
gsub("^(`?%?[.a-zA-Z][._a-zA-Z0-9 ]+%?(<-`)?`?).*", "\\1", funs)
#>  [1] "`%in%`"      "foo "        "foo2bar "    "`%in%`"      "foo"        
#>  [6] ".foo "       "foo2bar"     "`foo2bar<-`" "`foo3bar<-`" "`foo4bar<-`"


답변

이것이 자신의 스크립트이므로 형식화 방법을 제어 할 수 있으면 간단한 규칙으로 충분합니다. 각 함수 이름이 해당 행의 첫 번째 문자에서 시작하고 해당 행 function에도 단어 가 나타나는지 확인하십시오 . 다른 단어 사용은 function공백이나 탭으로 시작하는 줄에 나타나야합니다. 그런 다음 한 줄 솔루션은 다음과 같습니다.

sub(" .*", "", grep("^\\S.*function", readLines("myscript.R"), value = TRUE))

이 방법의 장점은

  • 매우 간단 합니다. 규칙은 간단하게 설명되어 있으며 함수 이름을 추출하는 데 필요한 간단한 R 코드 행은 하나뿐입니다. 정규 표현식도 간단하고 기존 파일의 경우 확인하기가 매우 쉽습니다. 단어를 grep하고 function표시된 각 항목이 규칙을 따르는 지 확인하십시오.

  • 소스를 실행할 필요가 없습니다. 완전히 정적 입니다.

  • 대부분의 경우 소스 파일 을 전혀 변경할 필요가 없으며 다른 경우에는 최소한의 변경이 있습니다. 이 점을 염두에두고 스크립트를 처음부터 작성하는 경우 훨씬 쉽게 정리할 수 있습니다.

컨벤션 아이디어에는 다른 많은 대안이 있습니다. # FUNCTION스크립트를 처음부터 새로 작성하고 해당 문구를 grep하고 줄에서 첫 번째 단어를 추출하는 경우 더 정교한 정규 표현식을 사용하거나 함수 정의의 첫 번째 줄 끝에 추가 할 수 있지만 주요 제안은 다음과 같습니다. 단순성과 나열된 다른 장점으로 인해 특히 매력적입니다.

테스트

# generate test file
cat("f <- function(x) x\nf(23)\n", file = "myscript.R")

sub(" .*", "", grep("^\\S.*function", readLines("myscript.R"), value = TRUE))
## [1] "f"


답변

이것은 내 의견의 게시물에 사용 된 코드를 일련의 토큰 (기호, 할당 연산자, 함수)을 검색하도록 조정하며 정의 된 함수를 가져 와야합니다. MrFlick의 답변으로 강력한 지 확실하지 않지만 다른 옵션입니다.

source2 <- function(file, ...) {
  source(file, ...)
  t_t <- subset(getParseData(parse(file)), terminal == TRUE)
  subset(t_t, token == "SYMBOL" &
           grepl("ASSIGN", c(tail(token, -1), NA), fixed = TRUE) &
           c(tail(token, -2), NA, NA) == "FUNCTION")[["text"]]
}


답변