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"]]
}