diff --git a/dev/LICENSE-text.html b/dev/LICENSE-text.html index 2b1dfb0..6ecbb73 100644 --- a/dev/LICENSE-text.html +++ b/dev/LICENSE-text.html @@ -38,8 +38,8 @@ -
YEAR: 2023
-COPYRIGHT HOLDER: Posit Software, PBC
+
YEAR: 2024
+COPYRIGHT HOLDER: R6 authors
 
diff --git a/dev/LICENSE.html b/dev/LICENSE.html new file mode 100644 index 0000000..164c3a3 --- /dev/null +++ b/dev/LICENSE.html @@ -0,0 +1,63 @@ + +MIT License • R6 + Skip to content + + +
+
+
+ +
+ +

Copyright (c) 2024 R6 authors

+

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+ +
+ + +
+ + diff --git a/dev/articles/Performance.html b/dev/articles/Performance.html index 0040103..2d5541b 100644 --- a/dev/articles/Performance.html +++ b/dev/articles/Performance.html @@ -433,16 +433,16 @@

Object instantiation speedspeed <- mb_summary(speed) speed #> name median -#> 1 RC$new() 203.4195 -#> 2 R6$new() 30.9830 -#> 3 R6NoClass$new() 31.3240 -#> 4 R6NonPortable$new() 31.5435 -#> 5 R6NonCloneable$new() 31.2230 -#> 6 R6Bare$new() 27.7870 -#> 7 R6Private$new() 42.9850 -#> 8 R6PrivateBare$new() 39.1130 -#> 9 FunctionEnvClass() 1.4875 -#> 10 FunctionEnvNoClass() 1.0020

+#> 1 RC$new() 202.1975 +#> 2 R6$new() 30.7070 +#> 3 R6NoClass$new() 31.3490 +#> 4 R6NonPortable$new() 31.4990 +#> 5 R6NonCloneable$new() 31.1585 +#> 6 R6Bare$new() 27.5015 +#> 7 R6Private$new() 42.7800 +#> 8 R6PrivateBare$new() 39.1180 +#> 9 FunctionEnvClass() 1.4480 +#> 10 FunctionEnvNoClass() 1.0175

The plot below shows the median instantiation time.

Reference classes are much slower to instantiate than the other types @@ -483,16 +483,16 @@

Field access speedspeed <- mb_summary(speed) speed #> name median -#> 1 rc$x 5.7555 -#> 2 r6$x 0.6515 +#> 1 rc$x 5.6210 +#> 2 r6$x 0.6510 #> 3 r6noclass$x 0.2100 -#> 4 r6noport$x 0.6915 -#> 5 r6noclone$x 0.7110 +#> 4 r6noport$x 0.6810 +#> 5 r6noclone$x 0.7210 #> 6 r6bare$x 0.2110 -#> 7 r6priv$x 0.7120 -#> 8 r6priv_bare$x 0.2310 -#> 9 fun_env$x 0.6260 -#> 10 fun_env_nc$x 0.2200 +#> 7 r6priv$x 0.7215 +#> 8 r6priv_bare$x 0.2210 +#> 9 fun_env$x 0.6510 +#> 10 fun_env_nc$x 0.2210

Accessing the field of a reference class is much slower than the other methods.

@@ -523,15 +523,15 @@

Field setting speed) speed <- mb_summary(speed) speed -#> name median -#> 1 rc$x <- 4 29.4650 -#> 2 r6$x <- 4 1.1720 -#> 3 r6noclass$x <- 4 0.6765 -#> 4 r6noport$x <- 4 1.2130 -#> 5 r6noclone$x <- 4 1.2570 -#> 6 r6bare$x <- 4 0.7110 -#> 7 fun_env$x <- 4 1.1625 -#> 8 fun_env_nc$x <- 4 0.6865 +#> name median +#> 1 rc$x <- 4 29.595 +#> 2 r6$x <- 4 1.182 +#> 3 r6noclass$x <- 4 0.701 +#> 4 r6noport$x <- 4 1.263 +#> 5 r6noclone$x <- 4 1.292 +#> 6 r6bare$x <- 4 0.722 +#> 7 fun_env$x <- 4 1.182 +#> 8 fun_env_nc$x <- 4 0.692

Reference classes are significantly slower than the others, again. In this case, there’s additional overhead due to type-checking the @@ -565,16 +565,16 @@

Speed of method call that ac speed <- mb_summary(speed) speed #> name median -#> 1 rc$getx() 5.9010 -#> 2 r6$getx() 1.5580 -#> 3 r6noclass$getx() 0.5460 +#> 1 rc$getx() 5.7805 +#> 2 r6$getx() 1.5730 +#> 3 r6noclass$getx() 0.5510 #> 4 r6noport$getx() 0.8620 -#> 5 r6noclone$getx() 1.6580 -#> 6 r6bare$getx() 0.3610 -#> 7 r6priv$getx() 1.0620 -#> 8 r6priv_bare$getx() 0.3655 -#> 9 fun_env$getx() 0.9120 -#> 10 fun_env_nc$getx() 0.4560 +#> 5 r6noclone$getx() 1.6335 +#> 6 r6bare$getx() 0.3710 +#> 7 r6priv$getx() 1.0770 +#> 8 r6priv_bare$getx() 0.3810 +#> 9 fun_env$getx() 0.9220 +#> 10 fun_env_nc$getx() 0.4710

The reference class is the slowest.

r6 is also somewhat slower than the others. There are @@ -647,10 +647,10 @@

Assignment using self$x <-speed <- mb_summary(speed) speed #> name median -#> 1 rc_self$setx() 35.8470 -#> 2 rc_noself$setx() 20.0420 -#> 3 r6_self$setx() 2.8800 -#> 4 r6_noself$setx() 1.3075 +#> 1 rc_self$setx() 35.4160 +#> 2 rc_noself$setx() 19.9325 +#> 3 r6_self$setx() 2.8605 +#> 4 r6_noself$setx() 1.3520

For both reference and non-portable R6 classes, assignment using .self$x <- is somewhat slower than using @@ -702,9 +702,9 @@

Overhead from usi speed <- mb_summary(speed) speed #> name median -#> 1 e1$x 0.191 -#> 2 e2$x 0.541 -#> 3 e3$x 0.842 +#> 1 e1$x 0.1900 +#> 2 e2$x 0.5415 +#> 3 e3$x 0.8520

Using $ on e2 and e3 is much slower than on e1. This is because e2 and e3 have a class attribute. Even though there’s no @@ -738,9 +738,9 @@

Lists vs. environments, and $)) #> name median #> 1 lst 0.181 -#> 2 env 0.170 -#> 3 lst[["x"]] 0.131 -#> 4 env[["x"]] 0.110 +#> 2 env 0.171 +#> 3 lst[["x"]] 0.140 +#> 4 env[["x"]] 0.120

Performance is comparable across environments and lists.

