Saya agak terkejut dengan perilaku R dalam kasus yang sangat spesifik. Katakanlah saya mendefinisikan fungsi square yang mengembalikan kuadrat dari argumennya, seperti ini:

square <- function(x) { return(x^2) }

Saya ingin memanggil fungsi ini di dalam fungsi lain, dan saya juga ingin menampilkan namanya ketika saya melakukannya. Saya bisa melakukannya menggunakan deparse(substitute()). Namun, perhatikan contoh berikut:

ds1 <- function(x) {
  print(deparse(substitute(x)))
}

ds1(square)
# [1] "square"

Ini adalah output yang diharapkan, jadi semuanya baik-baik saja. Namun, jika saya meneruskan fungsi yang dibungkus dalam daftar dan memprosesnya menggunakan for loop, hal berikut akan terjadi:

ds2 <- function(x) {
  for (y in x) {
    print(deparse(substitute(y)))
  }
}

ds2(c(square))
# [1] "function (x) "   "{"               "    return(x^2)" "}"  

Adakah yang bisa menjelaskan kepada saya mengapa ini terjadi dan bagaimana saya bisa mencegahnya terjadi?

13
A. Stam 20 Desember 2017, 13:49

1 menjawab

Jawaban Terbaik

Segera setelah Anda menggunakan x di dalam fungsi Anda, fungsi tersebut dievaluasi, sehingga "berhenti menjadi ekspresi (tidak dievaluasi)" dan "mulai menjadi nilai yang dihasilkan (ekspresi yang dievaluasi)". Untuk mencegah hal ini, Anda harus menangkap x dengan substitute sebelum Anda menggunakannya untuk pertama kali.

Hasil substitute adalah objek yang dapat Anda kueri seolah-olah itu adalah daftar. Jadi Anda bisa menggunakan

x <- substitute(x)

Dan kemudian x[[1]] (nama fungsi) dan x[[2]] dan mengikuti (argumen fungsi)

Jadi ini berfungsi:

ds2 <- function(x) {
    x <- substitute(x)
    # you can do `x[[1]]` but you can't use the expression object x in a
    # for loop. So you have to turn it into a list first
    for (y in as.list(x)[-1]) {
        print(deparse(y))
    }
}
ds2(c(square,sum))
## [1] "square"
## [1] "sum"
15
akraf 20 Desember 2017, 11:02