From 4e6438765550b918ba5614c49c0c979fc13ef360 Mon Sep 17 00:00:00 2001 From: "Jeffrey R. Stevens" Date: Mon, 9 Sep 2024 15:06:37 -0500 Subject: [PATCH 01/15] Add OOP comparison table --- 16_Trade-offs.Rmd | 764 ++++++++++++++++++++++++---------------------- 1 file changed, 392 insertions(+), 372 deletions(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 83173cb..ac05230 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -1,372 +1,392 @@ -# Trade-offs - -**Learning objectives:** - -- Understand the Trade-offs between S3, R6 and S4 - -- Brief intro to S7 (the object system formerly known as R7) - - -## Introduction - -* We have three OOP systems introduced so far (S3, S4, R6) - -* At the current time (pre - S7?) Hadley recommends use S3 by default: It's simple and widely used throughout base R and CRAN. - -* If you have experience in other languages, *Resist* the temptation to use R6 even though it will feel more familiar! - - -## S4 versus S3 - -**Which functional object system to use, S4 or S3? ** - -- **S3** is a simple and flexible system. - - - Good for small teams who need flexibility and immediate payoffs. - - - Commonly used throughout base R and CRAN - - - Flexibility can cause problems, more complex systems might require formal conventions - - -- **S4** is a more formal, strict system. - - - Good for large projects and large teams - - - Used by Bioconductor project - - - Requires significant up front investment in design, but payoff is a robust system that enforces conventions. - - - S4 Documentation is challenging to use. - - - -## R6 versus S3 - -**R6** is built on **encapsulated objects**, rather than generic functions. - - -**Big differences: general trade-offs** - -```{r 16-Trade-offs-4, echo=FALSE,fig.align='center'} -knitr::include_graphics("images/16-trade-offs.png") -``` - -## Namespacing {-} - -**Where methods are found?** - -- in S3, **Generic functions** are **global** and live in the **global namespace** - - - Advantage: Uniform API: `summary`, `print`, `predict` etc. - - - Disadvantage: Must be careful about creating new methods! Homonyms must be avoided, don't define `plot(bank_heist)` - - -- in R6, **Encapsulated methods** are **local**: objects with a **scope** - - - Advantage: No problems with homonyms: meaning of `bank_heist$plot()` is clear and unambiguous. - - - Disadvantage: Lack of a uniform API, except by convention. - - -## Threading state {-} - - -In S3 the challenge is to return a value and modify the object. - - -```{r} -new_stack <- function(items = list()) { - structure(list(items = items), class = "stack") -} - -push <- function(x, y) { - x$items <- c(x$items, list(y)) - x -} -``` - -No problem with that, but what about when we want to pop a value? We need to return two things. - -```{r} -pop <- function(x) { - n <- length(x$items) - - item <- x$items[[n]] - x$items <- x$items[-n] - - list(item = item, x = x) -} -``` - -The usage is a bit awkward: - -```{r} -s <- new_stack() -s <- push(s, 10) -s <- push(s, 20) - -out <- pop(s) -# Update state: -s <- out$x - -print(out$item) -``` - - -In python and other languages we have structured binding to make this less awkward. R has the {zeallot} package. For more, see this vignette: - -```{r 16-Trade-offs-5, eval=FALSE} -vignette('unpacking-assignment') -``` - -However, this is all easier in R6 due to the reference semantics! - -```{r} -Stack <- R6::R6Class("Stack", list( - items = list(), - push = function(x) { - self$items <- c(self$items, x) - invisible(self) - }, - pop = function() { - item <- self$items[[self$length()]] - self$items <- self$items[-self$length()] - item - }, - length = function() { - length(self$items) - } -)) - -s <- Stack$new() -s$push(10) -s$push(20) -s$pop() -``` - - -## Method chaining {-} - -Useful to compose functions from left-to-right. - -Use of the operators: - -- S3: `%>%` - -- R6: `$` - -```{r} -s$push(44)$push(32)$pop() -``` - - -## Umm... what about S7 ? {-} - -```{r standards, echo = FALSE, fig.cap = "https://xkcd.com/927/"} - -knitr::include_graphics("https://imgs.xkcd.com/comics/standards_2x.png") - -``` - -### Primary references: {-} - -* Docs: https://rconsortium.github.io/OOP-WG/ - -* Talk by Hadley Wickham https://www.youtube.com/watch?v=P3FxCvSueag - -## S7 briefly {-} - -* S7 is a 'better' version of S3 with some of the 'strictness' of S4. - -``` -"A little bit more complex then S3, with almost all of the features, -all of the payoff of S4" - rstudio conf 2022, Hadley Wickham -``` - -* Compatible with S3: S7 objects are S3 objects! Can even extend an S3 object with S7 - -* Somewhat compatible with S4, see [compatability vignette](https://rconsortium.github.io/OOP-WG/articles/compatibility.html) for details. - -* Helpful error messages! - -* Note that it was previously called R7, but it was changed to "S7" to better reflect that it is functional not encapsulated! - -## Abbreviated introduction based on the vignette {-} - -To install: -```{r, eval=FALSE} -# install.packages("remotes") -remotes::install_github("rconsortium/OOP-WG") -``` - - -```{r, eval=FALSE} -library(S7) -dog <- new_class("dog", properties = list( - name = class_character, - age = class_numeric -)) -dog - - -#> -#> @ name : dog -#> @ parent: -#> @ properties: -#> $ name: -#> $ age : or -``` - -Note the 'class_character', these are S7 classes corresponding to the base classes. - -Now to use it: - -```{r, eval = FALSE} -lola <- dog(name = "Lola", age = 11) -lola - -#> -#> @ name: chr "Lola" -#> @ age : num 11 -``` - -Properties can be set / read with '@', with automatic validation ('safety rails') based on the type! - -```{r, eval = FALSE} - -lola@age <- 12 -lola@age - -#> 12 - -lola@age <- "twelve" - -#> Error: @age must be or , not - -``` - -Note thehelpful error message! - -Like S3 (and S4) S7 has generics, implemented with `new_generic` and `method` for particular methods: - -```{r, eval = FALSE} -speak <- new_generic("speak", "x") - -method(speak, dog) <- function(x) { - "Woof" -} - -speak(lola) - -#> [1] "Woof" -``` - -If we have another class, we can implement the generic for that too: - -```{r, eval = FALSE} -cat <- new_class("cat", properties = list( - name = class_character, - age = class_double -)) -method(speak, cat) <- function(x) { - "Meow" -} - -fluffy <- cat(name = "Fluffy", age = 5) -speak(fluffy) - -#> [1] "Meow" -``` - -Helpful messages: - -```{r, eval = FALSE} -speak - -#> speak(x, ...) with 2 methods: -#> 1: method(speak, cat) -#> 2: method(speak, dog) -``` - - -"most usage of S7 with S3 will just work" - -```{r, eval = FALSE} -method(print, cat) <- function(...) { - print("I am a cat.") -} - -print(fluffy) -#> "I am a cat" - -``` - -*For validators, inheritance, dynamic properties and more, see the [vignette!](https://rconsortium.github.io/OOP-WG/articles/S7.html)* - -https://rconsortium.github.io/OOP-WG/articles/S7.html - -## So... switch to S7 ? {-} - -$$ -\huge -\textbf{Soon}^{tm} -$$ - -* Not yet... still in development! - -* But consider trying it out: - - * To stay ahead of the curve... S7 will be integrated into base R someday! - - * To contribute feedback to the S7 team! - - * To get "almost all" of the benefits of S4 without the complexity ! - -* In particular, if you have a new project that might require the complexity of S4, consider S7 instead! - -## Meeting Videos - -### Cohort 1 - -`r knitr::include_url("https://www.youtube.com/embed/W1uc8HbyZvI")` - -### Cohort 2 - -`r knitr::include_url("https://www.youtube.com/embed/bzo37PHCM1I")` - -### Cohort 3 - -`r knitr::include_url("https://www.youtube.com/embed/_byYFTQHp1Y")` - -### Cohort 4 - -`r knitr::include_url("https://www.youtube.com/embed/vdKDPBcOc6Y")` - -### Cohort 5 - -`r knitr::include_url("https://www.youtube.com/embed/3EvqtVYTFVM")` - -### Cohort 6 - -`r knitr::include_url("https://www.youtube.com/embed/vEButxFIvLw")` - -
- Meeting chat log - -``` -00:11:36 Oluwafemi Oyedele: I have not built anything with them!!! -00:16:31 Arthur Shaw: https://cran.r-project.org/web/packages/sp/index.html -00:19:05 Arthur Shaw: Apparently Hadley asked the same question we're asking several years ago: https://stackoverflow.com/questions/5437238/which-packages-make-good-use-of-s4-objects -00:19:16 Trevin: HA -00:23:54 Trevin: Your audio is breaking up Federica -01:06:58 Federica Gazzelloni: https://mastering-shiny.org/reactive-motivation.html?q=R6#event-driven -01:07:37 Federica Gazzelloni: https://engineering-shiny.org/common-app-caveats.html?q=R6#using-r6-as-data-storage -01:10:52 Oluwafemi Oyedele: Thank you !!! -``` -
- -### Cohort 7 - -`r knitr::include_url("https://www.youtube.com/embed/2vxnzqWp-OU")` +# Trade-offs + +**Learning objectives:** + +- Understand the Trade-offs between S3, R6 and S4 + +- Brief intro to S7 (the object system formerly known as R7) + + +## Introduction + +* We have three OOP systems introduced so far (S3, S4, R6) + +* At the current time (pre - S7?) Hadley recommends use S3 by default: It's simple and widely used throughout base R and CRAN. + +* If you have experience in other languages, *Resist* the temptation to use R6 even though it will feel more familiar! + + +## S4 versus S3 + +**Which functional object system to use, S3 or S4? ** + +- **S3** is a simple and flexible system. + + - Good for small teams who need flexibility and immediate payoffs. + + - Commonly used throughout base R and CRAN + + - Flexibility can cause problems, more complex systems might require formal conventions + + +- **S4** is a more formal, strict system. + + - Good for large projects and large teams + + - Used by Bioconductor project + + - Requires significant up front investment in design, but payoff is a robust system that enforces conventions. + + - S4 documentation is challenging to use. + + + +## R6 versus S3 + +**R6** is built on **encapsulated objects**, rather than generic functions. + + +**Big differences: general trade-offs** + +```{r 16-Trade-offs-4, echo=FALSE,fig.align='center'} +knitr::include_graphics("images/16-trade-offs.png") +``` + +## 16.3.1 Namespacing {-} + +**Where methods are found?** + +- in S3, **Generic functions** are **global** and live in the **global namespace** + + - Advantage: Uniform API: `summary`, `print`, `predict` etc. + + - Disadvantage: Must be careful about creating new methods! Homonyms must be avoided, don't define `plot(bank_heist)` + + +- in R6, **Encapsulated methods** are **local**: objects with a **scope** + + - Advantage: No problems with homonyms: meaning of `bank_heist$plot()` is clear and unambiguous. + + - Disadvantage: Lack of a uniform API, except by convention. + + +## 16.3.2 Threading state {-} + + +In S3 the challenge is to return a value and modify the object. + + +```{r} +new_stack <- function(items = list()) { + structure(list(items = items), class = "stack") +} + +push <- function(x, y) { + x$items <- c(x$items, list(y)) + x +} +``` + +No problem with that, but what about when we want to pop a value? We need to return two things. + +```{r} +pop <- function(x) { + n <- length(x$items) + + item <- x$items[[n]] + x$items <- x$items[-n] + + list(item = item, x = x) +} +``` + +The usage is a bit awkward: + +```{r} +s <- new_stack() +s <- push(s, 10) +s <- push(s, 20) + +out <- pop(s) +# Update state: +s <- out$x + +print(out$item) +``` + + +In python and other languages we have structured binding to make this less awkward. R has the {zeallot} package. For more, see this vignette: + +```{r 16-Trade-offs-5, eval=FALSE} +vignette('unpacking-assignment') +``` + +However, this is all easier in R6 due to the reference semantics! + +```{r} +Stack <- R6::R6Class("Stack", list( + items = list(), + push = function(x) { + self$items <- c(self$items, x) + invisible(self) + }, + pop = function() { + item <- self$items[[self$length()]] + self$items <- self$items[-self$length()] + item + }, + length = function() { + length(self$items) + } +)) + +s <- Stack$new() +s$push(10) +s$push(20) +s$pop() +``` + + +## 16.6.3 Method chaining {-} + +Useful to compose functions from left-to-right. + +Use of the operators: + +- S3: `%>%` + +- R6: `$` + +```{r} +s$push(44)$push(32)$pop() +``` + + +## Umm... what about S7 ? {-} + +```{r standards, echo = FALSE, fig.cap = "https://xkcd.com/927/"} + +knitr::include_graphics("https://imgs.xkcd.com/comics/standards_2x.png") + +``` + +### Primary references: {-} + +* Docs: https://rconsortium.github.io/S7/ + +* Talk by Hadley Wickham https://www.youtube.com/watch?v=P3FxCvSueag + +## S7 briefly {-} + +* S7 is a 'better' version of S3 with some of the 'strictness' of S4. + +``` +"A little bit more complex then S3, with almost all of the features, +all of the payoff of S4" - rstudio conf 2022, Hadley Wickham +``` + +* Compatible with S3: S7 objects are S3 objects! Can even extend an S3 object with S7 + +* Somewhat compatible with S4, see [compatability vignette](https://rconsortium.github.io/S7/articles/compatibility.html) for details. + +* Helpful error messages! + +* Note that it was previously called R7, but it was changed to "S7" to better reflect that it is functional not encapsulated! + +## Abbreviated introduction based on the vignette {-} + +To install (it's now on CRAN): +```{r, eval=FALSE} +install.packages("S7") +``` + + +```{r, eval=FALSE} +library(S7) +dog <- new_class("dog", properties = list( + name = class_character, + age = class_numeric +)) +dog + + +#> +#> @ name : dog +#> @ parent: +#> @ properties: +#> $ name: +#> $ age : or +``` + +Note the `class_character`, these are S7 classes corresponding to the base classes. + +Now to use it to create an object of class _dog_: + +```{r, eval = FALSE} +lola <- dog(name = "Lola", age = 11) +lola + +#> +#> @ name: chr "Lola" +#> @ age : num 11 +``` + +Properties can be set/read with `@`, with automatic validation ('safety rails') based on the type! + +```{r, eval = FALSE} + +lola@age <- 12 +lola@age + +#> 12 + +lola@age <- "twelve" + +#> Error: @age must be or , not + +``` + +Note the helpful error message! + +Like S3 (and S4) S7 has generics, implemented with `new_generic` and `method` for particular methods: + +```{r, eval = FALSE} +speak <- new_generic("speak", "x") + +method(speak, dog) <- function(x) { + "Woof" +} + +speak(lola) + +#> [1] "Woof" +``` + +If we have another class, we can implement the generic for that too: + +```{r, eval = FALSE} +cat <- new_class("cat", properties = list( + name = class_character, + age = class_double +)) +method(speak, cat) <- function(x) { + "Meow" +} + +fluffy <- cat(name = "Fluffy", age = 5) +speak(fluffy) + +#> [1] "Meow" +``` + +Helpful messages: + +```{r, eval = FALSE} +speak + +#> speak(x, ...) with 2 methods: +#> 1: method(speak, cat) +#> 2: method(speak, dog) +``` + + +"most usage of S7 with S3 will just work" + +```{r, eval = FALSE} +method(print, cat) <- function(...) { + print("I am a cat.") +} + +print(fluffy) +#> "I am a cat" + +``` + +*For validators, inheritance, dynamic properties and more, see the [vignette!](https://rconsortium.github.io/S7/articles/S7.html)* + +https://rconsortium.github.io/S7/articles/S7.html + +## So... switch to S7 ? {-} + +$$ +\huge +\textbf{Soon}^{tm} +$$ + +* Not yet... still in development! ![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg) + +* But consider trying it out: + + * To stay ahead of the curve... S7 will be integrated into base R someday! + + * To contribute feedback to the S7 team! + + * To get "almost all" of the benefits of S4 without the complexity ! + +* In particular, if you have a new project that might require the complexity of S4, consider S7 instead! + +## OOP system comparison {-} + +| Characteristic | S3 | S4 | S7 | R6 | +|-------|------|------|------|------| +| _Package_ | base R | base R | [S7](https://rconsortium.github.io/S7/) | [R6](https://r6.r-lib.org/) | +| _Programming type_ | Functional | Functional | Functional | Encapulated | +| _Complexity_ | Low | High | Medium | High | +| _Payoff_ | Low | High | High | High | +| _Team size_ | Small | Small-large | Large | ? | +| _Namespace_ | Global | Global? | Global? | Local | +| _Modify in place_ | No | No | No | Yes | +| _Method chaining_ | `|>` | ? | ? | `$` | +| _Get/set component_ | `$` | `@` | `@` | `$` | +| _Create class_ | `class()` or `structure()` with `class` argument | `setClass()` | `new_class()` | `R6Class()` | +| _Create validator_ | `function()` | `setValidity()` or `validator` argument in `setClass()` | `validator` argument in `new_class()` | `$validate()` | +| _Create generic_ | `UseMethod()` | `setGeneric()` | `new_generic()` | NA | +| _Create method_ | `function()` assigned to `generic.method` | `setMethod()` | `method()` | `R6Class()` | +| _Create object_ | `class()` or `structure()` with `class` argument or constructor function | `new()` | Use registered method function | `$new()` | +| _Additional components_ | attributes | slots | properties | | +| | | | | | + +## Meeting Videos {-} + +### Cohort 1 + +`r knitr::include_url("https://www.youtube.com/embed/W1uc8HbyZvI")` + +### Cohort 2 + +`r knitr::include_url("https://www.youtube.com/embed/bzo37PHCM1I")` + +### Cohort 3 + +`r knitr::include_url("https://www.youtube.com/embed/_byYFTQHp1Y")` + +### Cohort 4 + +`r knitr::include_url("https://www.youtube.com/embed/vdKDPBcOc6Y")` + +### Cohort 5 + +`r knitr::include_url("https://www.youtube.com/embed/3EvqtVYTFVM")` + +### Cohort 6 + +`r knitr::include_url("https://www.youtube.com/embed/vEButxFIvLw")` + +
+ Meeting chat log + +``` +00:11:36 Oluwafemi Oyedele: I have not built anything with them!!! +00:16:31 Arthur Shaw: https://cran.r-project.org/web/packages/sp/index.html +00:19:05 Arthur Shaw: Apparently Hadley asked the same question we're asking several years ago: https://stackoverflow.com/questions/5437238/which-packages-make-good-use-of-s4-objects +00:19:16 Trevin: HA +00:23:54 Trevin: Your audio is breaking up Federica +01:06:58 Federica Gazzelloni: https://mastering-shiny.org/reactive-motivation.html?q=R6#event-driven +01:07:37 Federica Gazzelloni: https://engineering-shiny.org/common-app-caveats.html?q=R6#using-r6-as-data-storage +01:10:52 Oluwafemi Oyedele: Thank you !!! +``` +
+ +### Cohort 7 + +`r knitr::include_url("https://www.youtube.com/embed/2vxnzqWp-OU")` From 28582f050f3b6b7f80efcd56af909d641d2b6302 Mon Sep 17 00:00:00 2001 From: Jeffrey Stevens <51374986+JeffreyRStevens@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:39:40 -0500 Subject: [PATCH 02/15] Update text, URLs, etc. --- 16_Trade-offs.Rmd | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index ac05230..9bce965 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -48,9 +48,11 @@ **Big differences: general trade-offs** -```{r 16-Trade-offs-4, echo=FALSE,fig.align='center'} -knitr::include_graphics("images/16-trade-offs.png") -``` +* A generic is a regular function so it lives in the global namespace. An R6 method belongs to an object so it lives in a local namespace. This influences how we think about naming. + +* R6's reference semantics allow methods to simultaneously return a value and modify an object. This solves a painful problem called "threading state". + +* You invoke an R6 method using `$`, which is an infix operator. If you set up your methods correctly you can use chains of method calls as an alternative to the pipe. ## 16.3.1 Namespacing {-} @@ -153,7 +155,7 @@ Useful to compose functions from left-to-right. Use of the operators: -- S3: `%>%` +- S3: `|>` or `%>%` - R6: `$` @@ -172,9 +174,9 @@ knitr::include_graphics("https://imgs.xkcd.com/comics/standards_2x.png") ### Primary references: {-} -* Docs: https://rconsortium.github.io/S7/ +* Docs: -* Talk by Hadley Wickham https://www.youtube.com/watch?v=P3FxCvSueag +* Talk by Hadley Wickham ## S7 briefly {-} @@ -184,6 +186,7 @@ knitr::include_graphics("https://imgs.xkcd.com/comics/standards_2x.png") "A little bit more complex then S3, with almost all of the features, all of the payoff of S4" - rstudio conf 2022, Hadley Wickham ``` +* S3 + S4 = S7 * Compatible with S3: S7 objects are S3 objects! Can even extend an S3 object with S7 @@ -304,7 +307,6 @@ print(fluffy) *For validators, inheritance, dynamic properties and more, see the [vignette!](https://rconsortium.github.io/S7/articles/S7.html)* -https://rconsortium.github.io/S7/articles/S7.html ## So... switch to S7 ? {-} @@ -336,7 +338,7 @@ $$ | _Team size_ | Small | Small-large | Large | ? | | _Namespace_ | Global | Global? | Global? | Local | | _Modify in place_ | No | No | No | Yes | -| _Method chaining_ | `|>` | ? | ? | `$` | +| _Method chaining_ | `|>` | `|>`? | `|>`? | `$` | | _Get/set component_ | `$` | `@` | `@` | `$` | | _Create class_ | `class()` or `structure()` with `class` argument | `setClass()` | `new_class()` | `R6Class()` | | _Create validator_ | `function()` | `setValidity()` or `validator` argument in `setClass()` | `validator` argument in `new_class()` | `$validate()` | From 0973bceb2ddecd20343925aef36e78ac90f6c24c Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:26 -0500 Subject: [PATCH 03/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 9bce965..7532e2c 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -7,7 +7,7 @@ - Brief intro to S7 (the object system formerly known as R7) -## Introduction +## Introduction {-} * We have three OOP systems introduced so far (S3, S4, R6) From b71cb8ee572f6c0b0b7086f654baaa989809284d Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:33 -0500 Subject: [PATCH 04/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 7532e2c..d64e6d2 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -16,7 +16,7 @@ * If you have experience in other languages, *Resist* the temptation to use R6 even though it will feel more familiar! -## S4 versus S3 +## S4 versus S3 {-} **Which functional object system to use, S3 or S4? ** From a2fb17d9c98fa10e5870b2878f77019cb5eb5654 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:38 -0500 Subject: [PATCH 05/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index d64e6d2..3a3f1e2 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -41,7 +41,7 @@ -## R6 versus S3 +## R6 versus S3 {-} **R6** is built on **encapsulated objects**, rather than generic functions. From e42f893fbecd18cb71592dfeb134bdc681a3a671 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:45 -0500 Subject: [PATCH 06/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 3a3f1e2..4f463aa 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -54,7 +54,7 @@ * You invoke an R6 method using `$`, which is an infix operator. If you set up your methods correctly you can use chains of method calls as an alternative to the pipe. -## 16.3.1 Namespacing {-} +## Namespacing {-} **Where methods are found?** From 3495354a7d31060774ac4d0ee12ac281fbed6401 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:50 -0500 Subject: [PATCH 07/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 4f463aa..175c39d 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -72,7 +72,7 @@ - Disadvantage: Lack of a uniform API, except by convention. -## 16.3.2 Threading state {-} +## Threading state {-} In S3 the challenge is to return a value and modify the object. From de253cbae3583e0aa3adff3cfac6972d8e02459b Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:38:58 -0500 Subject: [PATCH 08/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 175c39d..26a2c80 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -149,7 +149,7 @@ s$pop() ``` -## 16.6.3 Method chaining {-} +## Method chaining {-} Useful to compose functions from left-to-right. From aff99f01621c4853a65616c0a87b62733a4b67be Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:04 -0500 Subject: [PATCH 09/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 26a2c80..2ff3b8b 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -358,7 +358,7 @@ $$ `r knitr::include_url("https://www.youtube.com/embed/bzo37PHCM1I")` -### Cohort 3 +### Cohort 3 {-} `r knitr::include_url("https://www.youtube.com/embed/_byYFTQHp1Y")` From 3ef81ef4e5d655d115e66cf0718dc865fe676895 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:10 -0500 Subject: [PATCH 10/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 2ff3b8b..bd5b2c9 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -362,7 +362,7 @@ $$ `r knitr::include_url("https://www.youtube.com/embed/_byYFTQHp1Y")` -### Cohort 4 +### Cohort 4 {-} `r knitr::include_url("https://www.youtube.com/embed/vdKDPBcOc6Y")` From ef1b82747738d1692926858b2671e81003c8fe7f Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:15 -0500 Subject: [PATCH 11/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index bd5b2c9..4466c75 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -366,7 +366,7 @@ $$ `r knitr::include_url("https://www.youtube.com/embed/vdKDPBcOc6Y")` -### Cohort 5 +### Cohort 5 {-} `r knitr::include_url("https://www.youtube.com/embed/3EvqtVYTFVM")` From 47d8e0250b608ab2789ef96810579229f6362fbe Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:21 -0500 Subject: [PATCH 12/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 4466c75..e5055f2 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -370,7 +370,7 @@ $$ `r knitr::include_url("https://www.youtube.com/embed/3EvqtVYTFVM")` -### Cohort 6 +### Cohort 6 {-} `r knitr::include_url("https://www.youtube.com/embed/vEButxFIvLw")` From e13587ed0d1dde0ea3251e640d7908384271e862 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:27 -0500 Subject: [PATCH 13/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index e5055f2..a6715f1 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -389,6 +389,6 @@ $$ ``` -### Cohort 7 +### Cohort 7 {-} `r knitr::include_url("https://www.youtube.com/embed/2vxnzqWp-OU")` From 521f07bf68df63008a72e91bac1680d55ff63b8a Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:36 -0500 Subject: [PATCH 14/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index a6715f1..3a4735d 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -350,7 +350,7 @@ $$ ## Meeting Videos {-} -### Cohort 1 +### Cohort 1 {-} `r knitr::include_url("https://www.youtube.com/embed/W1uc8HbyZvI")` From 3dea6df2f28e2de219367b38a80b7b1566c1fbb9 Mon Sep 17 00:00:00 2001 From: Jon Harmon Date: Tue, 10 Sep 2024 11:39:42 -0500 Subject: [PATCH 15/15] Update 16_Trade-offs.Rmd --- 16_Trade-offs.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/16_Trade-offs.Rmd b/16_Trade-offs.Rmd index 3a4735d..d6bf0de 100644 --- a/16_Trade-offs.Rmd +++ b/16_Trade-offs.Rmd @@ -354,7 +354,7 @@ $$ `r knitr::include_url("https://www.youtube.com/embed/W1uc8HbyZvI")` -### Cohort 2 +### Cohort 2 {-} `r knitr::include_url("https://www.youtube.com/embed/bzo37PHCM1I")`