The [[ operator is slightly faster than $, probably because it doesn’t need to convert the unevaluated symbol to a diff --git a/dev/articles/Performance_files/figure-html/unnamed-chunk-25-1.png b/dev/articles/Performance_files/figure-html/unnamed-chunk-25-1.png index f9bd168..29b52f5 100644 Binary files a/dev/articles/Performance_files/figure-html/unnamed-chunk-25-1.png and b/dev/articles/Performance_files/figure-html/unnamed-chunk-25-1.png differ diff --git a/dev/articles/Performance_files/figure-html/unnamed-chunk-28-1.png b/dev/articles/Performance_files/figure-html/unnamed-chunk-28-1.png index eeb23d8..20ea666 100644 Binary files a/dev/articles/Performance_files/figure-html/unnamed-chunk-28-1.png and b/dev/articles/Performance_files/figure-html/unnamed-chunk-28-1.png differ diff --git a/dev/articles/Performance_files/figure-html/unnamed-chunk-30-1.png b/dev/articles/Performance_files/figure-html/unnamed-chunk-30-1.png index da307e6..3a30cc8 100644 Binary files a/dev/articles/Performance_files/figure-html/unnamed-chunk-30-1.png and b/dev/articles/Performance_files/figure-html/unnamed-chunk-30-1.png differ diff --git a/dev/articles/Performance_files/figure-html/unnamed-chunk-32-1.png b/dev/articles/Performance_files/figure-html/unnamed-chunk-32-1.png index 45a89fa..2b4a6ea 100644 Binary files a/dev/articles/Performance_files/figure-html/unnamed-chunk-32-1.png and b/dev/articles/Performance_files/figure-html/unnamed-chunk-32-1.png differ diff --git a/dev/articles/Performance_files/figure-html/unnamed-chunk-36-1.png b/dev/articles/Performance_files/figure-html/unnamed-chunk-36-1.png index 1713453..7c420a6 100644 Binary files a/dev/articles/Performance_files/figure-html/unnamed-chunk-36-1.png and b/dev/articles/Performance_files/figure-html/unnamed-chunk-36-1.png differ diff --git a/dev/index.html b/dev/index.html index 4e14ac5..57e07fc 100644 --- a/dev/index.html +++ b/dev/index.html @@ -123,9 +123,8 @@

Links

diff --git a/dev/pkgdown.yml b/dev/pkgdown.yml index d6d1813..4ed9b60 100644 --- a/dev/pkgdown.yml +++ b/dev/pkgdown.yml @@ -6,7 +6,7 @@ articles: Introduction: Introduction.html Performance: Performance.html Portable: Portable.html -last_built: 2024-09-05T15:30Z +last_built: 2024-09-06T07:28Z urls: reference: https://r6.r-lib.org/reference article: https://r6.r-lib.org/articles diff --git a/dev/search.json b/dev/search.json index ea644ce..4dca686 100644 --- a/dev/search.json +++ b/dev/search.json @@ -1 +1 @@ -[{"path":"https://r6.r-lib.org/dev/articles/Debugging.html","id":"enabling-debugging-for-all-future-instances-of-a-class","dir":"Articles","previous_headings":"","what":"Enabling debugging for all future instances of a class","title":"Debugging","text":"R6 generator objects method called debug() enable debugging method. affect instances class created debug() called. disable debugging future instances, use generator’s undebug() method:","code":"# An example class Simple <- R6Class(\"Simple\", public = list( x = 10, getx = function() self$x ) ) # This will enable debugging the getx() method for objects of the 'Simple' # class that are instantiated in the future. Simple$debug(\"getx\") s <- Simple$new() s$getx() # [Debugging prompt] # Disable debugging for future instances: Simple$undebug(\"getx\") s <- Simple$new() s$getx() #> [1] 10"},{"path":"https://r6.r-lib.org/dev/articles/Debugging.html","id":"debugging-methods-in-individual-objects","dir":"Articles","previous_headings":"","what":"Debugging methods in individual objects","title":"Debugging","text":"enable debugging method single instance object, use debug() function (debug() method generator object). Use undebug() disable debugging object’s method. can also use trace() function specify method want drop debugging console.","code":"s <- Simple$new() debug(s$getx) s$getx() # [Debugging prompt] undebug(s$getx) s$getx() #> [1] 10"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"r6-classes","dir":"Articles","previous_headings":"","what":"R6 classes","title":"Introduction","text":"R6 classes similar R’s reference classes, lighter weight, avoid issues come along using S4 (R’s reference classes based S4). information speed memory footprint, see vignette(\"Performance\"). Unlike many objects R, instances (objects) R6 classes reference semantics. R6 classes also support: public private methods active bindings inheritance (superclasses) works across packages name R6? R’s reference classes introduced, users, following names R’s existing class systems S3 S4, called new class system R5 jest. Although reference classes actually called R5, name package classes takes inspiration name. name R5 also code-name used different object system started Simon Urbanek, meant solve issues S4 relating syntax performance. However, R5 branch shelved little development, never released.","code":""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"basics","dir":"Articles","previous_headings":"R6 classes","what":"Basics","title":"Introduction","text":"’s create simple R6 class. public argument list items, can functions fields (non-functions). Functions used methods. instantiate object class, use $new(): $new() method creates object calls initialize() method, exists. Inside class methods, self refers object. Public members object (’ve seen far) accessed self$x, assignment done self$x <- y. object instantiated, can access public fields methods $: Implementation note: external face R6 object basically environment public members . also known public environment. R6 object’s methods separate enclosing environment , roughly speaking, environment “run ”. self binding found, simply reference back public environment.","code":"library(R6) Person <- R6Class(\"Person\", public = list( name = NULL, hair = NULL, initialize = function(name = NA, hair = NA) { self$name <- name self$hair <- hair self$greet() }, set_hair = function(val) { self$hair <- val }, greet = function() { cat(paste0(\"Hello, my name is \", self$name, \".\\n\")) } ) ) ann <- Person$new(\"Ann\", \"black\") #> Hello, my name is Ann. ann #> #> Public: #> clone: function (deep = FALSE) #> greet: function () #> hair: black #> initialize: function (name = NA, hair = NA) #> name: Ann #> set_hair: function (val) ann$hair #> [1] \"black\" ann$greet() #> Hello, my name is Ann. ann$set_hair(\"red\") ann$hair #> [1] \"red\""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"private-members","dir":"Articles","previous_headings":"R6 classes","what":"Private members","title":"Introduction","text":"previous example, members public. ’s also possible add private members: Whereas public members accessed self, like self$add(), private members accessed private, like private$queue. public members can accessed usual: However, private members can’t accessed directly: useful design pattern methods return self (invisibly) possible, makes chainable. example, add() method returns self can chain together: hand, remove() returns value removed, ’s chainable:","code":"Queue <- R6Class(\"Queue\", public = list( initialize = function(...) { for (item in list(...)) { self$add(item) } }, add = function(x) { private$queue <- c(private$queue, list(x)) invisible(self) }, remove = function() { if (private$length() == 0) return(NULL) # Can use private$queue for explicit access head <- private$queue[[1]] private$queue <- private$queue[-1] head } ), private = list( queue = list(), length = function() base::length(private$queue) ) ) q <- Queue$new(5, 6, \"foo\") # Add and remove items q$add(\"something\") q$add(\"another thing\") q$add(17) q$remove() #> [1] 5 q$remove() #> [1] 6 q$queue #> NULL q$length() #> Error: attempt to apply non-function q$add(10)$add(11)$add(12) q$remove() #> [1] \"foo\" q$remove() #> [1] \"something\" q$remove() #> [1] \"another thing\" q$remove() #> [1] 17"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"active-bindings","dir":"Articles","previous_headings":"R6 classes","what":"Active bindings","title":"Introduction","text":"Active bindings look like fields, time accessed, call function. always publicly visible. active binding accessed reading value, calls function value missing argument: ’s accessed assigning value, uses assignment value value argument: function takes arguments, ’s possible use <-: Implementation note: Active bindings bound public environment. enclosing environment functions also public environment.","code":"Numbers <- R6Class(\"Numbers\", public = list( x = 100 ), active = list( x2 = function(value) { if (missing(value)) return(self$x * 2) else self$x <- value/2 }, rand = function() rnorm(1) ) ) n <- Numbers$new() n$x #> [1] 100 n$x2 #> [1] 200 n$x2 <- 1000 n$x #> [1] 500 n$rand #> [1] 0.2648 n$rand #> [1] 2.171 n$rand <- 3 #> Error: unused argument (quote(3))"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"inheritance","dir":"Articles","previous_headings":"R6 classes","what":"Inheritance","title":"Introduction","text":"One R6 class can inherit another. words, can super- sub-classes. Subclasses can additional methods, can also methods override superclass methods. example queue retains history, ’ll add show() method override remove() method: Superclass methods can called super$xx(). CountingQueue (example ) keeps count total number objects ever added queue. overriding add() method – increments counter calls superclass’s add() method, super$add(x): Note , unlike classical OOP languages (e.g. C++), R6 subclasses also access private methods superclass. instance, following example, Duck class private method $quack(), subclass Mallard can access using super$quack().","code":"# Note that this isn't very efficient - it's just for illustrating inheritance. HistoryQueue <- R6Class(\"HistoryQueue\", inherit = Queue, public = list( show = function() { cat(\"Next item is at index\", private$head_idx + 1, \"\\n\") for (i in seq_along(private$queue)) { cat(i, \": \", private$queue[[i]], \"\\n\", sep = \"\") } }, remove = function() { if (private$length() - private$head_idx == 0) return(NULL) private$head_idx <- private$head_idx + 1 private$queue[[private$head_idx]] } ), private = list( head_idx = 0 ) ) hq <- HistoryQueue$new(5, 6, \"foo\") hq$show() #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 5 hq$show() #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 6 CountingQueue <- R6Class(\"CountingQueue\", inherit = Queue, public = list( add = function(x) { private$total <- private$total + 1 super$add(x) }, get_total = function() private$total ), private = list( total = 0 ) ) cq <- CountingQueue$new(\"x\", \"y\") cq$get_total() #> [1] 2 cq$add(\"z\") cq$remove() #> [1] \"x\" cq$remove() #> [1] \"y\" cq$get_total() #> [1] 3 Duck <- R6Class(\"Duck\", private = list(quack = function() print(\"Quack Quack\")) ) Mallard <- R6Class(\"Mallard\", inherit = Duck, public = list(quack = function() super$quack()) ) myMallard <- Mallard$new() myMallard$quack() #> [1] \"Quack Quack\""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"fields-containing-reference-objects","dir":"Articles","previous_headings":"R6 classes","what":"Fields containing reference objects","title":"Introduction","text":"R6 class contains fields also reference semantics (e.g., R6 objects, environments), fields populated $initialize() method. field set reference object directly class definition, object shared across instances R6 class. ’s example: avoid , populate field initialize method:","code":"SimpleClass <- R6Class(\"SimpleClass\", public = list(x = NULL) ) SharedField <- R6Class(\"SharedField\", public = list( e = SimpleClass$new() ) ) s1 <- SharedField$new() s1$e$x <- 1 s2 <- SharedField$new() s2$e$x <- 2 # Changing s2$e$x has changed the value of s1$e$x s1$e$x #> [1] 2 NonSharedField <- R6Class(\"NonSharedField\", public = list( e = NULL, initialize = function() self$e <- SimpleClass$new() ) ) n1 <- NonSharedField$new() n1$e$x <- 1 n2 <- NonSharedField$new() n2$e$x <- 2 # n2$e$x does not affect n1$e$x n1$e$x #> [1] 1"},{"path":[]},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"adding-members-to-an-existing-class","dir":"Articles","previous_headings":"Other topics","what":"Adding members to an existing class","title":"Introduction","text":"sometimes useful add members class class already created. can done using $set() method generator object. new members present instances created $set() called. prevent modification class, can use lock_class=TRUE creating class. can also lock unlock class follows:","code":"Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) Simple$set(\"public\", \"getx2\", function() self$x*2) # To replace an existing member, use `overwrite=TRUE` Simple$set(\"public\", \"x\", 10, overwrite = TRUE) s <- Simple$new() s$x #> [1] 10 s$getx2() #> [1] 20 # Create a locked class Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ), lock_class = TRUE ) # This would result in an error Simple$set(\"public\", \"y\", 2) #> Error in Simple$set(\"public\", \"y\", 2): Can't modify a locked R6 class. # Unlock the class Simple$unlock() # Now it works Simple$set(\"public\", \"y\", 2) # Lock the class again Simple$lock()"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"cloning-objects","dir":"Articles","previous_headings":"Other topics","what":"Cloning objects","title":"Introduction","text":"default, R6 objects method named $clone() making copy object. don’t want clone method added, can use cloneable=FALSE creating class. loaded R6 object clone method, function uses 84.11 kB bytes, additional object, clone method costs trivial amount space (112 B bytes). Note cloneable inheritance: superclass cloneable=FALSE, subclasses cloneable. (subclass sets cloneable=TRUE, message printed objects instantiated objects cloneable.)","code":"Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) s <- Simple$new() # Create a clone s1 <- s$clone() # Modify it s1$x <- 2 s1$getx() #> [1] 2 # Original is unaffected by changes to the clone s$getx() #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"deep-cloning","dir":"Articles","previous_headings":"Other topics > Cloning objects","what":"Deep cloning","title":"Introduction","text":"fields objects reference semantics (environments, R6 objects, reference class objects), copy get reference object. sometimes desirable, often . example, ’ll create object c1 contains another R6 object, s, clone . original’s clone’s s fields refer object, modifying one results change reflected . make clone receives copy s, can use deep=TRUE option: default behavior $clone(deep=TRUE) copy fields R6 objects, copy fields environments, reference class objects, data structures contain reference-type objects (example, list R6 object). R6 object contains types objects want make deep clone , must provide function deep cloning, private method named deep_clone. example R6 object two fields, b, environments, contain value x. also field v regular (non-reference) value, private deep_clone method. deep_clone method called field. passed name value field, value returns used clone. c1$clone(deep=TRUE) called, deep_clone method called field c1, passed name field value. version, environment gets copied, b , v (doesn’t matter since v reference object). can test clone: example deep_clone method , checked name field determine , also check value, using inherits(value, \"R6\"), .environment(), .","code":"Simple <- R6Class(\"Simple\", public = list(x = 1)) Cloneable <- R6Class(\"Cloneable\", public = list( s = NULL, initialize = function() self$s <- Simple$new() ) ) c1 <- Cloneable$new() c2 <- c1$clone() # Change c1's `s` field c1$s$x <- 2 # c2's `s` is the same object, so it reflects the change c2$s$x #> [1] 2 c3 <- c1$clone(deep = TRUE) # Change c1's `s` field c1$s$x <- 3 # c2's `s` is different c3$s$x #> [1] 2 CloneEnv <- R6Class(\"CloneEnv\", public = list( a = NULL, b = NULL, v = 1, initialize = function() { self$a <- new.env(parent = emptyenv()) self$b <- new.env(parent = emptyenv()) self$a$x <- 1 self$b$x <- 1 } ), private = list( deep_clone = function(name, value) { # With x$clone(deep=TRUE) is called, the deep_clone gets invoked once for # each field, with the name and value. if (name == \"a\") { # `a` is an environment, so use this quick way of copying list2env(as.list.environment(value, all.names = TRUE), parent = emptyenv()) } else { # For all other fields, just return the value value } } ) ) c1 <- CloneEnv$new() c2 <- c1$clone(deep = TRUE) # Modifying c1$a doesn't affect c2$a, because they're separate objects c1$a$x <- 2 c2$a$x #> [1] 1 # Modifying c1$b does affect c2$b, because they're the same object c1$b$x <- 3 c2$b$x #> [1] 3 # Modifying c1$v doesn't affect c2$v, because they're not reference objects c1$v <- 4 c2$v #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"printing-r6-objects-to-the-screen","dir":"Articles","previous_headings":"Other topics","what":"Printing R6 objects to the screen","title":"Introduction","text":"R6 objects default $print() method lists members object. class defines $print() method, overrides default one.","code":"PrettyCountingQueue <- R6Class(\"PrettyCountingQueue\", inherit = CountingQueue, public = list( print = function(...) { cat(\" of \", self$get_total(), \" elements\\n\", sep = \"\") } ) ) pq <- PrettyCountingQueue$new(1, 2, \"foobar\") pq #> of 3 elements"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"finalizers","dir":"Articles","previous_headings":"Other topics","what":"Finalizers","title":"Introduction","text":"Sometimes ’s useful run function object garbage collected. example, may want make sure file database connection gets closed. , can define private $finalize() method, called arguments object garbage collected. NOTE: R6 version 2.3.0 (released 2018-10-04) , $finalize() method public. version 2.4.0, can public private. Private preferable ’s reason finalizer needs publicly accessible. use private finalizer R package, set R6 version dependency R6 (>= 2.4.0). 2.6.0, R6 prints message finalizer public. future version, emit warnings, finally, longer support public finalizers. Finalizers implemented using reg.finalizer() function, set onexit=TRUE, finalizer also called R exits. useful cases, like database connections.","code":"A <- R6Class(\"A\", private = list( finalize = function() { print(\"Finalizer has been called!\") } )) # Instantiate an object: obj <- A$new() # Remove the single existing reference to it, and force garbage collection # (normally garbage collection will happen automatically from time # to time) rm(obj); gc() #> [1] \"Finalizer has been called!\" #> used (Mb) gc trigger (Mb) max used (Mb) #> Ncells 701830 37.5 1364540 72.9 1364540 72.9 #> Vcells 1324395 10.2 8388608 64.0 3573020 27.3"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"class-methods-vs--member-functions","dir":"Articles","previous_headings":"Other topics","what":"Class methods vs. member functions","title":"Introduction","text":"R6 class definition contains functions public private sections, functions class methods: can access self (well private super available). R6 object cloned, resulting object’s methods self refers new object. works changing enclosing environment method cloned object. contrast class methods, can also add regular functions members R6 object. can done assigning function field $initialize() method, object instantiated. functions class methods, access self, private, super. trivial class method get_self() simply returns self, well empty member, fn. example, ’ll assign function fn body get_self. However, since ’s regular function, self refer something R6 object: R6 2.3.0, object cloned, member (non-method) functions enclosing environment changed, one normally expect. behave way:","code":"FunctionWrapper <- R6Class(\"FunctionWrapper\", public = list( get_self = function() { self }, fn = NULL ) ) a <- FunctionWrapper$new() # Create a function that accesses a variable named `self`. # Note that `self` in this function's scope refers to 100, not to the R6 object. self <- 100 a$fn <- function() { self } a$get_self() #> #> Public: #> clone: function (deep = FALSE) #> fn: function () #> get_self: function () a$fn() #> [1] 100 b <- a$clone() b$get_self() #> #> Public: #> clone: function (deep = FALSE) #> fn: function () #> get_self: function () b$fn() #> [1] 100"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"class-definitions","dir":"Articles","previous_headings":"","what":"Class definitions","title":"R6 and Reference Class performance tests","text":"’ll start defining number classes class-like entities, using reference classes, R6 classes, simple environments created directly functions. number options R6 can affect size resulting objects, use number variants. classes used speed memory tests follow. lot boring code, may want skip ahead results. classes basic characteristics: field named x contains number. way initializing value x. method named getx retrieving value x. method named inc incrementing value x. fields methods accessed $ operator, object named obj, use obj$x obj$getx().","code":""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r-reference-class","dir":"Articles","previous_headings":"Class definitions","what":"R reference class","title":"R6 and Reference Class performance tests","text":"reference classes, binding points back object named .self. Within method, assignment can done using .self, .self$x <- 10, using <<-, x <<- 10. create object, simply call $new() class:","code":"RC <- setRefClass(\"RC\", fields = list(x = \"numeric\"), methods = list( initialize = function(x = 1) .self$x <- x, getx = function() x, inc = function(n = 1) x <<- x + n ) ) RC$new() #> Reference class object of class \"RC\" #> Field \"x\": #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class","dir":"Articles","previous_headings":"Class definitions","what":"R6 class","title":"R6 and Reference Class performance tests","text":"Creating R6 class similar reference class, except ’s need separate fields methods, can’t specify types fields. Whereas reference classes use .self, R6 classes use self (without leading period). reference classes, objects instantiated calling $new(): R6 object essentially just set environments structured particular way. fields methods R6 object bindings (, names) public environment. also separate environment enclosing environment methods (“run ” environment contains binding named self, simply reference public environment).","code":"R6 <- R6Class(\"R6\", public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- x + n ) ) R6$new() #> #> Public: #> clone: function (deep = FALSE) #> getx: function () #> inc: function (n = 1) #> initialize: function (x = 1) #> x: 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-without-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, without class attribute","title":"R6 and Reference Class performance tests","text":"default, class attribute added R6 objects. attribute adds slight performance penalty R attempt use S3 dispatch using $ object. ’s possible generate objects without class attribute, using class=FALSE: Note without class attribute, S3 method dispatch objects possible.","code":"R6NoClass <- R6Class(\"R6NoClass\", class = FALSE, public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- self$x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-non-portable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, non-portable","title":"R6 and Reference Class performance tests","text":"default, R6 objects portable. means inheritance can classes different packages. However, also requires use self$ private$ access members, incurs small performance penalty. portable=FALSE used, members can accessed without using self$, assignment can done <<-:","code":"R6NonPortable <- R6Class(\"R6NonPortable\", portable = FALSE, public = list( x = NULL, initialize = function(value = 1) x <<- value, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-cloneablefalse","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with cloneable=FALSE","title":"R6 and Reference Class performance tests","text":"default, R6 objects clone() method, fairly large function. need feature, can save memory using cloneable=FALSE.","code":"R6NonCloneable <- R6Class(\"R6NonCloneable\", cloneable = FALSE, public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- self$x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-without-class-attribute-non-portable-and-non-cloneable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, without class attribute, non-portable, and non-cloneable","title":"R6 and Reference Class performance tests","text":"comparison, ’ll use R6 class without class attribute, non-portable, non-cloneable. stripped-can make R6 object.","code":"R6Bare <- R6Class(\"R6Bare\", portable = FALSE, class = FALSE, cloneable = FALSE, public = list( x = NULL, initialize = function(value = 1) x <<- value, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-public-and-private-members","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with public and private members","title":"R6 and Reference Class performance tests","text":"variant public private members. Instead single self object refers items object, objects self (refers public items) private.","code":"R6Private <- R6Class(\"R6Private\", private = list(x = NULL), public = list( initialize = function(x = 1) private$x <- x, getx = function() private$x, inc = function(n = 1) private$x <- private$x + n ) ) R6Private$new() #> #> Public: #> clone: function (deep = FALSE) #> getx: function () #> inc: function (n = 1) #> initialize: function (x = 1) #> Private: #> x: 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-public-and-private-no-class-attribute-non-portable-and-non-cloneable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with public and private, no class attribute, non-portable, and non-cloneable","title":"R6 and Reference Class performance tests","text":"comparison, ’ll add version without class attribute, non-portable, non-cloneable.","code":"R6PrivateBare <- R6Class(\"R6PrivateBare\", portable = FALSE, class = FALSE, cloneable = FALSE, private = list(x = NULL), public = list( initialize = function(x = 1) private$x <- x, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"environment-created-by-a-function-call-with-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"Environment created by a function call, with class attribute","title":"R6 and Reference Class performance tests","text":"R, environments passed reference. simple way create object ’s passed reference use environment created invocation function. function captures environment, attaches class , returns : Even though x isn’t declared function body, gets captured ’s argument function. Objects created way similar created R6 generator created .","code":"FunctionEnvClass <- function(x = 1) { inc <- function(n = 1) x <<- x + n getx <- function() x self <- environment() class(self) <- \"FunctionEnvClass\" self } ls(FunctionEnvClass()) #> [1] \"getx\" \"inc\" \"self\" \"x\""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"environment-created-by-a-function-call-without-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"Environment created by a function call, without class attribute","title":"R6 and Reference Class performance tests","text":"can make even simpler type reference object previous one, class attribute, self object: simply environment objects .","code":"FunctionEnvNoClass <- function(x = 1) { inc <- function(n = 1) x <<- x + n getx <- function() x environment() } ls(FunctionEnvNoClass()) #> [1] \"getx\" \"inc\" \"x\""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"tests","dir":"Articles","previous_headings":"","what":"Tests","title":"R6 and Reference Class performance tests","text":"timings using microbenchmark(), results reported microseconds, useful value probably median column.","code":""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"memory-footprint","dir":"Articles","previous_headings":"Tests","what":"Memory footprint","title":"R6 and Reference Class performance tests","text":"much memory single instance object take, much memory additional object take? ’ll use functions obj_size obj_sizes (shown bottom document) calculate sizes. Sizes type object, bytes: results plotted . Note plots different x scales. preliminary observations first instance various classes: Using reference class consumes large amount memory. R6 objects, option largest impact cloneable: clone() method saves around 40 kB memory. subsequent instances classes, isn’t nearly much difference different kinds. appeared using reference class takes huge amount memory, much shared reference classes. Adding object different reference class doesn’t require much memory — around 38KB:","code":"sizes <- obj_sizes( RC$new(), R6$new(), R6NoClass$new(), R6NonPortable$new(), R6NonCloneable$new(), R6Bare$new(), R6Private$new(), R6PrivateBare$new(), FunctionEnvClass(), FunctionEnvNoClass() ) sizes #> one incremental #> RC$new() 2032832 1400 #> R6$new() 97200 1016 #> R6NoClass$new() 97920 896 #> R6NonPortable$new() 96872 960 #> R6NonCloneable$new() 14288 904 #> R6Bare$new() 13488 728 #> R6Private$new() 98112 1128 #> R6PrivateBare$new() 14512 840 #> FunctionEnvClass() 13424 616 #> FunctionEnvNoClass() 11944 504 RC2 <- setRefClass(\"RC2\", fields = list(x = \"numeric\"), methods = list( initialize = function(x = 2) .self$x <<- x, inc = function(n = 2) x <<- x * n ) ) # Calcualte the size of a new RC2 object, over and above an RC object as.numeric(obj_size(RC$new(), RC2$new()) - obj_size(RC$new())) #> [1] 0 0"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"object-instantiation-speed","dir":"Articles","previous_headings":"Tests","what":"Object instantiation speed","title":"R6 and Reference Class performance tests","text":"much time take create one objects? shows median time, microseconds: plot shows median instantiation time. Reference classes much slower instantiate types classes. Instantiating R6 objects roughly 5 times faster. Creating environment simple function call another 20-30 times faster.","code":"# Function to extract the medians from microbenchmark results mb_summary <- function(x) { res <- summary(x, unit=\"us\") data.frame(name = res$expr, median = res$median) } speed <- microbenchmark( RC$new(), R6$new(), R6NoClass$new(), R6NonPortable$new(), R6NonCloneable$new(), R6Bare$new(), R6Private$new(), R6PrivateBare$new(), FunctionEnvClass(), FunctionEnvNoClass() ) speed <- mb_summary(speed) speed #> name median #> 1 RC$new() 203.4195 #> 2 R6$new() 30.9830 #> 3 R6NoClass$new() 31.3240 #> 4 R6NonPortable$new() 31.5435 #> 5 R6NonCloneable$new() 31.2230 #> 6 R6Bare$new() 27.7870 #> 7 R6Private$new() 42.9850 #> 8 R6PrivateBare$new() 39.1130 #> 9 FunctionEnvClass() 1.4875 #> 10 FunctionEnvNoClass() 1.0020"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"field-access-speed","dir":"Articles","previous_headings":"Tests","what":"Field access speed","title":"R6 and Reference Class performance tests","text":"much time take access field object? First ’ll make objects: get value objects: Accessing field reference class much slower methods. ’s also obvious pattern accessing field environment (created R6 function call) slower class attribute. , objects class attribute, R attempts look S3 method $, lookup performance penalty. ’ll see .","code":"rc <- RC$new() r6 <- R6$new() r6noclass <- R6NoClass$new() r6noport <- R6NonPortable$new() r6noclone <- R6NonCloneable$new() r6bare <- R6Bare$new() r6priv <- R6Private$new() r6priv_bare <- R6PrivateBare$new() fun_env <- FunctionEnvClass() fun_env_nc <- FunctionEnvNoClass() speed <- microbenchmark( rc$x, r6$x, r6noclass$x, r6noport$x, r6noclone$x, r6bare$x, r6priv$x, r6priv_bare$x, fun_env$x, fun_env_nc$x ) speed <- mb_summary(speed) speed #> name median #> 1 rc$x 5.7555 #> 2 r6$x 0.6515 #> 3 r6noclass$x 0.2100 #> 4 r6noport$x 0.6915 #> 5 r6noclone$x 0.7110 #> 6 r6bare$x 0.2110 #> 7 r6priv$x 0.7120 #> 8 r6priv_bare$x 0.2310 #> 9 fun_env$x 0.6260 #> 10 fun_env_nc$x 0.2200"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"field-setting-speed","dir":"Articles","previous_headings":"Tests","what":"Field setting speed","title":"R6 and Reference Class performance tests","text":"much time take set value field object? Reference classes significantly slower others, . case, ’s additional overhead due type-checking value. , -class objects significantly faster others, probably due attempted S3 dispatch `$<-` function.","code":"speed <- microbenchmark( rc$x <- 4, r6$x <- 4, r6noclass$x <- 4, r6noport$x <- 4, r6noclone$x <- 4, r6bare$x <- 4, # r6priv$x <- 4, # Can't set private field directly, # r6priv_nc_np$x <- 4, # so we'll skip these two fun_env$x <- 4, fun_env_nc$x <- 4 ) speed <- mb_summary(speed) speed #> name median #> 1 rc$x <- 4 29.4650 #> 2 r6$x <- 4 1.1720 #> 3 r6noclass$x <- 4 0.6765 #> 4 r6noport$x <- 4 1.2130 #> 5 r6noclone$x <- 4 1.2570 #> 6 r6bare$x <- 4 0.7110 #> 7 fun_env$x <- 4 1.1625 #> 8 fun_env_nc$x <- 4 0.6865"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"speed-of-method-call-that-accesses-a-field","dir":"Articles","previous_headings":"Tests","what":"Speed of method call that accesses a field","title":"R6 and Reference Class performance tests","text":"much overhead calling method one objects? getx() methods simply return value x object. necessary, method uses self$x (R6 classes, portable=TRUE), others, just uses x (portable=FALSE, reference classes). reference class slowest. r6 also somewhat slower others. two reasons : first, uses self$x adds time, second, class attribute, slows access r6$getx self$x. One might expect r6priv speed r6, faster. Although accessing r6priv$getx slow r6priv class attribute, accessing private$x faster class attribute. objects can access x directly (without self private) lack class attribute fastest.","code":"speed <- microbenchmark( rc$getx(), r6$getx(), r6noclass$getx(), r6noport$getx(), r6noclone$getx(), r6bare$getx(), r6priv$getx(), r6priv_bare$getx(), fun_env$getx(), fun_env_nc$getx() ) speed <- mb_summary(speed) speed #> name median #> 1 rc$getx() 5.9010 #> 2 r6$getx() 1.5580 #> 3 r6noclass$getx() 0.5460 #> 4 r6noport$getx() 0.8620 #> 5 r6noclone$getx() 1.6580 #> 6 r6bare$getx() 0.3610 #> 7 r6priv$getx() 1.0620 #> 8 r6priv_bare$getx() 0.3655 #> 9 fun_env$getx() 0.9120 #> 10 fun_env_nc$getx() 0.4560"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"assignment-using-selfx---vs--x--","dir":"Articles","previous_headings":"Tests","what":"Assignment using self$x <- vs. x <<-","title":"R6 and Reference Class performance tests","text":"reference classes, can modify fields using <<- operator, using .self object. example, compare setx() methods two classes: Non-portable R6 classes similar, except use self instead .self. reference non-portable R6 classes, assignment using .self$x <- somewhat slower using x <<-. Bear mind , default, R6 classes portable, can’t use assignment x <<-.","code":"RCself <- setRefClass(\"RCself\", fields = list(x = \"numeric\"), methods = list( initialize = function() .self$x <- 1, setx = function(n = 2) .self$x <- n ) ) RCnoself <- setRefClass(\"RCnoself\", fields = list(x = \"numeric\"), methods = list( initialize = function() x <<- 1, setx = function(n = 2) x <<- n ) ) R6self <- R6Class(\"R6self\", portable = FALSE, public = list( x = 1, setx = function(n = 2) self$x <- n ) ) R6noself <- R6Class(\"R6noself\", portable = FALSE, public = list( x = 1, setx = function(n = 2) x <<- n ) ) rc_self <- RCself$new() rc_noself <- RCnoself$new() r6_self <- R6self$new() r6_noself <- R6noself$new() speed <- microbenchmark( rc_self$setx(), rc_noself$setx(), r6_self$setx(), r6_noself$setx() ) speed <- mb_summary(speed) speed #> name median #> 1 rc_self$setx() 35.8470 #> 2 rc_noself$setx() 20.0420 #> 3 r6_self$setx() 2.8800 #> 4 r6_noself$setx() 1.3075"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"overhead-from-using-on-objects-with-a-class-attribute","dir":"Articles","previous_headings":"Tests","what":"Overhead from using $ on objects with a class attribute","title":"R6 and Reference Class performance tests","text":"overhead using $ object class attribute. test , ’ll create three different kinds objects: environment class attribute. environment class \"e2\", without $.e2 S3 method. environment class \"e3\", $.e3 S3 method simply returns NULL. one environments contain object x. Now can run timing tests calling $ type object. Note e3 object, $ function nothing — simply returns NULL. Using $ e2 e3 much slower e1. e2 e3 class attribute. Even though ’s $ method defined e2, e2$x still 6 times slower e1$x, simply R looks appropriate S3 method. e3$x slightly faster e2$x; probably $.e3 function doesn’t actually anything return NULL. object class attribute, R attempt look method every time $ called. can slow things considerably, $ used often.","code":"e1 <- new.env(hash = FALSE, parent = emptyenv()) e2 <- new.env(hash = FALSE, parent = emptyenv()) e3 <- new.env(hash = FALSE, parent = emptyenv()) e1$x <- 1 e2$x <- 1 e3$x <- 1 class(e2) <- \"e2\" class(e3) <- \"e3\" # Define an S3 method for class e3 `$.e3` <- function(x, name) { NULL } speed <- microbenchmark( e1$x, e2$x, e3$x ) speed <- mb_summary(speed) speed #> name median #> 1 e1$x 0.191 #> 2 e2$x 0.541 #> 3 e3$x 0.842"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"lists-vs--environments-and-vs-","dir":"Articles","previous_headings":"Tests","what":"Lists vs. environments, and $ vs. [[","title":"R6 and Reference Class performance tests","text":"Lists also used creating classes (albeit reference semantics). much time take access items using $ lists vs. environments? ’ll also compare using obj$x obj[['x']]. Performance comparable across environments lists. [[ operator slightly faster $, probably doesn’t need convert unevaluated symbol string.","code":"lst <- list(x = 10) env <- new.env() env$x <- 10 mb_summary(microbenchmark( lst = lst$x, env = env$x, lst[['x']], env[['x']] )) #> name median #> 1 lst 0.181 #> 2 env 0.170 #> 3 lst[[\"x\"]] 0.131 #> 4 env[[\"x\"]] 0.110"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"wrap-up","dir":"Articles","previous_headings":"","what":"Wrap-up","title":"R6 and Reference Class performance tests","text":"R6 objects take less memory significantly faster R’s reference class objects, also options provide even speed. tests, biggest speedup R6 classes comes using class attribute; speeds use $. Non-portable R6 classes can also access fields without $ , provides another modest speed boost. cases, speed increases negligible – order microseconds noticeable tens even hundreds thousands class member accesses performed.","code":""},{"path":[]},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"functions-for-calculating-object-sizes","dir":"Articles","previous_headings":"Appendix","what":"Functions for calculating object sizes","title":"R6 and Reference Class performance tests","text":"","code":"# Utility functions for calculating sizes obj_size <- function(expr, .env = parent.frame()) { size_n <- function(n = 1) { objs <- lapply(1:n, function(x) eval(expr, .env)) as.numeric(do.call(lobstr::obj_size, objs)) } data.frame(one = size_n(1), incremental = size_n(2) - size_n(1)) } obj_sizes <- function(..., .env = parent.frame()) { exprs <- as.list(match.call(expand.dots = FALSE)$...) names(exprs) <- lapply(1:length(exprs), FUN = function(n) { name <- names(exprs)[n] if (is.null(name) || name == \"\") paste(deparse(exprs[[n]]), collapse = \" \") else name }) sizes <- mapply(obj_size, exprs, MoreArgs = list(.env = .env), SIMPLIFY = FALSE) do.call(rbind, sizes) }"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"system-information","dir":"Articles","previous_headings":"Appendix","what":"System information","title":"R6 and Reference Class performance tests","text":"","code":"sessionInfo() #> R version 4.4.1 (2024-06-14) #> Platform: x86_64-pc-linux-gnu #> Running under: Ubuntu 22.04.4 LTS #> #> Matrix products: default #> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 #> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0 #> #> locale: #> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8 #> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8 #> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C #> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C #> #> time zone: UTC #> tzcode source: system (glibc) #> #> attached base packages: #> [1] stats graphics grDevices utils datasets methods base #> #> other attached packages: #> [1] scales_1.3.0 ggplot2_3.5.1 R6_2.5.1.9000 #> [4] lobstr_1.1.2 microbenchmark_1.5.0 #> #> loaded via a namespace (and not attached): #> [1] gtable_0.3.5 jsonlite_1.8.8 highr_0.11 #> [4] compiler_4.4.1 jquerylib_0.1.4 systemfonts_1.1.0 #> [7] textshaping_0.4.0 yaml_2.3.10 fastmap_1.2.0 #> [10] labeling_0.4.3 knitr_1.48 tibble_3.2.1 #> [13] desc_1.4.3 munsell_0.5.1 bslib_0.8.0 #> [16] pillar_1.9.0 rlang_1.1.4 utf8_1.2.4 #> [19] cachem_1.1.0 xfun_0.47 fs_1.6.4 #> [22] sass_0.4.9 cli_3.6.3 pkgdown_2.1.0 #> [25] withr_3.0.1 magrittr_2.0.3 digest_0.6.37 #> [28] grid_4.4.1 lifecycle_1.0.4 vctrs_0.6.5 #> [31] evaluate_0.24.0 glue_1.7.0 farver_2.1.2 #> [34] codetools_0.2-20 ragg_1.3.2 fansi_1.0.6 #> [37] colorspace_2.1-1 rmarkdown_2.28 tools_4.4.1 #> [40] pkgconfig_2.0.3 htmltools_0.5.8.1"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"the-problem","dir":"Articles","previous_headings":"","what":"The problem","title":"Portable and non-portable R6 classes","text":"example cross-package inheritance problem reference classes: Suppose ClassA pkgA, ClassB pkgB, inherits ClassA. ClassA method foo calls non-exported function fun pkgA. ClassB inherits foo, try call fun – since ClassB objects created pkgB namespace (environment) instead pkgA namespace, won’t able find fun. Something similar happens R6 portable=FALSE option used. example: create instance ClassA, works expected: ClassB, can’t find foo function:","code":"library(R6) # Simulate packages by creating environments pkgA <- new.env() pkgB <- new.env() # Create a function in pkgA but not pkgB pkgA$fun <- function() 10 ClassA <- R6Class(\"ClassA\", portable = FALSE, public = list( foo = function() fun() ), parent_env = pkgA ) # ClassB inherits from ClassA ClassB <- R6Class(\"ClassB\", portable = FALSE, inherit = ClassA, parent_env = pkgB ) a <- ClassA$new() a$foo() #> [1] 10 b <- ClassB$new() b$foo() #> Error in b$foo() : could not find function \"fun\""},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"portable-r6","dir":"Articles","previous_headings":"","what":"Portable R6","title":"Portable and non-portable R6 classes","text":"R6 supports inheritance across different packages, default portable=TRUE option. example, ’ll simulate different packages creating separate parent environments classes. method inherited superclass, method also gets class’s environment. words, method “runs ” superclass’s environment. makes possible inheritance work across packages. method defined subclass, method gets subclass’s environment. example, ClassC subclass ClassA, defines foo method overrides foo method ClassA. happens method looks ClassA’s – just calls fun. time finds pkgC$fun instead pkgA$fun. contrast ClassB, inherited foo method environment ClassA.","code":"pkgA <- new.env() pkgB <- new.env() pkgA$fun <- function() { \"This function `fun` in pkgA\" } ClassA <- R6Class(\"ClassA\", portable = TRUE, # The default public = list( foo = function() fun() ), parent_env = pkgA ) ClassB <- R6Class(\"ClassB\", portable = TRUE, inherit = ClassA, parent_env = pkgB ) a <- ClassA$new() a$foo() #> [1] \"This function `fun` in pkgA\" b <- ClassB$new() b$foo() #> [1] \"This function `fun` in pkgA\" pkgC <- new.env() pkgC$fun <- function() { \"This function `fun` in pkgC\" } ClassC <- R6Class(\"ClassC\", portable = TRUE, inherit = ClassA, public = list( foo = function() fun() ), parent_env = pkgC ) cc <- ClassC$new() # This method is defined in ClassC, so finds pkgC$fun cc$foo() #> [1] \"This function `fun` in pkgC\""},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"using-self","dir":"Articles","previous_headings":"","what":"Using self","title":"Portable and non-portable R6 classes","text":"One important difference non-portable portable classes non-portable classes, ’s possible access members just name member, portable classes, member access always requires using self$ private$. consequence inheritance implementation. ’s example non-portable class two methods: sety, sets private field y using <<- operator, getxy, returns vector values fields x y: attempt portable class, results error: make work portable class, need use self$x private$y: small performance penalty using self$x opposed x. cases, negligible, can noticeable situations tens thousands accesses per second. information, see vignette(\"Performance\").","code":"NP <- R6Class(\"NP\", portable = FALSE, public = list( x = 1, getxy = function() c(x, y), sety = function(value) y <<- value ), private = list( y = NA ) ) np <- NP$new() np$sety(20) np$getxy() #> [1] 1 20 P <- R6Class(\"P\", portable = TRUE, public = list( x = 1, getxy = function() c(x, y), sety = function(value) y <<- value ), private = list( y = NA ) ) p <- P$new() # No error, but instead of setting private$y, this sets y in the global # environment! This is because of the semantics of <<-. p$sety(20) y #> [1] 20 p$getxy() #> Error in p$getxy() : object 'y' not found P2 <- R6Class(\"P2\", portable = TRUE, public = list( x = 1, getxy = function() c(self$x, private$y), sety = function(value) private$y <- value ), private = list( y = NA ) ) p2 <- P2$new() p2$sety(20) p2$getxy() #> [1] 1 20"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"potential-pitfalls-with-cross-package-inheritance","dir":"Articles","previous_headings":"","what":"Potential pitfalls with cross-package inheritance","title":"Portable and non-portable R6 classes","text":"Inheritance happens object instantiated MyClass$new(). time, members superclass get copied new object. means instantiate R6 object, essentially save pieces superclass object. way packages built R, R6’s inheritance behavior potentially lead surprising, hard--diagnose problems packages change versions. Suppose two packages, pkgA, containing ClassA, pkgB, containing ClassB, code pkgB instantiates ClassB object, objB, build time. contrast instantiating ClassB run-time, calling function. code package run binary package built, resulting objects saved package. (Generally, object can accessed pkgB:::objB, means created build time.) objB created package build time, pieces superclass, pkgA::ClassA, saved inside . fine . imagine pkgB built installed pkgA 1.0, upgrade pkgA 2.0 without subsequently building installing pkgB. pkgB::objB contain code pkgA::ClassA 1.0, version pkgA::ClassA ’s installed 2.0. can cause problems objB inherited code uses parts pkgA changed – problems may entirely obvious. scenario entirely possible installing packages CRAN. common package upgraded without upgrading downstream dependencies. far know, R mechanism force downstream dependencies rebuilt package upgraded user’s computer. problem happens, remedy rebuild pkgB pkgA 2.0. don’t know CRAN rebuilds downstream dependencies package updated. doesn’t, ’s possible CRAN incompatible binary builds pkgA pkgB, users install pkgB source, install.packages(\"pkgB\", type = \"source\"). avoid problem entirely, objects ClassB must instantiated build time. can either () instantiate functions, (B) instantiate package load time, adding .onLoad function package. example: might wondering ClassB (class, instance class objB) doesn’t save copy pkgA::ClassA inside package built. , inherit argument, R6Class saves unevaluated expression (pkgA::ClassA), evaluates $new() called.","code":"ClassB <- R6Class(\"ClassB\", inherit = pkgA::ClassA, public = list(x = 1) ) # We'll fill this at load time objB <- NULL .onLoad <- function(libname, pkgname) { # The namespace is locked after loading; we can still modify objB at this time. objB <<- ClassB$new() }"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"wrap-up","dir":"Articles","previous_headings":"","what":"Wrap-up","title":"Portable and non-portable R6 classes","text":"summary: Portable classes allow inheritance across different packages. Portable classes always require use self private access members. can incur small performance penalty, since using self$x slower just x.","code":""},{"path":"https://r6.r-lib.org/dev/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Winston Chang. Author, maintainer. . Copyright holder, funder.","code":""},{"path":"https://r6.r-lib.org/dev/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Chang W (2024). R6: Encapsulated Classes Reference Semantics. R package version 2.5.1.9000, https://github.com/r-lib/R6/, https://r6.r-lib.org.","code":"@Manual{, title = {R6: Encapsulated Classes with Reference Semantics}, author = {Winston Chang}, year = {2024}, note = {R package version 2.5.1.9000, https://github.com/r-lib/R6/}, url = {https://r6.r-lib.org}, }"},{"path":"https://r6.r-lib.org/dev/index.html","id":"r6-encapsulated-object-oriented-programming-for-r-","dir":"","previous_headings":"","what":"Encapsulated Classes with Reference Semantics","title":"Encapsulated Classes with Reference Semantics","text":"R6 implementation encapsulated object-oriented programming R, simpler, faster, lighter-weight alternative R’s built-reference classes. style programming also sometimes referred classical object-oriented programming. features R6: R6 objects reference semantics. R6 cleanly supports inheritance across packages. R6 classes public private members. contrast R’s reference classes, R6 built S4 class system, require methods package. Unlike reference classes, R6 classes can cleanly inherited across different packages. See Introduction article usage examples.","code":""},{"path":"https://r6.r-lib.org/dev/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Encapsulated Classes with Reference Semantics","text":"install R6 CRAN: install development version (requires devtools package):","code":"install.packages('R6') devtools::install_github('r-lib/R6', build_vignettes = FALSE)"},{"path":"https://r6.r-lib.org/dev/index.html","id":"documentation","dir":"","previous_headings":"","what":"Documentation","title":"Encapsulated Classes with Reference Semantics","text":"Introduction R6 Debugging methods R6 objects Performance tests - Speed memory comparisons R6 classes reference classes. Portable R6 classes - Inheritance across different packages.","code":""},{"path":"https://r6.r-lib.org/dev/index.html","id":"why-r6","dir":"","previous_headings":"Documentation","what":"Why R6?","title":"Encapsulated Classes with Reference Semantics","text":"name R6? R’s reference classes introduced, users, following names R’s existing class systems S3 S4, called new class system R5 jest. Although reference classes actually called R5, name package classes takes inspiration name. name R5 also code-name used different object system started Simon Urbanek, meant solve issues S4 relating syntax performance. However, R5 branch shelved little development, never released.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an R6 reference object generator — R6Class","title":"Create an R6 reference object generator — R6Class","text":"R6 objects essentially environments, structured way makes look like object typical object-oriented language R. support public private members, well inheritance across different packages.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an R6 reference object generator — R6Class","text":"","code":"R6Class( classname = NULL, public = list(), private = NULL, active = NULL, inherit = NULL, lock_objects = TRUE, class = TRUE, portable = TRUE, lock_class = FALSE, cloneable = TRUE, parent_env = parent.frame() )"},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an R6 reference object generator — R6Class","text":"classname Name class. class name useful primarily S3 method dispatch. public list public members, can functions (methods) non-functions (fields). private optional list private members, can functions non-functions. active optional list active binding functions. inherit R6ClassGenerator object inherit ; words, superclass. captured unevaluated expression evaluated parent_env time object instantiated. lock_objects environments generated objects locked? locked, new members added objects. class class attribute added object? Default TRUE. FALSE, objects simply look like environments, . portable TRUE (default), class work inheritance across different packages. Note enabled, fields members must accessed self$x private$x; accessed just x. lock_class TRUE, possible add members generator object $set. FALSE (default), possible add members $set. methods $is_locked, $lock, $unlock can used query change locked state class. cloneable TRUE (default), generated objects method named $clone, makes copy object. parent_env environment use parent newly-created objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Create an R6 reference object generator — R6Class","text":"R6 object consists public environment, may also contain private environment, well environments superclasses. one sense, object public environment ; reference object identical reference public environment. another sense, object also consists fields, methods, private environment . active argument list active binding functions. functions take one argument. look like regular variables, accessed, function called optional argument. example, obj$x2 active binding, accessed obj$x2, calls x2() function active list, arguments. However, value assigned , obj$x2 <- 50, function called right-side value argument, x2(50). See makeActiveBinding information. public private lists contain items reference semantics (example, environment), items shared across instances class. avoid , add entry item NULL initial value, initialize method, instantiate object assign .","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"the-print-method","dir":"Reference","previous_headings":"","what":"The print method","title":"Create an R6 reference object generator — R6Class","text":"R6 object generators R6 objects default print method show screen: simply list members parameters (e.g. lock_objects, portable, etc., see ) object. default print method R6 objects can redefined, supplying public print method. (print members functions ignored.) method automatically called whenever object printed, e.g. object's name typed command prompt, print(obj) called. can also called directly via obj$print(). extra arguments print(obj, ...) call passed obj$print(...) method.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"portable-and-non-portable-classes","dir":"Reference","previous_headings":"","what":"Portable and non-portable classes","title":"Create an R6 reference object generator — R6Class","text":"R6 classes portable (default), can inherited across packages without complication. However, portable mode, members must accessed self private, self$x private$y. used non-portable mode, R6 classes behave like reference classes: inheritance across packages work well, self private necessary accessing fields.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"cloning-objects","dir":"Reference","previous_headings":"","what":"Cloning objects","title":"Create an R6 reference object generator — R6Class","text":"R6 objects method named clone default. disable , use cloneable=FALSE. clone method present slightly increase memory footprint R6 objects, since method shared across R6 objects, memory use negligible. default, calling x$clone() R6 object result shallow clone. , fields reference semantics (environments, R6, reference class objects), copied; instead, clone object field simply refers object. make deep copy, can use x$clone(deep=TRUE). option, fields R6 objects also cloned; however, environments reference class objects . want different deep copying behavior, can supply private method called deep_clone. method called field object, two arguments: name, name field, value, value. Whatever method returns used value field new clone object. can write deep_clone method makes copies specific fields, whether environments, R6 objects, reference class objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"s-details","dir":"Reference","previous_headings":"","what":"S3 details","title":"Create an R6 reference object generator — R6Class","text":"Normally public environment two classes: one supplied classname argument, \"R6\". possible get public environment classes, using class=FALSE. result faster access speeds avoiding class-based dispatch $. benefit negligible cases. class subclass another, object classes classname, superclass's classname, \"R6\" primary difference behavior class=FALSE , without class attribute, possible use S3 methods objects. , example, pretty printing (print.R6Class) used.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an R6 reference object generator — R6Class","text":"","code":"# A queue --------------------------------------------------------- Queue <- R6Class(\"Queue\", public = list( initialize = function(...) { for (item in list(...)) { self$add(item) } }, add = function(x) { private$queue <- c(private$queue, list(x)) invisible(self) }, remove = function() { if (private$length() == 0) return(NULL) # Can use private$queue for explicit access head <- private$queue[[1]] private$queue <- private$queue[-1] head } ), private = list( queue = list(), length = function() base::length(private$queue) ) ) q <- Queue$new(5, 6, \"foo\") # Add and remove items q$add(\"something\") q$add(\"another thing\") q$add(17) q$remove() #> [1] 5 #> [1] 5 q$remove() #> [1] 6 #> [1] 6 # Private members can't be accessed directly q$queue #> NULL #> NULL # q$length() #> Error: attempt to apply non-function # add() returns self, so it can be chained q$add(10)$add(11)$add(12) # remove() returns the value removed, so it's not chainable q$remove() #> [1] \"foo\" #> [1] \"foo\" q$remove() #> [1] \"something\" #> [1] \"something\" q$remove() #> [1] \"another thing\" #> [1] \"another thing\" q$remove() #> [1] 17 #> [1] 17 # Active bindings ------------------------------------------------- Numbers <- R6Class(\"Numbers\", public = list( x = 100 ), active = list( x2 = function(value) { if (missing(value)) return(self$x * 2) else self$x <- value/2 }, rand = function() rnorm(1) ) ) n <- Numbers$new() n$x #> [1] 100 #> [1] 100 n$x2 #> [1] 200 #> [1] 200 n$x2 <- 1000 n$x #> [1] 500 #> [1] 500 # If the function takes no arguments, it's not possible to use it with <-: n$rand #> [1] -1.400044 #> [1] 0.2648 n$rand #> [1] 0.2553171 #> [1] 2.171 # n$rand <- 3 #> Error: unused argument (quote(3)) # Inheritance ----------------------------------------------------- # Note that this isn't very efficient - it's just for illustrating inheritance. HistoryQueue <- R6Class(\"HistoryQueue\", inherit = Queue, public = list( show = function() { cat(\"Next item is at index\", private$head_idx + 1, \"\\n\") for (i in seq_along(private$queue)) { cat(i, \": \", private$queue[[i]], \"\\n\", sep = \"\") } }, remove = function() { if (private$length() - private$head_idx == 0) return(NULL) private$head_idx <<- private$head_idx + 1 private$queue[[private$head_idx]] } ), private = list( head_idx = 0 ) ) hq <- HistoryQueue$new(5, 6, \"foo\") hq$show() #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 5 #> [1] 5 hq$show() #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 6 #> [1] 6 # Calling superclass methods with super$ -------------------------- CountingQueue <- R6Class(\"CountingQueue\", inherit = Queue, public = list( add = function(x) { private$total <<- private$total + 1 super$add(x) }, get_total = function() private$total ), private = list( total = 0 ) ) cq <- CountingQueue$new(\"x\", \"y\") cq$get_total() #> [1] 2 #> [1] 2 cq$add(\"z\") cq$remove() #> [1] \"x\" #> [1] \"x\" cq$remove() #> [1] \"y\" #> [1] \"y\" cq$get_total() #> [1] 3 #> [1] 3 # Non-portable classes -------------------------------------------- # By default, R6 classes are portable, which means they can be inherited # across different packages. Portable classes require using self$ and # private$ to access members. # When used in non-portable mode, members can be accessed without self$, # and assignments can be made with <<-. NP <- R6Class(\"NP\", portable = FALSE, public = list( x = NA, getx = function() x, setx = function(value) x <<- value ) ) np <- NP$new() np$setx(10) np$getx() #> [1] 10 #> [1] 10 # Setting new values ---------------------------------------------- # It is possible to add new members to the class after it has been created, # by using the $set() method on the generator. Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) Simple$set(\"public\", \"getx2\", function() self$x*2) # Use overwrite = TRUE to overwrite existing values Simple$set(\"public\", \"x\", 10, overwrite = TRUE) s <- Simple$new() s$x #> [1] 10 s$getx2() #> [1] 20 # Cloning objects ------------------------------------------------- a <- Queue$new(5, 6) a$remove() #> [1] 5 #> [1] 5 # Clone a. New object gets a's state. b <- a$clone() # Can add to each queue separately now. a$add(10) b$add(20) a$remove() #> [1] 6 #> [1] 6 a$remove() #> [1] 10 #> [1] 10 b$remove() #> [1] 6 #> [1] 6 b$remove() #> [1] 20 #> [1] 20 # Deep clones ----------------------------------------------------- Simple <- R6Class(\"Simple\", public = list( x = NULL, initialize = function(val) self$x <- val ) ) Cloner <- R6Class(\"Cloner\", public = list( s = NULL, y = 1, initialize = function() self$s <- Simple$new(1) ) ) a <- Cloner$new() b <- a$clone() c <- a$clone(deep = TRUE) # Modify a a$s$x <- 2 a$y <- 2 # b is a shallow clone. b$s is the same as a$s because they are R6 objects. b$s$x #> [1] 2 #> [1] 2 # But a$y and b$y are different, because y is just a value. b$y #> [1] 1 #> [1] 1 # c is a deep clone, so c$s is not the same as a$s. c$s$x #> [1] 1 #> [1] 1 c$y #> [1] 1 #> [1] 1 # Deep clones with custom deep_clone method ----------------------- CustomCloner <- R6Class(\"CustomCloner\", public = list( e = NULL, s1 = NULL, s2 = NULL, s3 = NULL, initialize = function() { self$e <- new.env(parent = emptyenv()) self$e$x <- 1 self$s1 <- Simple$new(1) self$s2 <- Simple$new(1) self$s3 <- Simple$new(1) } ), private = list( # When x$clone(deep=TRUE) is called, the deep_clone gets invoked once for # each field, with the name and value. deep_clone = function(name, value) { if (name == \"e\") { # e1 is an environment, so use this quick way of copying list2env(as.list.environment(value, all.names = TRUE), parent = emptyenv()) } else if (name %in% c(\"s1\", \"s2\")) { # s1 and s2 are R6 objects which we can clone value$clone() } else { # For everything else, just return it. This results in a shallow # copy of s3. value } } ) ) a <- CustomCloner$new() b <- a$clone(deep = TRUE) # Change some values in a's fields a$e$x <- 2 a$s1$x <- 3 a$s2$x <- 4 a$s3$x <- 5 # b has copies of e, s1, and s2, but shares the same s3 b$e$x #> [1] 1 #> [1] 1 b$s1$x #> [1] 1 #> [1] 1 b$s2$x #> [1] 1 #> [1] 1 b$s3$x #> [1] 5 #> [1] 5 # Debugging ------------------------------------------------------- if (FALSE) { # \\dontrun{ # This will enable debugging the getx() method for objects of the 'Simple' # class that are instantiated in the future. Simple$debug(\"getx\") s <- Simple$new() s$getx() # Disable debugging for future instances: Simple$undebug(\"getx\") s <- Simple$new() s$getx() # To enable and disable debugging for a method in a single instance of an # R6 object (this will not affect other objects): s <- Simple$new() debug(s$getx) s$getx() undebug(s$getx) } # }"},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a list from an R6 object — as.list.R6","title":"Create a list from an R6 object — as.list.R6","text":"returns list public members object. simply calls .list.environment.","code":""},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a list from an R6 object — as.list.R6","text":"","code":"# S3 method for class 'R6' as.list(x, ...)"},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a list from an R6 object — as.list.R6","text":"x R6 object. ... arguments, ignored.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":null,"dir":"Reference","previous_headings":"","what":"Is an object an R6 Class Generator or Object? — is.R6","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"Checks R6 class generators R6 objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"","code":"is.R6(x) is.R6Class(x)"},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"x object.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"logical value. .R6Class returns TRUE input R6 class generator FALSE otherwise. .R6 returns TRUE input R6 object FALSE otherwise.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"","code":"class_generator <- R6Class() object <- class_generator$new() is.R6Class(class_generator) #> [1] TRUE is.R6(class_generator) #> [1] FALSE is.R6Class(object) #> [1] FALSE is.R6(object) #> [1] TRUE"},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-2519000","dir":"Changelog","previous_headings":"","what":"R6 2.5.1.9000","title":"R6 2.5.1.9000","text":"R6 methods longer recommends initialize .__enclos_env__ autocomplete. deprecated lock parameter removed. R6Class() now prints message finalize method public instead private. superclass cloneable, subclasses cloneable (@IndrajeetPatil, #247). Fixed #253: Errors occur deep cloning member object environment class $ method. Deep cloning now uses get0() instead $. R6 now requires R >= 3.2. (@zeehio, #274)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-251","dir":"Changelog","previous_headings":"","what":"R6 2.5.1","title":"R6 2.5.1","text":"CRAN release: 2021-08-19 Removed unused packages Suggests section DESCRIPTION.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-250","dir":"Changelog","previous_headings":"","what":"R6 2.5.0","title":"R6 2.5.0","text":"CRAN release: 2020-10-28 Resolved #195: Slightly clearer message error initialize() method. Fixed #214: non-portable object inheritance cloned, methods inherited (overridden) wrong environment. (#215, #217) Printing R6 objects, longer includes .__active__.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-241","dir":"Changelog","previous_headings":"","what":"R6 2.4.1","title":"R6 2.4.1","text":"CRAN release: 2019-11-12 Cloning active bindings previously relied buggy behavior .list.environment(), return active binding’s function definition rather value invoking function. R 4.0, behavior chang returns value. R6 now longer relies buggy behavior. (#192)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-240","dir":"Changelog","previous_headings":"","what":"R6 2.4.0","title":"R6 2.4.0","text":"CRAN release: 2019-02-14 Fixed #146: Finalizers can now private methods. (#181) Fixed #167: Finalizers now run cloned objects. (#180)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-230","dir":"Changelog","previous_headings":"","what":"R6 2.3.0","title":"R6 2.3.0","text":"CRAN release: 2018-10-04 Vignettes longer included part source package large size. Documentation now https://r6.r-lib.org/. Fixed #125: print.R6 method now always returns object passed . Fixed #155: cases, cloned object’s methods refer wrong super object. (#156) Fixed #94, #133: cloning object contained function method, corresponding function new object environment changed, though method. Now longer changed environment. (#156) Fixed #121: finalize method present, prevent objects passed initialize getting GC’d. Fixed #158: $set method R6 generator object given value NULL, previously removed named item. Now adds named item value NULL. Fixed #159: Printing R6 object containing large vector slow.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-222","dir":"Changelog","previous_headings":"","what":"R6 2.2.2","title":"R6 2.2.2","text":"CRAN release: 2017-06-17 Fixed #108: object super object active binding super object cloned, new object’s super object get active binding – normal function. Fixed #119: class two levels inheritance, instance class’s super object contain methods incorrect enclosing environment.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-221","dir":"Changelog","previous_headings":"","what":"R6 2.2.1","title":"R6 2.2.1","text":"CRAN release: 2017-05-10 Vignettes now try use microbenchmark package present. package builds properly platforms microbenchmark present, like Solaris. Fixed ending position trim().","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-220","dir":"Changelog","previous_headings":"","what":"R6 2.2.0","title":"R6 2.2.0","text":"CRAN release: 2016-10-05 Classes can define finalizers explicitly, defining public finalize method. (#92, #93) Added function .R6() .R6Class(). (#95) Fixed #96: R6 now avoids using $ [[ class assigned object. allows user provide methods $ [[ without causing problems R6’s operation.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-213","dir":"Changelog","previous_headings":"","what":"R6 2.1.3","title":"R6 2.1.3","text":"CRAN release: 2016-08-19 plot S3 method R6 objects call $plot object present. (#77) Fixed printing members R6 objects. (#88) Fixed deep cloning non-portable classes. (#85) Added .list.R6 method. (#91)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-212","dir":"Changelog","previous_headings":"","what":"R6 2.1.2","title":"R6 2.1.2","text":"CRAN release: 2016-01-26 Implemented format.R6() format.R6ClassGenerator, former calls public format method defined. might change functionality existing classes define public format method intended purposes (#73. Thanks Kirill Müller) Functions shown interface print format, limited one line (#76. Thanks Kirill Müller) R6 objects generators print class inherit . (#67)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-211","dir":"Changelog","previous_headings":"","what":"R6 2.1.1","title":"R6 2.1.1","text":"CRAN release: 2015-08-19 Fixed bug printing R6 objects [[ method defined class. (#70) Fixed cloning objects call super method accesses private. (#72)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-210","dir":"Changelog","previous_headings":"","what":"R6 2.1.0","title":"R6 2.1.0","text":"CRAN release: 2015-07-04 Added support making clones R6 objects clone() method R6 objects. deep=TRUE option allows making clones copies fields reference semantics (like R6 objects). (#27) Allow adding public private members public private members begin . (#51) Previously, R6 object printed, accessed (called) active bindings. Now simply reports field active binding. (#37, #38. Thanks Oscar de Lama) Printing private members now works correctly portable R6 objects. (#26) ‘lock’ argument renamed ‘lock_objects’. Also, new argument, ‘lock_class’, can prevent changes class. (#52) Fixed printing NULL fields.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-201","dir":"Changelog","previous_headings":"","what":"R6 2.0.1","title":"R6 2.0.1","text":"CRAN release: 2014-10-29 superclass validated object instantiation, class creation. Added debug undebug methods generator object.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-20","dir":"Changelog","previous_headings":"","what":"R6 2.0","title":"R6 2.0","text":"CRAN release: 2014-08-19 [BREAKING CHANGE] Added portable option, allows inheritance across different package namespaces, made default. Added set() method class generator object, new fields methods can added generator created. functions involved instantiating objects encapsulated environment separate R6 namespace. means generator created one version R6, saved, restored new R session different version R6, shouldn’t problems compatibility. Methods locked can’t changed. (Fixes #19) Inheritance superclasses dynamic; instead reading superclass class created, happens time object instantiated. (Fixes #12) Added trailing newline printing R6 objects. (Thanks Gabor Csardi) print method R6 objects can redefined. (Thanks Gabor Csardi)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-101","dir":"Changelog","previous_headings":"","what":"R6 1.0.1","title":"R6 1.0.1","text":"CRAN release: 2014-07-17 First release CRAN. Removed pryr suggested packages.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-10","dir":"Changelog","previous_headings":"","what":"R6 1.0","title":"R6 1.0","text":"First release","code":""}] +[{"path":"https://r6.r-lib.org/dev/LICENSE.html","id":null,"dir":"","previous_headings":"","what":"MIT License","title":"MIT License","text":"Copyright (c) 2024 R6 authors Permission hereby granted, free charge, person obtaining copy software associated documentation files (“Software”), deal Software without restriction, including without limitation rights use, copy, modify, merge, publish, distribute, sublicense, /sell copies Software, permit persons Software furnished , subject following conditions: copyright notice permission notice shall included copies substantial portions Software. SOFTWARE PROVIDED “”, WITHOUT WARRANTY KIND, EXPRESS IMPLIED, INCLUDING LIMITED WARRANTIES MERCHANTABILITY, FITNESS PARTICULAR PURPOSE NONINFRINGEMENT. EVENT SHALL AUTHORS COPYRIGHT HOLDERS LIABLE CLAIM, DAMAGES LIABILITY, WHETHER ACTION CONTRACT, TORT OTHERWISE, ARISING , CONNECTION SOFTWARE USE DEALINGS SOFTWARE.","code":""},{"path":"https://r6.r-lib.org/dev/articles/Debugging.html","id":"enabling-debugging-for-all-future-instances-of-a-class","dir":"Articles","previous_headings":"","what":"Enabling debugging for all future instances of a class","title":"Debugging","text":"R6 generator objects method called debug() enable debugging method. affect instances class created debug() called. disable debugging future instances, use generator’s undebug() method:","code":"# An example class Simple <- R6Class(\"Simple\", public = list( x = 10, getx = function() self$x ) ) # This will enable debugging the getx() method for objects of the 'Simple' # class that are instantiated in the future. Simple$debug(\"getx\") s <- Simple$new() s$getx() # [Debugging prompt] # Disable debugging for future instances: Simple$undebug(\"getx\") s <- Simple$new() s$getx() #> [1] 10"},{"path":"https://r6.r-lib.org/dev/articles/Debugging.html","id":"debugging-methods-in-individual-objects","dir":"Articles","previous_headings":"","what":"Debugging methods in individual objects","title":"Debugging","text":"enable debugging method single instance object, use debug() function (debug() method generator object). Use undebug() disable debugging object’s method. can also use trace() function specify method want drop debugging console.","code":"s <- Simple$new() debug(s$getx) s$getx() # [Debugging prompt] undebug(s$getx) s$getx() #> [1] 10"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"r6-classes","dir":"Articles","previous_headings":"","what":"R6 classes","title":"Introduction","text":"R6 classes similar R’s reference classes, lighter weight, avoid issues come along using S4 (R’s reference classes based S4). information speed memory footprint, see vignette(\"Performance\"). Unlike many objects R, instances (objects) R6 classes reference semantics. R6 classes also support: public private methods active bindings inheritance (superclasses) works across packages name R6? R’s reference classes introduced, users, following names R’s existing class systems S3 S4, called new class system R5 jest. Although reference classes actually called R5, name package classes takes inspiration name. name R5 also code-name used different object system started Simon Urbanek, meant solve issues S4 relating syntax performance. However, R5 branch shelved little development, never released.","code":""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"basics","dir":"Articles","previous_headings":"R6 classes","what":"Basics","title":"Introduction","text":"’s create simple R6 class. public argument list items, can functions fields (non-functions). Functions used methods. instantiate object class, use $new(): $new() method creates object calls initialize() method, exists. Inside class methods, self refers object. Public members object (’ve seen far) accessed self$x, assignment done self$x <- y. object instantiated, can access public fields methods $: Implementation note: external face R6 object basically environment public members . also known public environment. R6 object’s methods separate enclosing environment , roughly speaking, environment “run ”. self binding found, simply reference back public environment.","code":"library(R6) Person <- R6Class(\"Person\", public = list( name = NULL, hair = NULL, initialize = function(name = NA, hair = NA) { self$name <- name self$hair <- hair self$greet() }, set_hair = function(val) { self$hair <- val }, greet = function() { cat(paste0(\"Hello, my name is \", self$name, \".\\n\")) } ) ) ann <- Person$new(\"Ann\", \"black\") #> Hello, my name is Ann. ann #> #> Public: #> clone: function (deep = FALSE) #> greet: function () #> hair: black #> initialize: function (name = NA, hair = NA) #> name: Ann #> set_hair: function (val) ann$hair #> [1] \"black\" ann$greet() #> Hello, my name is Ann. ann$set_hair(\"red\") ann$hair #> [1] \"red\""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"private-members","dir":"Articles","previous_headings":"R6 classes","what":"Private members","title":"Introduction","text":"previous example, members public. ’s also possible add private members: Whereas public members accessed self, like self$add(), private members accessed private, like private$queue. public members can accessed usual: However, private members can’t accessed directly: useful design pattern methods return self (invisibly) possible, makes chainable. example, add() method returns self can chain together: hand, remove() returns value removed, ’s chainable:","code":"Queue <- R6Class(\"Queue\", public = list( initialize = function(...) { for (item in list(...)) { self$add(item) } }, add = function(x) { private$queue <- c(private$queue, list(x)) invisible(self) }, remove = function() { if (private$length() == 0) return(NULL) # Can use private$queue for explicit access head <- private$queue[[1]] private$queue <- private$queue[-1] head } ), private = list( queue = list(), length = function() base::length(private$queue) ) ) q <- Queue$new(5, 6, \"foo\") # Add and remove items q$add(\"something\") q$add(\"another thing\") q$add(17) q$remove() #> [1] 5 q$remove() #> [1] 6 q$queue #> NULL q$length() #> Error: attempt to apply non-function q$add(10)$add(11)$add(12) q$remove() #> [1] \"foo\" q$remove() #> [1] \"something\" q$remove() #> [1] \"another thing\" q$remove() #> [1] 17"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"active-bindings","dir":"Articles","previous_headings":"R6 classes","what":"Active bindings","title":"Introduction","text":"Active bindings look like fields, time accessed, call function. always publicly visible. active binding accessed reading value, calls function value missing argument: ’s accessed assigning value, uses assignment value value argument: function takes arguments, ’s possible use <-: Implementation note: Active bindings bound public environment. enclosing environment functions also public environment.","code":"Numbers <- R6Class(\"Numbers\", public = list( x = 100 ), active = list( x2 = function(value) { if (missing(value)) return(self$x * 2) else self$x <- value/2 }, rand = function() rnorm(1) ) ) n <- Numbers$new() n$x #> [1] 100 n$x2 #> [1] 200 n$x2 <- 1000 n$x #> [1] 500 n$rand #> [1] 0.2648 n$rand #> [1] 2.171 n$rand <- 3 #> Error: unused argument (quote(3))"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"inheritance","dir":"Articles","previous_headings":"R6 classes","what":"Inheritance","title":"Introduction","text":"One R6 class can inherit another. words, can super- sub-classes. Subclasses can additional methods, can also methods override superclass methods. example queue retains history, ’ll add show() method override remove() method: Superclass methods can called super$xx(). CountingQueue (example ) keeps count total number objects ever added queue. overriding add() method – increments counter calls superclass’s add() method, super$add(x): Note , unlike classical OOP languages (e.g. C++), R6 subclasses also access private methods superclass. instance, following example, Duck class private method $quack(), subclass Mallard can access using super$quack().","code":"# Note that this isn't very efficient - it's just for illustrating inheritance. HistoryQueue <- R6Class(\"HistoryQueue\", inherit = Queue, public = list( show = function() { cat(\"Next item is at index\", private$head_idx + 1, \"\\n\") for (i in seq_along(private$queue)) { cat(i, \": \", private$queue[[i]], \"\\n\", sep = \"\") } }, remove = function() { if (private$length() - private$head_idx == 0) return(NULL) private$head_idx <- private$head_idx + 1 private$queue[[private$head_idx]] } ), private = list( head_idx = 0 ) ) hq <- HistoryQueue$new(5, 6, \"foo\") hq$show() #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 5 hq$show() #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 6 CountingQueue <- R6Class(\"CountingQueue\", inherit = Queue, public = list( add = function(x) { private$total <- private$total + 1 super$add(x) }, get_total = function() private$total ), private = list( total = 0 ) ) cq <- CountingQueue$new(\"x\", \"y\") cq$get_total() #> [1] 2 cq$add(\"z\") cq$remove() #> [1] \"x\" cq$remove() #> [1] \"y\" cq$get_total() #> [1] 3 Duck <- R6Class(\"Duck\", private = list(quack = function() print(\"Quack Quack\")) ) Mallard <- R6Class(\"Mallard\", inherit = Duck, public = list(quack = function() super$quack()) ) myMallard <- Mallard$new() myMallard$quack() #> [1] \"Quack Quack\""},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"fields-containing-reference-objects","dir":"Articles","previous_headings":"R6 classes","what":"Fields containing reference objects","title":"Introduction","text":"R6 class contains fields also reference semantics (e.g., R6 objects, environments), fields populated $initialize() method. field set reference object directly class definition, object shared across instances R6 class. ’s example: avoid , populate field initialize method:","code":"SimpleClass <- R6Class(\"SimpleClass\", public = list(x = NULL) ) SharedField <- R6Class(\"SharedField\", public = list( e = SimpleClass$new() ) ) s1 <- SharedField$new() s1$e$x <- 1 s2 <- SharedField$new() s2$e$x <- 2 # Changing s2$e$x has changed the value of s1$e$x s1$e$x #> [1] 2 NonSharedField <- R6Class(\"NonSharedField\", public = list( e = NULL, initialize = function() self$e <- SimpleClass$new() ) ) n1 <- NonSharedField$new() n1$e$x <- 1 n2 <- NonSharedField$new() n2$e$x <- 2 # n2$e$x does not affect n1$e$x n1$e$x #> [1] 1"},{"path":[]},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"adding-members-to-an-existing-class","dir":"Articles","previous_headings":"Other topics","what":"Adding members to an existing class","title":"Introduction","text":"sometimes useful add members class class already created. can done using $set() method generator object. new members present instances created $set() called. prevent modification class, can use lock_class=TRUE creating class. can also lock unlock class follows:","code":"Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) Simple$set(\"public\", \"getx2\", function() self$x*2) # To replace an existing member, use `overwrite=TRUE` Simple$set(\"public\", \"x\", 10, overwrite = TRUE) s <- Simple$new() s$x #> [1] 10 s$getx2() #> [1] 20 # Create a locked class Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ), lock_class = TRUE ) # This would result in an error Simple$set(\"public\", \"y\", 2) #> Error in Simple$set(\"public\", \"y\", 2): Can't modify a locked R6 class. # Unlock the class Simple$unlock() # Now it works Simple$set(\"public\", \"y\", 2) # Lock the class again Simple$lock()"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"cloning-objects","dir":"Articles","previous_headings":"Other topics","what":"Cloning objects","title":"Introduction","text":"default, R6 objects method named $clone() making copy object. don’t want clone method added, can use cloneable=FALSE creating class. loaded R6 object clone method, function uses 84.11 kB bytes, additional object, clone method costs trivial amount space (112 B bytes). Note cloneable inheritance: superclass cloneable=FALSE, subclasses cloneable. (subclass sets cloneable=TRUE, message printed objects instantiated objects cloneable.)","code":"Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) s <- Simple$new() # Create a clone s1 <- s$clone() # Modify it s1$x <- 2 s1$getx() #> [1] 2 # Original is unaffected by changes to the clone s$getx() #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"deep-cloning","dir":"Articles","previous_headings":"Other topics > Cloning objects","what":"Deep cloning","title":"Introduction","text":"fields objects reference semantics (environments, R6 objects, reference class objects), copy get reference object. sometimes desirable, often . example, ’ll create object c1 contains another R6 object, s, clone . original’s clone’s s fields refer object, modifying one results change reflected . make clone receives copy s, can use deep=TRUE option: default behavior $clone(deep=TRUE) copy fields R6 objects, copy fields environments, reference class objects, data structures contain reference-type objects (example, list R6 object). R6 object contains types objects want make deep clone , must provide function deep cloning, private method named deep_clone. example R6 object two fields, b, environments, contain value x. also field v regular (non-reference) value, private deep_clone method. deep_clone method called field. passed name value field, value returns used clone. c1$clone(deep=TRUE) called, deep_clone method called field c1, passed name field value. version, environment gets copied, b , v (doesn’t matter since v reference object). can test clone: example deep_clone method , checked name field determine , also check value, using inherits(value, \"R6\"), .environment(), .","code":"Simple <- R6Class(\"Simple\", public = list(x = 1)) Cloneable <- R6Class(\"Cloneable\", public = list( s = NULL, initialize = function() self$s <- Simple$new() ) ) c1 <- Cloneable$new() c2 <- c1$clone() # Change c1's `s` field c1$s$x <- 2 # c2's `s` is the same object, so it reflects the change c2$s$x #> [1] 2 c3 <- c1$clone(deep = TRUE) # Change c1's `s` field c1$s$x <- 3 # c2's `s` is different c3$s$x #> [1] 2 CloneEnv <- R6Class(\"CloneEnv\", public = list( a = NULL, b = NULL, v = 1, initialize = function() { self$a <- new.env(parent = emptyenv()) self$b <- new.env(parent = emptyenv()) self$a$x <- 1 self$b$x <- 1 } ), private = list( deep_clone = function(name, value) { # With x$clone(deep=TRUE) is called, the deep_clone gets invoked once for # each field, with the name and value. if (name == \"a\") { # `a` is an environment, so use this quick way of copying list2env(as.list.environment(value, all.names = TRUE), parent = emptyenv()) } else { # For all other fields, just return the value value } } ) ) c1 <- CloneEnv$new() c2 <- c1$clone(deep = TRUE) # Modifying c1$a doesn't affect c2$a, because they're separate objects c1$a$x <- 2 c2$a$x #> [1] 1 # Modifying c1$b does affect c2$b, because they're the same object c1$b$x <- 3 c2$b$x #> [1] 3 # Modifying c1$v doesn't affect c2$v, because they're not reference objects c1$v <- 4 c2$v #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"printing-r6-objects-to-the-screen","dir":"Articles","previous_headings":"Other topics","what":"Printing R6 objects to the screen","title":"Introduction","text":"R6 objects default $print() method lists members object. class defines $print() method, overrides default one.","code":"PrettyCountingQueue <- R6Class(\"PrettyCountingQueue\", inherit = CountingQueue, public = list( print = function(...) { cat(\" of \", self$get_total(), \" elements\\n\", sep = \"\") } ) ) pq <- PrettyCountingQueue$new(1, 2, \"foobar\") pq #> of 3 elements"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"finalizers","dir":"Articles","previous_headings":"Other topics","what":"Finalizers","title":"Introduction","text":"Sometimes ’s useful run function object garbage collected. example, may want make sure file database connection gets closed. , can define private $finalize() method, called arguments object garbage collected. NOTE: R6 version 2.3.0 (released 2018-10-04) , $finalize() method public. version 2.4.0, can public private. Private preferable ’s reason finalizer needs publicly accessible. use private finalizer R package, set R6 version dependency R6 (>= 2.4.0). 2.6.0, R6 prints message finalizer public. future version, emit warnings, finally, longer support public finalizers. Finalizers implemented using reg.finalizer() function, set onexit=TRUE, finalizer also called R exits. useful cases, like database connections.","code":"A <- R6Class(\"A\", private = list( finalize = function() { print(\"Finalizer has been called!\") } )) # Instantiate an object: obj <- A$new() # Remove the single existing reference to it, and force garbage collection # (normally garbage collection will happen automatically from time # to time) rm(obj); gc() #> [1] \"Finalizer has been called!\" #> used (Mb) gc trigger (Mb) max used (Mb) #> Ncells 701830 37.5 1364540 72.9 1364540 72.9 #> Vcells 1324395 10.2 8388608 64.0 3573020 27.3"},{"path":"https://r6.r-lib.org/dev/articles/Introduction.html","id":"class-methods-vs--member-functions","dir":"Articles","previous_headings":"Other topics","what":"Class methods vs. member functions","title":"Introduction","text":"R6 class definition contains functions public private sections, functions class methods: can access self (well private super available). R6 object cloned, resulting object’s methods self refers new object. works changing enclosing environment method cloned object. contrast class methods, can also add regular functions members R6 object. can done assigning function field $initialize() method, object instantiated. functions class methods, access self, private, super. trivial class method get_self() simply returns self, well empty member, fn. example, ’ll assign function fn body get_self. However, since ’s regular function, self refer something R6 object: R6 2.3.0, object cloned, member (non-method) functions enclosing environment changed, one normally expect. behave way:","code":"FunctionWrapper <- R6Class(\"FunctionWrapper\", public = list( get_self = function() { self }, fn = NULL ) ) a <- FunctionWrapper$new() # Create a function that accesses a variable named `self`. # Note that `self` in this function's scope refers to 100, not to the R6 object. self <- 100 a$fn <- function() { self } a$get_self() #> #> Public: #> clone: function (deep = FALSE) #> fn: function () #> get_self: function () a$fn() #> [1] 100 b <- a$clone() b$get_self() #> #> Public: #> clone: function (deep = FALSE) #> fn: function () #> get_self: function () b$fn() #> [1] 100"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"class-definitions","dir":"Articles","previous_headings":"","what":"Class definitions","title":"R6 and Reference Class performance tests","text":"’ll start defining number classes class-like entities, using reference classes, R6 classes, simple environments created directly functions. number options R6 can affect size resulting objects, use number variants. classes used speed memory tests follow. lot boring code, may want skip ahead results. classes basic characteristics: field named x contains number. way initializing value x. method named getx retrieving value x. method named inc incrementing value x. fields methods accessed $ operator, object named obj, use obj$x obj$getx().","code":""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r-reference-class","dir":"Articles","previous_headings":"Class definitions","what":"R reference class","title":"R6 and Reference Class performance tests","text":"reference classes, binding points back object named .self. Within method, assignment can done using .self, .self$x <- 10, using <<-, x <<- 10. create object, simply call $new() class:","code":"RC <- setRefClass(\"RC\", fields = list(x = \"numeric\"), methods = list( initialize = function(x = 1) .self$x <- x, getx = function() x, inc = function(n = 1) x <<- x + n ) ) RC$new() #> Reference class object of class \"RC\" #> Field \"x\": #> [1] 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class","dir":"Articles","previous_headings":"Class definitions","what":"R6 class","title":"R6 and Reference Class performance tests","text":"Creating R6 class similar reference class, except ’s need separate fields methods, can’t specify types fields. Whereas reference classes use .self, R6 classes use self (without leading period). reference classes, objects instantiated calling $new(): R6 object essentially just set environments structured particular way. fields methods R6 object bindings (, names) public environment. also separate environment enclosing environment methods (“run ” environment contains binding named self, simply reference public environment).","code":"R6 <- R6Class(\"R6\", public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- x + n ) ) R6$new() #> #> Public: #> clone: function (deep = FALSE) #> getx: function () #> inc: function (n = 1) #> initialize: function (x = 1) #> x: 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-without-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, without class attribute","title":"R6 and Reference Class performance tests","text":"default, class attribute added R6 objects. attribute adds slight performance penalty R attempt use S3 dispatch using $ object. ’s possible generate objects without class attribute, using class=FALSE: Note without class attribute, S3 method dispatch objects possible.","code":"R6NoClass <- R6Class(\"R6NoClass\", class = FALSE, public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- self$x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-non-portable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, non-portable","title":"R6 and Reference Class performance tests","text":"default, R6 objects portable. means inheritance can classes different packages. However, also requires use self$ private$ access members, incurs small performance penalty. portable=FALSE used, members can accessed without using self$, assignment can done <<-:","code":"R6NonPortable <- R6Class(\"R6NonPortable\", portable = FALSE, public = list( x = NULL, initialize = function(value = 1) x <<- value, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-cloneablefalse","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with cloneable=FALSE","title":"R6 and Reference Class performance tests","text":"default, R6 objects clone() method, fairly large function. need feature, can save memory using cloneable=FALSE.","code":"R6NonCloneable <- R6Class(\"R6NonCloneable\", cloneable = FALSE, public = list( x = NULL, initialize = function(x = 1) self$x <- x, getx = function() self$x, inc = function(n = 1) self$x <- self$x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-without-class-attribute-non-portable-and-non-cloneable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, without class attribute, non-portable, and non-cloneable","title":"R6 and Reference Class performance tests","text":"comparison, ’ll use R6 class without class attribute, non-portable, non-cloneable. stripped-can make R6 object.","code":"R6Bare <- R6Class(\"R6Bare\", portable = FALSE, class = FALSE, cloneable = FALSE, public = list( x = NULL, initialize = function(value = 1) x <<- value, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-public-and-private-members","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with public and private members","title":"R6 and Reference Class performance tests","text":"variant public private members. Instead single self object refers items object, objects self (refers public items) private.","code":"R6Private <- R6Class(\"R6Private\", private = list(x = NULL), public = list( initialize = function(x = 1) private$x <- x, getx = function() private$x, inc = function(n = 1) private$x <- private$x + n ) ) R6Private$new() #> #> Public: #> clone: function (deep = FALSE) #> getx: function () #> inc: function (n = 1) #> initialize: function (x = 1) #> Private: #> x: 1"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"r6-class-with-public-and-private-no-class-attribute-non-portable-and-non-cloneable","dir":"Articles","previous_headings":"Class definitions","what":"R6 class, with public and private, no class attribute, non-portable, and non-cloneable","title":"R6 and Reference Class performance tests","text":"comparison, ’ll add version without class attribute, non-portable, non-cloneable.","code":"R6PrivateBare <- R6Class(\"R6PrivateBare\", portable = FALSE, class = FALSE, cloneable = FALSE, private = list(x = NULL), public = list( initialize = function(x = 1) private$x <- x, getx = function() x, inc = function(n = 1) x <<- x + n ) )"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"environment-created-by-a-function-call-with-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"Environment created by a function call, with class attribute","title":"R6 and Reference Class performance tests","text":"R, environments passed reference. simple way create object ’s passed reference use environment created invocation function. function captures environment, attaches class , returns : Even though x isn’t declared function body, gets captured ’s argument function. Objects created way similar created R6 generator created .","code":"FunctionEnvClass <- function(x = 1) { inc <- function(n = 1) x <<- x + n getx <- function() x self <- environment() class(self) <- \"FunctionEnvClass\" self } ls(FunctionEnvClass()) #> [1] \"getx\" \"inc\" \"self\" \"x\""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"environment-created-by-a-function-call-without-class-attribute","dir":"Articles","previous_headings":"Class definitions","what":"Environment created by a function call, without class attribute","title":"R6 and Reference Class performance tests","text":"can make even simpler type reference object previous one, class attribute, self object: simply environment objects .","code":"FunctionEnvNoClass <- function(x = 1) { inc <- function(n = 1) x <<- x + n getx <- function() x environment() } ls(FunctionEnvNoClass()) #> [1] \"getx\" \"inc\" \"x\""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"tests","dir":"Articles","previous_headings":"","what":"Tests","title":"R6 and Reference Class performance tests","text":"timings using microbenchmark(), results reported microseconds, useful value probably median column.","code":""},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"memory-footprint","dir":"Articles","previous_headings":"Tests","what":"Memory footprint","title":"R6 and Reference Class performance tests","text":"much memory single instance object take, much memory additional object take? ’ll use functions obj_size obj_sizes (shown bottom document) calculate sizes. Sizes type object, bytes: results plotted . Note plots different x scales. preliminary observations first instance various classes: Using reference class consumes large amount memory. R6 objects, option largest impact cloneable: clone() method saves around 40 kB memory. subsequent instances classes, isn’t nearly much difference different kinds. appeared using reference class takes huge amount memory, much shared reference classes. Adding object different reference class doesn’t require much memory — around 38KB:","code":"sizes <- obj_sizes( RC$new(), R6$new(), R6NoClass$new(), R6NonPortable$new(), R6NonCloneable$new(), R6Bare$new(), R6Private$new(), R6PrivateBare$new(), FunctionEnvClass(), FunctionEnvNoClass() ) sizes #> one incremental #> RC$new() 2032832 1400 #> R6$new() 97200 1016 #> R6NoClass$new() 97920 896 #> R6NonPortable$new() 96872 960 #> R6NonCloneable$new() 14288 904 #> R6Bare$new() 13488 728 #> R6Private$new() 98112 1128 #> R6PrivateBare$new() 14512 840 #> FunctionEnvClass() 13424 616 #> FunctionEnvNoClass() 11944 504 RC2 <- setRefClass(\"RC2\", fields = list(x = \"numeric\"), methods = list( initialize = function(x = 2) .self$x <<- x, inc = function(n = 2) x <<- x * n ) ) # Calcualte the size of a new RC2 object, over and above an RC object as.numeric(obj_size(RC$new(), RC2$new()) - obj_size(RC$new())) #> [1] 0 0"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"object-instantiation-speed","dir":"Articles","previous_headings":"Tests","what":"Object instantiation speed","title":"R6 and Reference Class performance tests","text":"much time take create one objects? shows median time, microseconds: plot shows median instantiation time. Reference classes much slower instantiate types classes. Instantiating R6 objects roughly 5 times faster. Creating environment simple function call another 20-30 times faster.","code":"# Function to extract the medians from microbenchmark results mb_summary <- function(x) { res <- summary(x, unit=\"us\") data.frame(name = res$expr, median = res$median) } speed <- microbenchmark( RC$new(), R6$new(), R6NoClass$new(), R6NonPortable$new(), R6NonCloneable$new(), R6Bare$new(), R6Private$new(), R6PrivateBare$new(), FunctionEnvClass(), FunctionEnvNoClass() ) speed <- mb_summary(speed) speed #> name median #> 1 RC$new() 202.1975 #> 2 R6$new() 30.7070 #> 3 R6NoClass$new() 31.3490 #> 4 R6NonPortable$new() 31.4990 #> 5 R6NonCloneable$new() 31.1585 #> 6 R6Bare$new() 27.5015 #> 7 R6Private$new() 42.7800 #> 8 R6PrivateBare$new() 39.1180 #> 9 FunctionEnvClass() 1.4480 #> 10 FunctionEnvNoClass() 1.0175"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"field-access-speed","dir":"Articles","previous_headings":"Tests","what":"Field access speed","title":"R6 and Reference Class performance tests","text":"much time take access field object? First ’ll make objects: get value objects: Accessing field reference class much slower methods. ’s also obvious pattern accessing field environment (created R6 function call) slower class attribute. , objects class attribute, R attempts look S3 method $, lookup performance penalty. ’ll see .","code":"rc <- RC$new() r6 <- R6$new() r6noclass <- R6NoClass$new() r6noport <- R6NonPortable$new() r6noclone <- R6NonCloneable$new() r6bare <- R6Bare$new() r6priv <- R6Private$new() r6priv_bare <- R6PrivateBare$new() fun_env <- FunctionEnvClass() fun_env_nc <- FunctionEnvNoClass() speed <- microbenchmark( rc$x, r6$x, r6noclass$x, r6noport$x, r6noclone$x, r6bare$x, r6priv$x, r6priv_bare$x, fun_env$x, fun_env_nc$x ) speed <- mb_summary(speed) speed #> name median #> 1 rc$x 5.6210 #> 2 r6$x 0.6510 #> 3 r6noclass$x 0.2100 #> 4 r6noport$x 0.6810 #> 5 r6noclone$x 0.7210 #> 6 r6bare$x 0.2110 #> 7 r6priv$x 0.7215 #> 8 r6priv_bare$x 0.2210 #> 9 fun_env$x 0.6510 #> 10 fun_env_nc$x 0.2210"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"field-setting-speed","dir":"Articles","previous_headings":"Tests","what":"Field setting speed","title":"R6 and Reference Class performance tests","text":"much time take set value field object? Reference classes significantly slower others, . case, ’s additional overhead due type-checking value. , -class objects significantly faster others, probably due attempted S3 dispatch `$<-` function.","code":"speed <- microbenchmark( rc$x <- 4, r6$x <- 4, r6noclass$x <- 4, r6noport$x <- 4, r6noclone$x <- 4, r6bare$x <- 4, # r6priv$x <- 4, # Can't set private field directly, # r6priv_nc_np$x <- 4, # so we'll skip these two fun_env$x <- 4, fun_env_nc$x <- 4 ) speed <- mb_summary(speed) speed #> name median #> 1 rc$x <- 4 29.595 #> 2 r6$x <- 4 1.182 #> 3 r6noclass$x <- 4 0.701 #> 4 r6noport$x <- 4 1.263 #> 5 r6noclone$x <- 4 1.292 #> 6 r6bare$x <- 4 0.722 #> 7 fun_env$x <- 4 1.182 #> 8 fun_env_nc$x <- 4 0.692"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"speed-of-method-call-that-accesses-a-field","dir":"Articles","previous_headings":"Tests","what":"Speed of method call that accesses a field","title":"R6 and Reference Class performance tests","text":"much overhead calling method one objects? getx() methods simply return value x object. necessary, method uses self$x (R6 classes, portable=TRUE), others, just uses x (portable=FALSE, reference classes). reference class slowest. r6 also somewhat slower others. two reasons : first, uses self$x adds time, second, class attribute, slows access r6$getx self$x. One might expect r6priv speed r6, faster. Although accessing r6priv$getx slow r6priv class attribute, accessing private$x faster class attribute. objects can access x directly (without self private) lack class attribute fastest.","code":"speed <- microbenchmark( rc$getx(), r6$getx(), r6noclass$getx(), r6noport$getx(), r6noclone$getx(), r6bare$getx(), r6priv$getx(), r6priv_bare$getx(), fun_env$getx(), fun_env_nc$getx() ) speed <- mb_summary(speed) speed #> name median #> 1 rc$getx() 5.7805 #> 2 r6$getx() 1.5730 #> 3 r6noclass$getx() 0.5510 #> 4 r6noport$getx() 0.8620 #> 5 r6noclone$getx() 1.6335 #> 6 r6bare$getx() 0.3710 #> 7 r6priv$getx() 1.0770 #> 8 r6priv_bare$getx() 0.3810 #> 9 fun_env$getx() 0.9220 #> 10 fun_env_nc$getx() 0.4710"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"assignment-using-selfx---vs--x--","dir":"Articles","previous_headings":"Tests","what":"Assignment using self$x <- vs. x <<-","title":"R6 and Reference Class performance tests","text":"reference classes, can modify fields using <<- operator, using .self object. example, compare setx() methods two classes: Non-portable R6 classes similar, except use self instead .self. reference non-portable R6 classes, assignment using .self$x <- somewhat slower using x <<-. Bear mind , default, R6 classes portable, can’t use assignment x <<-.","code":"RCself <- setRefClass(\"RCself\", fields = list(x = \"numeric\"), methods = list( initialize = function() .self$x <- 1, setx = function(n = 2) .self$x <- n ) ) RCnoself <- setRefClass(\"RCnoself\", fields = list(x = \"numeric\"), methods = list( initialize = function() x <<- 1, setx = function(n = 2) x <<- n ) ) R6self <- R6Class(\"R6self\", portable = FALSE, public = list( x = 1, setx = function(n = 2) self$x <- n ) ) R6noself <- R6Class(\"R6noself\", portable = FALSE, public = list( x = 1, setx = function(n = 2) x <<- n ) ) rc_self <- RCself$new() rc_noself <- RCnoself$new() r6_self <- R6self$new() r6_noself <- R6noself$new() speed <- microbenchmark( rc_self$setx(), rc_noself$setx(), r6_self$setx(), r6_noself$setx() ) speed <- mb_summary(speed) speed #> name median #> 1 rc_self$setx() 35.4160 #> 2 rc_noself$setx() 19.9325 #> 3 r6_self$setx() 2.8605 #> 4 r6_noself$setx() 1.3520"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"overhead-from-using-on-objects-with-a-class-attribute","dir":"Articles","previous_headings":"Tests","what":"Overhead from using $ on objects with a class attribute","title":"R6 and Reference Class performance tests","text":"overhead using $ object class attribute. test , ’ll create three different kinds objects: environment class attribute. environment class \"e2\", without $.e2 S3 method. environment class \"e3\", $.e3 S3 method simply returns NULL. one environments contain object x. Now can run timing tests calling $ type object. Note e3 object, $ function nothing — simply returns NULL. Using $ e2 e3 much slower e1. e2 e3 class attribute. Even though ’s $ method defined e2, e2$x still 6 times slower e1$x, simply R looks appropriate S3 method. e3$x slightly faster e2$x; probably $.e3 function doesn’t actually anything return NULL. object class attribute, R attempt look method every time $ called. can slow things considerably, $ used often.","code":"e1 <- new.env(hash = FALSE, parent = emptyenv()) e2 <- new.env(hash = FALSE, parent = emptyenv()) e3 <- new.env(hash = FALSE, parent = emptyenv()) e1$x <- 1 e2$x <- 1 e3$x <- 1 class(e2) <- \"e2\" class(e3) <- \"e3\" # Define an S3 method for class e3 `$.e3` <- function(x, name) { NULL } speed <- microbenchmark( e1$x, e2$x, e3$x ) speed <- mb_summary(speed) speed #> name median #> 1 e1$x 0.1900 #> 2 e2$x 0.5415 #> 3 e3$x 0.8520"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"lists-vs--environments-and-vs-","dir":"Articles","previous_headings":"Tests","what":"Lists vs. environments, and $ vs. [[","title":"R6 and Reference Class performance tests","text":"Lists also used creating classes (albeit reference semantics). much time take access items using $ lists vs. environments? ’ll also compare using obj$x obj[['x']]. Performance comparable across environments lists. [[ operator slightly faster $, probably doesn’t need convert unevaluated symbol string.","code":"lst <- list(x = 10) env <- new.env() env$x <- 10 mb_summary(microbenchmark( lst = lst$x, env = env$x, lst[['x']], env[['x']] )) #> name median #> 1 lst 0.181 #> 2 env 0.171 #> 3 lst[[\"x\"]] 0.140 #> 4 env[[\"x\"]] 0.120"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"wrap-up","dir":"Articles","previous_headings":"","what":"Wrap-up","title":"R6 and Reference Class performance tests","text":"R6 objects take less memory significantly faster R’s reference class objects, also options provide even speed. tests, biggest speedup R6 classes comes using class attribute; speeds use $. Non-portable R6 classes can also access fields without $ , provides another modest speed boost. cases, speed increases negligible – order microseconds noticeable tens even hundreds thousands class member accesses performed.","code":""},{"path":[]},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"functions-for-calculating-object-sizes","dir":"Articles","previous_headings":"Appendix","what":"Functions for calculating object sizes","title":"R6 and Reference Class performance tests","text":"","code":"# Utility functions for calculating sizes obj_size <- function(expr, .env = parent.frame()) { size_n <- function(n = 1) { objs <- lapply(1:n, function(x) eval(expr, .env)) as.numeric(do.call(lobstr::obj_size, objs)) } data.frame(one = size_n(1), incremental = size_n(2) - size_n(1)) } obj_sizes <- function(..., .env = parent.frame()) { exprs <- as.list(match.call(expand.dots = FALSE)$...) names(exprs) <- lapply(1:length(exprs), FUN = function(n) { name <- names(exprs)[n] if (is.null(name) || name == \"\") paste(deparse(exprs[[n]]), collapse = \" \") else name }) sizes <- mapply(obj_size, exprs, MoreArgs = list(.env = .env), SIMPLIFY = FALSE) do.call(rbind, sizes) }"},{"path":"https://r6.r-lib.org/dev/articles/Performance.html","id":"system-information","dir":"Articles","previous_headings":"Appendix","what":"System information","title":"R6 and Reference Class performance tests","text":"","code":"sessionInfo() #> R version 4.4.1 (2024-06-14) #> Platform: x86_64-pc-linux-gnu #> Running under: Ubuntu 22.04.4 LTS #> #> Matrix products: default #> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 #> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0 #> #> locale: #> [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8 #> [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8 #> [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C #> [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C #> #> time zone: UTC #> tzcode source: system (glibc) #> #> attached base packages: #> [1] stats graphics grDevices utils datasets methods base #> #> other attached packages: #> [1] scales_1.3.0 ggplot2_3.5.1 R6_2.5.1.9000 #> [4] lobstr_1.1.2 microbenchmark_1.5.0 #> #> loaded via a namespace (and not attached): #> [1] gtable_0.3.5 jsonlite_1.8.8 highr_0.11 #> [4] compiler_4.4.1 jquerylib_0.1.4 systemfonts_1.1.0 #> [7] textshaping_0.4.0 yaml_2.3.10 fastmap_1.2.0 #> [10] labeling_0.4.3 knitr_1.48 tibble_3.2.1 #> [13] desc_1.4.3 munsell_0.5.1 bslib_0.8.0 #> [16] pillar_1.9.0 rlang_1.1.4 utf8_1.2.4 #> [19] cachem_1.1.0 xfun_0.47 fs_1.6.4 #> [22] sass_0.4.9 cli_3.6.3 pkgdown_2.1.0 #> [25] withr_3.0.1 magrittr_2.0.3 digest_0.6.37 #> [28] grid_4.4.1 lifecycle_1.0.4 vctrs_0.6.5 #> [31] evaluate_0.24.0 glue_1.7.0 farver_2.1.2 #> [34] codetools_0.2-20 ragg_1.3.2 fansi_1.0.6 #> [37] colorspace_2.1-1 rmarkdown_2.28 tools_4.4.1 #> [40] pkgconfig_2.0.3 htmltools_0.5.8.1"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"the-problem","dir":"Articles","previous_headings":"","what":"The problem","title":"Portable and non-portable R6 classes","text":"example cross-package inheritance problem reference classes: Suppose ClassA pkgA, ClassB pkgB, inherits ClassA. ClassA method foo calls non-exported function fun pkgA. ClassB inherits foo, try call fun – since ClassB objects created pkgB namespace (environment) instead pkgA namespace, won’t able find fun. Something similar happens R6 portable=FALSE option used. example: create instance ClassA, works expected: ClassB, can’t find foo function:","code":"library(R6) # Simulate packages by creating environments pkgA <- new.env() pkgB <- new.env() # Create a function in pkgA but not pkgB pkgA$fun <- function() 10 ClassA <- R6Class(\"ClassA\", portable = FALSE, public = list( foo = function() fun() ), parent_env = pkgA ) # ClassB inherits from ClassA ClassB <- R6Class(\"ClassB\", portable = FALSE, inherit = ClassA, parent_env = pkgB ) a <- ClassA$new() a$foo() #> [1] 10 b <- ClassB$new() b$foo() #> Error in b$foo() : could not find function \"fun\""},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"portable-r6","dir":"Articles","previous_headings":"","what":"Portable R6","title":"Portable and non-portable R6 classes","text":"R6 supports inheritance across different packages, default portable=TRUE option. example, ’ll simulate different packages creating separate parent environments classes. method inherited superclass, method also gets class’s environment. words, method “runs ” superclass’s environment. makes possible inheritance work across packages. method defined subclass, method gets subclass’s environment. example, ClassC subclass ClassA, defines foo method overrides foo method ClassA. happens method looks ClassA’s – just calls fun. time finds pkgC$fun instead pkgA$fun. contrast ClassB, inherited foo method environment ClassA.","code":"pkgA <- new.env() pkgB <- new.env() pkgA$fun <- function() { \"This function `fun` in pkgA\" } ClassA <- R6Class(\"ClassA\", portable = TRUE, # The default public = list( foo = function() fun() ), parent_env = pkgA ) ClassB <- R6Class(\"ClassB\", portable = TRUE, inherit = ClassA, parent_env = pkgB ) a <- ClassA$new() a$foo() #> [1] \"This function `fun` in pkgA\" b <- ClassB$new() b$foo() #> [1] \"This function `fun` in pkgA\" pkgC <- new.env() pkgC$fun <- function() { \"This function `fun` in pkgC\" } ClassC <- R6Class(\"ClassC\", portable = TRUE, inherit = ClassA, public = list( foo = function() fun() ), parent_env = pkgC ) cc <- ClassC$new() # This method is defined in ClassC, so finds pkgC$fun cc$foo() #> [1] \"This function `fun` in pkgC\""},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"using-self","dir":"Articles","previous_headings":"","what":"Using self","title":"Portable and non-portable R6 classes","text":"One important difference non-portable portable classes non-portable classes, ’s possible access members just name member, portable classes, member access always requires using self$ private$. consequence inheritance implementation. ’s example non-portable class two methods: sety, sets private field y using <<- operator, getxy, returns vector values fields x y: attempt portable class, results error: make work portable class, need use self$x private$y: small performance penalty using self$x opposed x. cases, negligible, can noticeable situations tens thousands accesses per second. information, see vignette(\"Performance\").","code":"NP <- R6Class(\"NP\", portable = FALSE, public = list( x = 1, getxy = function() c(x, y), sety = function(value) y <<- value ), private = list( y = NA ) ) np <- NP$new() np$sety(20) np$getxy() #> [1] 1 20 P <- R6Class(\"P\", portable = TRUE, public = list( x = 1, getxy = function() c(x, y), sety = function(value) y <<- value ), private = list( y = NA ) ) p <- P$new() # No error, but instead of setting private$y, this sets y in the global # environment! This is because of the semantics of <<-. p$sety(20) y #> [1] 20 p$getxy() #> Error in p$getxy() : object 'y' not found P2 <- R6Class(\"P2\", portable = TRUE, public = list( x = 1, getxy = function() c(self$x, private$y), sety = function(value) private$y <- value ), private = list( y = NA ) ) p2 <- P2$new() p2$sety(20) p2$getxy() #> [1] 1 20"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"potential-pitfalls-with-cross-package-inheritance","dir":"Articles","previous_headings":"","what":"Potential pitfalls with cross-package inheritance","title":"Portable and non-portable R6 classes","text":"Inheritance happens object instantiated MyClass$new(). time, members superclass get copied new object. means instantiate R6 object, essentially save pieces superclass object. way packages built R, R6’s inheritance behavior potentially lead surprising, hard--diagnose problems packages change versions. Suppose two packages, pkgA, containing ClassA, pkgB, containing ClassB, code pkgB instantiates ClassB object, objB, build time. contrast instantiating ClassB run-time, calling function. code package run binary package built, resulting objects saved package. (Generally, object can accessed pkgB:::objB, means created build time.) objB created package build time, pieces superclass, pkgA::ClassA, saved inside . fine . imagine pkgB built installed pkgA 1.0, upgrade pkgA 2.0 without subsequently building installing pkgB. pkgB::objB contain code pkgA::ClassA 1.0, version pkgA::ClassA ’s installed 2.0. can cause problems objB inherited code uses parts pkgA changed – problems may entirely obvious. scenario entirely possible installing packages CRAN. common package upgraded without upgrading downstream dependencies. far know, R mechanism force downstream dependencies rebuilt package upgraded user’s computer. problem happens, remedy rebuild pkgB pkgA 2.0. don’t know CRAN rebuilds downstream dependencies package updated. doesn’t, ’s possible CRAN incompatible binary builds pkgA pkgB, users install pkgB source, install.packages(\"pkgB\", type = \"source\"). avoid problem entirely, objects ClassB must instantiated build time. can either () instantiate functions, (B) instantiate package load time, adding .onLoad function package. example: might wondering ClassB (class, instance class objB) doesn’t save copy pkgA::ClassA inside package built. , inherit argument, R6Class saves unevaluated expression (pkgA::ClassA), evaluates $new() called.","code":"ClassB <- R6Class(\"ClassB\", inherit = pkgA::ClassA, public = list(x = 1) ) # We'll fill this at load time objB <- NULL .onLoad <- function(libname, pkgname) { # The namespace is locked after loading; we can still modify objB at this time. objB <<- ClassB$new() }"},{"path":"https://r6.r-lib.org/dev/articles/Portable.html","id":"wrap-up","dir":"Articles","previous_headings":"","what":"Wrap-up","title":"Portable and non-portable R6 classes","text":"summary: Portable classes allow inheritance across different packages. Portable classes always require use self private access members. can incur small performance penalty, since using self$x slower just x.","code":""},{"path":"https://r6.r-lib.org/dev/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Winston Chang. Author, maintainer. . Copyright holder, funder.","code":""},{"path":"https://r6.r-lib.org/dev/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Chang W (2024). R6: Encapsulated Classes Reference Semantics. R package version 2.5.1.9000, https://github.com/r-lib/R6/, https://r6.r-lib.org.","code":"@Manual{, title = {R6: Encapsulated Classes with Reference Semantics}, author = {Winston Chang}, year = {2024}, note = {R package version 2.5.1.9000, https://github.com/r-lib/R6/}, url = {https://r6.r-lib.org}, }"},{"path":"https://r6.r-lib.org/dev/index.html","id":"r6-encapsulated-object-oriented-programming-for-r-","dir":"","previous_headings":"","what":"Encapsulated Classes with Reference Semantics","title":"Encapsulated Classes with Reference Semantics","text":"R6 implementation encapsulated object-oriented programming R, simpler, faster, lighter-weight alternative R’s built-reference classes. style programming also sometimes referred classical object-oriented programming. features R6: R6 objects reference semantics. R6 cleanly supports inheritance across packages. R6 classes public private members. contrast R’s reference classes, R6 built S4 class system, require methods package. Unlike reference classes, R6 classes can cleanly inherited across different packages. See Introduction article usage examples.","code":""},{"path":"https://r6.r-lib.org/dev/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Encapsulated Classes with Reference Semantics","text":"install R6 CRAN: install development version (requires devtools package):","code":"install.packages('R6') devtools::install_github('r-lib/R6', build_vignettes = FALSE)"},{"path":"https://r6.r-lib.org/dev/index.html","id":"documentation","dir":"","previous_headings":"","what":"Documentation","title":"Encapsulated Classes with Reference Semantics","text":"Introduction R6 Debugging methods R6 objects Performance tests - Speed memory comparisons R6 classes reference classes. Portable R6 classes - Inheritance across different packages.","code":""},{"path":"https://r6.r-lib.org/dev/index.html","id":"why-r6","dir":"","previous_headings":"Documentation","what":"Why R6?","title":"Encapsulated Classes with Reference Semantics","text":"name R6? R’s reference classes introduced, users, following names R’s existing class systems S3 S4, called new class system R5 jest. Although reference classes actually called R5, name package classes takes inspiration name. name R5 also code-name used different object system started Simon Urbanek, meant solve issues S4 relating syntax performance. However, R5 branch shelved little development, never released.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":null,"dir":"Reference","previous_headings":"","what":"Create an R6 reference object generator — R6Class","title":"Create an R6 reference object generator — R6Class","text":"R6 objects essentially environments, structured way makes look like object typical object-oriented language R. support public private members, well inheritance across different packages.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create an R6 reference object generator — R6Class","text":"","code":"R6Class( classname = NULL, public = list(), private = NULL, active = NULL, inherit = NULL, lock_objects = TRUE, class = TRUE, portable = TRUE, lock_class = FALSE, cloneable = TRUE, parent_env = parent.frame() )"},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create an R6 reference object generator — R6Class","text":"classname Name class. class name useful primarily S3 method dispatch. public list public members, can functions (methods) non-functions (fields). private optional list private members, can functions non-functions. active optional list active binding functions. inherit R6ClassGenerator object inherit ; words, superclass. captured unevaluated expression evaluated parent_env time object instantiated. lock_objects environments generated objects locked? locked, new members added objects. class class attribute added object? Default TRUE. FALSE, objects simply look like environments, . portable TRUE (default), class work inheritance across different packages. Note enabled, fields members must accessed self$x private$x; accessed just x. lock_class TRUE, possible add members generator object $set. FALSE (default), possible add members $set. methods $is_locked, $lock, $unlock can used query change locked state class. cloneable TRUE (default), generated objects method named $clone, makes copy object. parent_env environment use parent newly-created objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Create an R6 reference object generator — R6Class","text":"R6 object consists public environment, may also contain private environment, well environments superclasses. one sense, object public environment ; reference object identical reference public environment. another sense, object also consists fields, methods, private environment . active argument list active binding functions. functions take one argument. look like regular variables, accessed, function called optional argument. example, obj$x2 active binding, accessed obj$x2, calls x2() function active list, arguments. However, value assigned , obj$x2 <- 50, function called right-side value argument, x2(50). See makeActiveBinding information. public private lists contain items reference semantics (example, environment), items shared across instances class. avoid , add entry item NULL initial value, initialize method, instantiate object assign .","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"the-print-method","dir":"Reference","previous_headings":"","what":"The print method","title":"Create an R6 reference object generator — R6Class","text":"R6 object generators R6 objects default print method show screen: simply list members parameters (e.g. lock_objects, portable, etc., see ) object. default print method R6 objects can redefined, supplying public print method. (print members functions ignored.) method automatically called whenever object printed, e.g. object's name typed command prompt, print(obj) called. can also called directly via obj$print(). extra arguments print(obj, ...) call passed obj$print(...) method.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"portable-and-non-portable-classes","dir":"Reference","previous_headings":"","what":"Portable and non-portable classes","title":"Create an R6 reference object generator — R6Class","text":"R6 classes portable (default), can inherited across packages without complication. However, portable mode, members must accessed self private, self$x private$y. used non-portable mode, R6 classes behave like reference classes: inheritance across packages work well, self private necessary accessing fields.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"cloning-objects","dir":"Reference","previous_headings":"","what":"Cloning objects","title":"Create an R6 reference object generator — R6Class","text":"R6 objects method named clone default. disable , use cloneable=FALSE. clone method present slightly increase memory footprint R6 objects, since method shared across R6 objects, memory use negligible. default, calling x$clone() R6 object result shallow clone. , fields reference semantics (environments, R6, reference class objects), copied; instead, clone object field simply refers object. make deep copy, can use x$clone(deep=TRUE). option, fields R6 objects also cloned; however, environments reference class objects . want different deep copying behavior, can supply private method called deep_clone. method called field object, two arguments: name, name field, value, value. Whatever method returns used value field new clone object. can write deep_clone method makes copies specific fields, whether environments, R6 objects, reference class objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"s-details","dir":"Reference","previous_headings":"","what":"S3 details","title":"Create an R6 reference object generator — R6Class","text":"Normally public environment two classes: one supplied classname argument, \"R6\". possible get public environment classes, using class=FALSE. result faster access speeds avoiding class-based dispatch $. benefit negligible cases. class subclass another, object classes classname, superclass's classname, \"R6\" primary difference behavior class=FALSE , without class attribute, possible use S3 methods objects. , example, pretty printing (print.R6Class) used.","code":""},{"path":"https://r6.r-lib.org/dev/reference/R6Class.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create an R6 reference object generator — R6Class","text":"","code":"# A queue --------------------------------------------------------- Queue <- R6Class(\"Queue\", public = list( initialize = function(...) { for (item in list(...)) { self$add(item) } }, add = function(x) { private$queue <- c(private$queue, list(x)) invisible(self) }, remove = function() { if (private$length() == 0) return(NULL) # Can use private$queue for explicit access head <- private$queue[[1]] private$queue <- private$queue[-1] head } ), private = list( queue = list(), length = function() base::length(private$queue) ) ) q <- Queue$new(5, 6, \"foo\") # Add and remove items q$add(\"something\") q$add(\"another thing\") q$add(17) q$remove() #> [1] 5 #> [1] 5 q$remove() #> [1] 6 #> [1] 6 # Private members can't be accessed directly q$queue #> NULL #> NULL # q$length() #> Error: attempt to apply non-function # add() returns self, so it can be chained q$add(10)$add(11)$add(12) # remove() returns the value removed, so it's not chainable q$remove() #> [1] \"foo\" #> [1] \"foo\" q$remove() #> [1] \"something\" #> [1] \"something\" q$remove() #> [1] \"another thing\" #> [1] \"another thing\" q$remove() #> [1] 17 #> [1] 17 # Active bindings ------------------------------------------------- Numbers <- R6Class(\"Numbers\", public = list( x = 100 ), active = list( x2 = function(value) { if (missing(value)) return(self$x * 2) else self$x <- value/2 }, rand = function() rnorm(1) ) ) n <- Numbers$new() n$x #> [1] 100 #> [1] 100 n$x2 #> [1] 200 #> [1] 200 n$x2 <- 1000 n$x #> [1] 500 #> [1] 500 # If the function takes no arguments, it's not possible to use it with <-: n$rand #> [1] -1.400044 #> [1] 0.2648 n$rand #> [1] 0.2553171 #> [1] 2.171 # n$rand <- 3 #> Error: unused argument (quote(3)) # Inheritance ----------------------------------------------------- # Note that this isn't very efficient - it's just for illustrating inheritance. HistoryQueue <- R6Class(\"HistoryQueue\", inherit = Queue, public = list( show = function() { cat(\"Next item is at index\", private$head_idx + 1, \"\\n\") for (i in seq_along(private$queue)) { cat(i, \": \", private$queue[[i]], \"\\n\", sep = \"\") } }, remove = function() { if (private$length() - private$head_idx == 0) return(NULL) private$head_idx <<- private$head_idx + 1 private$queue[[private$head_idx]] } ), private = list( head_idx = 0 ) ) hq <- HistoryQueue$new(5, 6, \"foo\") hq$show() #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo #> Next item is at index 1 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 5 #> [1] 5 hq$show() #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo #> Next item is at index 2 #> 1: 5 #> 2: 6 #> 3: foo hq$remove() #> [1] 6 #> [1] 6 # Calling superclass methods with super$ -------------------------- CountingQueue <- R6Class(\"CountingQueue\", inherit = Queue, public = list( add = function(x) { private$total <<- private$total + 1 super$add(x) }, get_total = function() private$total ), private = list( total = 0 ) ) cq <- CountingQueue$new(\"x\", \"y\") cq$get_total() #> [1] 2 #> [1] 2 cq$add(\"z\") cq$remove() #> [1] \"x\" #> [1] \"x\" cq$remove() #> [1] \"y\" #> [1] \"y\" cq$get_total() #> [1] 3 #> [1] 3 # Non-portable classes -------------------------------------------- # By default, R6 classes are portable, which means they can be inherited # across different packages. Portable classes require using self$ and # private$ to access members. # When used in non-portable mode, members can be accessed without self$, # and assignments can be made with <<-. NP <- R6Class(\"NP\", portable = FALSE, public = list( x = NA, getx = function() x, setx = function(value) x <<- value ) ) np <- NP$new() np$setx(10) np$getx() #> [1] 10 #> [1] 10 # Setting new values ---------------------------------------------- # It is possible to add new members to the class after it has been created, # by using the $set() method on the generator. Simple <- R6Class(\"Simple\", public = list( x = 1, getx = function() self$x ) ) Simple$set(\"public\", \"getx2\", function() self$x*2) # Use overwrite = TRUE to overwrite existing values Simple$set(\"public\", \"x\", 10, overwrite = TRUE) s <- Simple$new() s$x #> [1] 10 s$getx2() #> [1] 20 # Cloning objects ------------------------------------------------- a <- Queue$new(5, 6) a$remove() #> [1] 5 #> [1] 5 # Clone a. New object gets a's state. b <- a$clone() # Can add to each queue separately now. a$add(10) b$add(20) a$remove() #> [1] 6 #> [1] 6 a$remove() #> [1] 10 #> [1] 10 b$remove() #> [1] 6 #> [1] 6 b$remove() #> [1] 20 #> [1] 20 # Deep clones ----------------------------------------------------- Simple <- R6Class(\"Simple\", public = list( x = NULL, initialize = function(val) self$x <- val ) ) Cloner <- R6Class(\"Cloner\", public = list( s = NULL, y = 1, initialize = function() self$s <- Simple$new(1) ) ) a <- Cloner$new() b <- a$clone() c <- a$clone(deep = TRUE) # Modify a a$s$x <- 2 a$y <- 2 # b is a shallow clone. b$s is the same as a$s because they are R6 objects. b$s$x #> [1] 2 #> [1] 2 # But a$y and b$y are different, because y is just a value. b$y #> [1] 1 #> [1] 1 # c is a deep clone, so c$s is not the same as a$s. c$s$x #> [1] 1 #> [1] 1 c$y #> [1] 1 #> [1] 1 # Deep clones with custom deep_clone method ----------------------- CustomCloner <- R6Class(\"CustomCloner\", public = list( e = NULL, s1 = NULL, s2 = NULL, s3 = NULL, initialize = function() { self$e <- new.env(parent = emptyenv()) self$e$x <- 1 self$s1 <- Simple$new(1) self$s2 <- Simple$new(1) self$s3 <- Simple$new(1) } ), private = list( # When x$clone(deep=TRUE) is called, the deep_clone gets invoked once for # each field, with the name and value. deep_clone = function(name, value) { if (name == \"e\") { # e1 is an environment, so use this quick way of copying list2env(as.list.environment(value, all.names = TRUE), parent = emptyenv()) } else if (name %in% c(\"s1\", \"s2\")) { # s1 and s2 are R6 objects which we can clone value$clone() } else { # For everything else, just return it. This results in a shallow # copy of s3. value } } ) ) a <- CustomCloner$new() b <- a$clone(deep = TRUE) # Change some values in a's fields a$e$x <- 2 a$s1$x <- 3 a$s2$x <- 4 a$s3$x <- 5 # b has copies of e, s1, and s2, but shares the same s3 b$e$x #> [1] 1 #> [1] 1 b$s1$x #> [1] 1 #> [1] 1 b$s2$x #> [1] 1 #> [1] 1 b$s3$x #> [1] 5 #> [1] 5 # Debugging ------------------------------------------------------- if (FALSE) { # \\dontrun{ # This will enable debugging the getx() method for objects of the 'Simple' # class that are instantiated in the future. Simple$debug(\"getx\") s <- Simple$new() s$getx() # Disable debugging for future instances: Simple$undebug(\"getx\") s <- Simple$new() s$getx() # To enable and disable debugging for a method in a single instance of an # R6 object (this will not affect other objects): s <- Simple$new() debug(s$getx) s$getx() undebug(s$getx) } # }"},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a list from an R6 object — as.list.R6","title":"Create a list from an R6 object — as.list.R6","text":"returns list public members object. simply calls .list.environment.","code":""},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a list from an R6 object — as.list.R6","text":"","code":"# S3 method for class 'R6' as.list(x, ...)"},{"path":"https://r6.r-lib.org/dev/reference/as.list.R6.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a list from an R6 object — as.list.R6","text":"x R6 object. ... arguments, ignored.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":null,"dir":"Reference","previous_headings":"","what":"Is an object an R6 Class Generator or Object? — is.R6","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"Checks R6 class generators R6 objects.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"","code":"is.R6(x) is.R6Class(x)"},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"x object.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"logical value. .R6Class returns TRUE input R6 class generator FALSE otherwise. .R6 returns TRUE input R6 object FALSE otherwise.","code":""},{"path":"https://r6.r-lib.org/dev/reference/is.R6.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Is an object an R6 Class Generator or Object? — is.R6","text":"","code":"class_generator <- R6Class() object <- class_generator$new() is.R6Class(class_generator) #> [1] TRUE is.R6(class_generator) #> [1] FALSE is.R6Class(object) #> [1] FALSE is.R6(object) #> [1] TRUE"},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-2519000","dir":"Changelog","previous_headings":"","what":"R6 2.5.1.9000","title":"R6 2.5.1.9000","text":"R6 methods longer recommends initialize .__enclos_env__ autocomplete. deprecated lock parameter removed. R6Class() now prints message finalize method public instead private. superclass cloneable, subclasses cloneable (@IndrajeetPatil, #247). Fixed #253: Errors occur deep cloning member object environment class $ method. Deep cloning now uses get0() instead $. R6 now requires R >= 3.2. (@zeehio, #274)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-251","dir":"Changelog","previous_headings":"","what":"R6 2.5.1","title":"R6 2.5.1","text":"CRAN release: 2021-08-19 Removed unused packages Suggests section DESCRIPTION.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-250","dir":"Changelog","previous_headings":"","what":"R6 2.5.0","title":"R6 2.5.0","text":"CRAN release: 2020-10-28 Resolved #195: Slightly clearer message error initialize() method. Fixed #214: non-portable object inheritance cloned, methods inherited (overridden) wrong environment. (#215, #217) Printing R6 objects, longer includes .__active__.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-241","dir":"Changelog","previous_headings":"","what":"R6 2.4.1","title":"R6 2.4.1","text":"CRAN release: 2019-11-12 Cloning active bindings previously relied buggy behavior .list.environment(), return active binding’s function definition rather value invoking function. R 4.0, behavior chang returns value. R6 now longer relies buggy behavior. (#192)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-240","dir":"Changelog","previous_headings":"","what":"R6 2.4.0","title":"R6 2.4.0","text":"CRAN release: 2019-02-14 Fixed #146: Finalizers can now private methods. (#181) Fixed #167: Finalizers now run cloned objects. (#180)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-230","dir":"Changelog","previous_headings":"","what":"R6 2.3.0","title":"R6 2.3.0","text":"CRAN release: 2018-10-04 Vignettes longer included part source package large size. Documentation now https://r6.r-lib.org/. Fixed #125: print.R6 method now always returns object passed . Fixed #155: cases, cloned object’s methods refer wrong super object. (#156) Fixed #94, #133: cloning object contained function method, corresponding function new object environment changed, though method. Now longer changed environment. (#156) Fixed #121: finalize method present, prevent objects passed initialize getting GC’d. Fixed #158: $set method R6 generator object given value NULL, previously removed named item. Now adds named item value NULL. Fixed #159: Printing R6 object containing large vector slow.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-222","dir":"Changelog","previous_headings":"","what":"R6 2.2.2","title":"R6 2.2.2","text":"CRAN release: 2017-06-17 Fixed #108: object super object active binding super object cloned, new object’s super object get active binding – normal function. Fixed #119: class two levels inheritance, instance class’s super object contain methods incorrect enclosing environment.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-221","dir":"Changelog","previous_headings":"","what":"R6 2.2.1","title":"R6 2.2.1","text":"CRAN release: 2017-05-10 Vignettes now try use microbenchmark package present. package builds properly platforms microbenchmark present, like Solaris. Fixed ending position trim().","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-220","dir":"Changelog","previous_headings":"","what":"R6 2.2.0","title":"R6 2.2.0","text":"CRAN release: 2016-10-05 Classes can define finalizers explicitly, defining public finalize method. (#92, #93) Added function .R6() .R6Class(). (#95) Fixed #96: R6 now avoids using $ [[ class assigned object. allows user provide methods $ [[ without causing problems R6’s operation.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-213","dir":"Changelog","previous_headings":"","what":"R6 2.1.3","title":"R6 2.1.3","text":"CRAN release: 2016-08-19 plot S3 method R6 objects call $plot object present. (#77) Fixed printing members R6 objects. (#88) Fixed deep cloning non-portable classes. (#85) Added .list.R6 method. (#91)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-212","dir":"Changelog","previous_headings":"","what":"R6 2.1.2","title":"R6 2.1.2","text":"CRAN release: 2016-01-26 Implemented format.R6() format.R6ClassGenerator, former calls public format method defined. might change functionality existing classes define public format method intended purposes (#73. Thanks Kirill Müller) Functions shown interface print format, limited one line (#76. Thanks Kirill Müller) R6 objects generators print class inherit . (#67)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-211","dir":"Changelog","previous_headings":"","what":"R6 2.1.1","title":"R6 2.1.1","text":"CRAN release: 2015-08-19 Fixed bug printing R6 objects [[ method defined class. (#70) Fixed cloning objects call super method accesses private. (#72)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-210","dir":"Changelog","previous_headings":"","what":"R6 2.1.0","title":"R6 2.1.0","text":"CRAN release: 2015-07-04 Added support making clones R6 objects clone() method R6 objects. deep=TRUE option allows making clones copies fields reference semantics (like R6 objects). (#27) Allow adding public private members public private members begin . (#51) Previously, R6 object printed, accessed (called) active bindings. Now simply reports field active binding. (#37, #38. Thanks Oscar de Lama) Printing private members now works correctly portable R6 objects. (#26) ‘lock’ argument renamed ‘lock_objects’. Also, new argument, ‘lock_class’, can prevent changes class. (#52) Fixed printing NULL fields.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-201","dir":"Changelog","previous_headings":"","what":"R6 2.0.1","title":"R6 2.0.1","text":"CRAN release: 2014-10-29 superclass validated object instantiation, class creation. Added debug undebug methods generator object.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-20","dir":"Changelog","previous_headings":"","what":"R6 2.0","title":"R6 2.0","text":"CRAN release: 2014-08-19 [BREAKING CHANGE] Added portable option, allows inheritance across different package namespaces, made default. Added set() method class generator object, new fields methods can added generator created. functions involved instantiating objects encapsulated environment separate R6 namespace. means generator created one version R6, saved, restored new R session different version R6, shouldn’t problems compatibility. Methods locked can’t changed. (Fixes #19) Inheritance superclasses dynamic; instead reading superclass class created, happens time object instantiated. (Fixes #12) Added trailing newline printing R6 objects. (Thanks Gabor Csardi) print method R6 objects can redefined. (Thanks Gabor Csardi)","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-101","dir":"Changelog","previous_headings":"","what":"R6 1.0.1","title":"R6 1.0.1","text":"CRAN release: 2014-07-17 First release CRAN. Removed pryr suggested packages.","code":""},{"path":"https://r6.r-lib.org/dev/news/index.html","id":"r6-10","dir":"Changelog","previous_headings":"","what":"R6 1.0","title":"R6 1.0","text":"First release","code":""}] diff --git a/dev/sitemap.xml b/dev/sitemap.xml index 71675ab..044c61c 100644 --- a/dev/sitemap.xml +++ b/dev/sitemap.xml @@ -1,5 +1,6 @@ https://r6.r-lib.org/dev/LICENSE-text.html +https://r6.r-lib.org/dev/LICENSE.html https://r6.r-lib.org/dev/articles/Debugging.html https://r6.r-lib.org/dev/articles/Introduction.html https://r6.r-lib.org/dev/articles/Performance.html