Bu işlev içindeki işlev adını belirleme


15

Bu anonim olmayan işlev içinde işlevin adını nasıl alabilirim? aşağıda bunu denecek bir fonksiyon veya süreç magical_r_function()olduğunu ve beklenen çıktıların ne olacağını varsayıyorum .

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"

Yanıtlar:


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

Demo:

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"

Tyler, kesinlikle umursamıyorum (ve GG'ler de iyidir), ancak hangi cevabı seçmek için kriteriniz vardı?
r2evans

İyi soru. Her ikisi de mükemmel seçimler. Testlerimde ikisi de aynı şekilde çalışıyor gibiydi. GG'ler biraz daha ayrıntı verdi. Karar vermek zor oldu.
Tyler Rinker

Daha yakından incelendiğinde, yeni bir isme bir işlev atamanın son şartı, bu, orijinal soruyla daha yakından uyumludur.
Tyler Rinker

Lütfen sadece yorumumda değişiklik yapmayın! Ben wanking ve tekrar ihtiyaç (ben hepinizden biraz daha var) rağmen. Hayır, sadece merak ettim. Her ikisini de düşünüyorum match.callve sys.call"etkisi" ve "gereksinimleri" küçük fark ile geçerli temel fonksiyonları vardır. Bu yüzden birini diğerini tercih ederken edinebileceğinizi merak ettim.
r2evans

12

sys.call(0)Bir çağrı nesnesi çıktısının uygun olup olmadığını deneyin veya sadece karakter dizesi olarak ad istiyorsanız bunu kullanın. Aşağıda bunun birkaç testi var. sys.call hem adı hem de bağımsız değişkenleri döndürür ve [[1]] yalnızca adı seçer.

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

g <- function() my_fun()

my_fun()
## [1] "my_fun"

g()
## [1] "my_fun"

İşlev adları

İşlevlerin aslında adları olmadığını unutmayın. İşlev adları olarak gördüğümüz şey aslında sadece işlevi tutan ve işlevin kendisinin bir parçası olmayan değişkenlerdir. Bir işlev argümanlardan, bedenden ve bir çevreden oluşur - bu bileşenler arasında işlev adı yoktur.

Anonim işlevler

Ayrıca, isimsiz işlevler olabilir ve bunlar yukarıda kullanıldığında garip sonuçlar verebilir.

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

Edge kutuları

Özellikle anonim işlevler içeren bazı durumlar vardır, burada deparsebirden fazla eleman döndürülür , bu nedenle bu gibi uç durumları kapsamak istiyorsanız, ayrılmak veya kalkış (...) [[1]] veya @Konrad Rudolph tarafından R 4.0.0'da deparse1 kullanılarak belirtilmiştir.

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

Diğer

Hatırlayın . İşlev adının nedenini işlevi yinelemeli olarak çağırmaksa Recall()bunun yerine kullanın. Yardım dosyasından:

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

uyarı ve durdurma Her ikisi de kendisine iletilen argümanla birlikte işlevin adını verir, böylece geçerli işlev adını almanıza gerek kalmaz.

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

2
“Edge kasanız” R 4.0'da deparse1işlevin tanıtılmasıyla zarif bir şekilde çözülmüştür . Sanırım deparsebenimseme yeterince yüksek olduğunda, bunun yerine varsayılan olarak kullanmaya başlamalıyız .
Konrad Rudolph

+1 için RecallOP'nin gerçekten ihtiyaç duyduğu şey olduğunu düşünüyorum. Bununla birlikte, Fibonacci dizisi örneğiniz gerçekten iyi değil: çağrıları sık sık tekrarlamanız sorunu var: çünkü fib(10), fib(8)toplamda 2 kez (bir kez fib(10)doğrudan, bir kez fib(9)), fib(7)3 kez fib(6)denir, denir 5 kere. Bunun nereye gittiğini görüyor musunuz?
Emil Bode

@Emil, Bu, Hatırlama yardım sayfasından (yanıtta belirtildiği gibi) doğrudur, bu yüzden kesinlikle noktayı göstermektedir. Diğer gerekçelerden hoşlanmıyorsanız, R geliştiricilerine şikayet edebilirsiniz.
G. Grothendieck

5

Ayrıca kullanabiliriz

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

my_fun()
#[1] "my_fun"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.