해당 함수 내에서 함수 이름 결정


15

익명이 아닌 함수 내에서 함수 이름을 얻으려면 어떻게해야합니까? 아래에서는이 작업을 수행하는 함수 또는 프로세스 magical_r_function()가 있고 예상 출력이 무엇인지 가정 합니다.

my_fun <- function(){
      magical_r_function()
}
my_fun()
## [1] "my_fun"


foo_bar <- function(){
      magical_r_function()
}
foo_bar()
## [1] "foo_bar"

ballyhoo <- function(){
    foo_bar()
}
ballyhoo()
## [1] "foo_bar"

tom_foolery <- foo_bar
tom_foolery()
## [1] "tom_foolery"

답변:


18
as.character(match.call()[[1]])

데모:

my_fun <- function(){
  as.character(match.call()[[1]])
}
my_fun()
# [1] "my_fun"
foo_bar <- function(){
  as.character(match.call()[[1]])
}
foo_bar()
# [1] "foo_bar"
ballyhoo <- function(){
  foo_bar()
}
ballyhoo()
# [1] "foo_bar"
tom_foolery <- foo_bar
tom_foolery()
# [1] "tom_foolery"

타일러, 나는 확실히 신경 쓰지 않고 (GG도 좋습니다), 어떤 대답을 선택할 기준이 되었습니까?
r2evans

좋은 질문. 두 가지 모두 탁월한 선택입니다. 둘 다 내 테스트에서 동일하게 작동하는 것 같습니다. GG는 좀 더 자세히 설명했습니다. 결정하기가 힘들었습니다.
Tyler Rinker

새로운 이름에 기능을 할당하는 마지막 조건을 면밀히 조사하면 원래 요청과 더 밀접하게 일치합니다.
Tyler Rinker

내 의견만으로 변경하지 마십시오! 나는 깨지 않고 담당자를 필요로하지 않습니다 (그러나 모두가 나보다 조금 더 있습니다). 아뇨, 그냥 궁금 했어요 난 둘 생각 match.callsys.call"효과"와 "요구 사항"에 약간의 차이가 유효한 기본 기능입니다. 그래서 나는 당신이 다른 것을 선호하는 통찰력이 궁금합니다.
r2evans

12

시도 sys.call(0)호출 객체 출력이 그냥 문자열로 이름을 원한다면 것을 확인 또는 deparse 경우. 다음은이 테스트에 대한 몇 가지 테스트입니다. sys.call은 이름과 인수를 모두 반환하며 [[1]]은 이름 만 선택합니다.

my_fun <- function() deparse(sys.call(0)[[1]])

g <- function() my_fun()

my_fun()
## [1] "my_fun"

g()
## [1] "my_fun"

기능 이름

함수에는 실제로 이름이 없습니다. 함수 이름으로 간주하는 것은 실제로 함수를 보유하고 함수 자체의 일부가 아닌 변수입니다. 함수는 인수, 본문 및 환경으로 구성됩니다. 이러한 구성 요소에는 함수 이름이 없습니다.

익명 함수

또한 익명의 기능을 가질 수 있으며 위와 함께 사용하면 이상한 결과를 반환 할 수 있습니다.

sapply(1:3, function(x) deparse(sys.call(0)[[1]]))
## [1] "FUN" "FUN" "FUN"

가장자리 케이스

특히 익명 함수와 관련하여 deparse여러 요소를 반환 하는 일부 상황이 있으므로 이러한 에지 사례를 다루려면 nlines = 1 인수를 사용하여 deparse (...) [[1]] 또는 R 4.0.0에서 deparse1을 사용하여 @Konrad Rudolph가 언급했습니다.

Map(function(x) deparse(sys.call(0)[[1]], nlines = 1), 1:2)
## [[1]]
## [1] "function (x) "
## 
## [[2]]
## [1] "function (x) "

Map(function(x) deparse(sys.call(0)[[1]]), 1:2)  # without nlines=1
## [[1]]
## [1] "function (x) "             "deparse(sys.call(0)[[1]])"
##
## [[2]]
## [1] "function (x) "             "deparse(sys.call(0)[[1]])"

다른

기억하십시오 . 함수 이름을 원하는 이유가 재귀 적으로 함수를 호출하는 것이라면 Recall()대신 사용하십시오. 도움말 파일에서 :

fib <- function(n)
   if(n<=2) { if(n>=0) 1 else 0 } else Recall(n-1) + Recall(n-2)
fib(4)
## [1] 3

warning and stop 이들은 둘 다 전달 된 인수와 함께 함수 이름을 발행하므로 현재 함수 이름을 얻을 필요가 없습니다.

testWarning <- function() warning("X")
testWarning()
## Warning message:
## In testWarning() : X

2
deparse1기능 의 도입을 통해 R 4.0에서“가장자리 케이스”가 우아하게 해결되었습니다 . deparse채택이 충분히 높아지면 기본적으로 대신 사용을 시작해야한다고 생각합니다 .
Konrad Rudolph

에 대한 +1 Recall, OP가 실제로 필요한 것입니다. 그러나, 피보나치 시퀀스의 당신의 예는 정말 좋은 하나되지 않습니다 : 그것은 당신이 자주 전화를 반복하는 문제가 있습니다 위해 fib(10), fib(8)(한 번, 총 두 번 호출을 fib(10)직접 한 번 fib(9)), fib(7)3 번 호출, fib(6)호출 5 회. 어디로 가는지 봅니까?
Emil Bode

@Emil, 이것은 Recall 도움말 페이지 (답변에 명시된 바와 같이)에서 바로 요점을 분명히 보여줍니다. 다른 이유로 마음에 들지 않으면 R 개발자에게 불만을 제기 할 수 있습니다.
G. Grothendieck

5

우리는 또한 사용할 수 있습니다

my_fun <- function(){
  as.character(as.list(sys.calls()[[1]])[[1]])
 }

my_fun()
#[1] "my_fun"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.