<p>R6 setara dengan metode dunder python __call__</p>

Dibuat pada 29 Nov 2020  ·  7Komentar  ·  Sumber: r-lib/R6

Hai @wch ,

Apakah ada R6 setara dengan __call__ metode dunder di python yang pada dasarnya membuat instance kelas dapat dipanggil seperti fungsi? Apakah ini fitur yang mungkin bisa ditambahkan? Apakah ada kepentingan dalam fitur ini?

Sesuatu seperti:

foo <- R6::R6Class(
  "foo",
  public = list(
    .__call__ = function(args) {...}
  )
)

bar <- foo$new()
bar(...)

Hampir semua metode dunder lainnya dapat diimplementasikan dalam R dengan menulis metode S3 untuk obat generik yang ada, tetapi yang ini sepertinya perlu ditangani secara internal oleh R6 , jika itu mungkin sama sekali.

Semua 7 komentar

Saya cukup yakin bahwa di R, menggunakan () hanya akan berfungsi jika objeknya adalah suatu fungsi. Yang dapat Anda lakukan adalah mengembalikan fungsinya, dan menambahkan objek R6 sebagai atributnya.

library(R6)

Foo <- R6Class("Foo",
  public = list(
    call = function() {
      self$x
    },
    x = 10,
    printx = function() {
      cat("The value of x is", self$x)
    }
  )
)

foo <- function() {
  obj <- Foo$new()

  # Return the obj$call method, and attach the full object as an attribute named
  # 'impl'. Also add the class "wrapped" to it so that we can define `$` and 
  # `$<-` methods for it.
  structure(
    obj$call,
    impl = obj,
    class = "wrapped"
  )
}

# The $ and $<- methods essentially pass through to the "impl" object attached
# to the function.
`$.wrapped` <- function(x, name) {
  obj <- attr(x, "impl", exact = TRUE)
  obj[[name]]
}

`$<-.wrapped` <- function(x, name, value) {
  obj <- attr(x, "impl", exact = TRUE)
  obj[[name]] <- value
  x
}



f <- foo()
f()
#> [1] 10
f$printx()
#> The value of x is 10
f$x
#> [1] 10

f$x <- 20
f()
#> [1] 20
f$printx()
#> The value of x is 20

Metode panggilan dunder terasa sangat tidak- R -seperti, jadi saya pikir itu tidak mungkin. Ini adalah solusi yang menarik sekalipun. Sangat pintar. Terima kasih atas tanggapannya.

Saya kira kelemahannya adalah kurangnya bantuan pelengkapan otomatis untuk fungsi internal ( f$printx() ) dan args internal f$printx(arg) , tampaknya tidak dapat dihindari.

Anda dapat menambahkan pelengkapan otomatis dengan ini:

.DollarNames.wrapped <- function(x, pattern) {
  ls(attr(x, "impl", exact = TRUE))
}

Err, wah. Itu luar biasa. Sangat keren.

Hai @wch ,

Saya punya pertanyaan aneh lain yang mungkin bisa Anda pecahkan. Tapi yang satu ini sangat aneh.

Mirip dengan pertanyaan di atas terkait dengan memiliki objek yang terlihat dan terasa seperti objek normal, tetapi memiliki beberapa metode yang dienkapsulasi. Saya bertanya-tanya apakah mungkin untuk memperbarui objek global ketika nilai yang menjadi dasarnya diperbarui dalam contoh R6? Ini mungkin agak membingungkan jadi inilah contohnya.

x adalah objek yang kita inginkan untuk digunakan oleh pengguna - Ini hanya bilangan bulat. Tetapi melalui keajaiban yang Anda bagikan, Anda mengemas objek R6 sebagai atribut sehingga beberapa metode internal tersedia (misalnya x$update() ). Tetapi ketika Anda membuat pembaruan dengan x$update(20) , itu hanya memperbarui self$x dan bukan x . Apakah mungkin untuk menyebarkan perubahan ke definisi global x , mungkin dengan penugasan super?

library(R6)

Foo <- R6Class(
  "Foo",
  public = list(
    x = 10,
    update = function(value) {
      self$x <- value
    }
  )
)

foo <- function() {
  obj <- Foo$new()
  structure(
    obj$x,
    impl = obj,
    class = "wrapped"
  )
}

`$.wrapped` <- function(x, name) {
  obj <- attr(x, "impl", exact = TRUE)
  obj[[name]]
}

`$<-.wrapped` <- function(x, name, value) {
  obj <- attr(x, "impl", exact = TRUE)
  obj[[name]] <- value
  obj$x
}

.DollarNames.wrapped <- function(x, pattern) {
  ls(attr(x, "impl", exact = TRUE))
}


x <- foo()
x
#> [1] 10
#> attr(,"impl")
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     update: function (value) 
#>     x: 10
#> attr(,"class")
#> [1] "wrapped"
x$update(20)
x
#> [1] 10
#> attr(,"impl")
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     update: function (value) 
#>     x: 20
#> attr(,"class")
#> [1] "wrapped"

Saya kira itu dapat diringkas sebagai modifikasi di tempat, tetapi dalam situasi di mana kita ingin objek terlihat dan terasa seperti objek R familiar dan umum, tetapi memiliki metode yang disematkan ini yang bertindak pada objek.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

rappster picture rappster  ·  11Komentar

paulstaab picture paulstaab  ·  3Komentar

rappster picture rappster  ·  3Komentar

mb706 picture mb706  ·  4Komentar

wch picture wch  ·  8Komentar