···66pak::pkg_install("VisruthSK/BigNum")
77```
8899-## Why S7?
99+## Overview
1010+1111+***This project is a work in progress, and needs reviews and revisions to check for consistency and such. Some best practices for S7 development (e.g. [documentation](https://github.com/RConsortium/S7/issues/315)) haven't been established yet though.***
1212+1313+What is S7? What is BigNum? Why can't I subtract two `big_num`s?
10141111-This package was created for a number of reasons. Chief among those is to provide a worked example of S7 in a package context, but it was also written to purvey the benefits of S7. So here I wish to address some reasons why S7 is best, and why you should seriously consider using S7 the next time you need a class for something. This is almost entirely subjective, and as an op-ed, the points I make are personal. There are certainly many contexts where S7 is not appropriate (one could argue that this package is best suited to R6), but there are also many places where you *could* use S7; I'm more focused on the latter.
1515+Let's start with the most interesting part: S7.
12161313-S7 is formal. I first encountered S3 when speaking to Dr Bodwin; the topic came up somehow and she showed me how flexible S3 is with an example, something like:
1717+### S7
1818+1919+["The S7 package is a new OOP system designed to be a successor to S3 and S4." - R Consortium Object-Oriented Programming Working Group.](https://rconsortium.github.io/S7/)
2020+2121+S7 is a new way to do OOP in R, and I think it is fantastic. The quote above links to the official S7 website, which contains a great deal of information regarding S7--its origins, features, compatibility, specifications, etc. I think any developer who wishes to use S7 should certainly study that website. It is quite cogent and detailed, and I use it as a reference all the time–its practically an extra chapter of Advanced R. This package is meant to be used in conjunction with the S7 website, hopefully serving as a (slightly non-contrived) implementation which can be used to understand how S7 can work in practice.
2222+2323+Some goals of the project, viz. with regards to S7:
2424+2525+Since S7 is so new, and is still technically experimental, major changes to the API [aren't off the table](https://rconsortium.github.io/S7/index.html?q=experimental#s7). As such, for this project to be effective, it will be updated with S7 as the OOP system matures. The package's major version will follow S7, which is why this (will) release into 2.0.0. Best practices, as and when they are developed, will be implemented to serve as an effective, worked out example for S7 package development.
2626+2727+### Why S7?
2828+2929+This package was created for a number of reasons. Chief among those is to provide a worked example of S7 in a package context, but it was also written to purvey the benefits of S7, and posit it as the next R OOP paradigm you should reach for. I highly recommend listening to Hadley's talk on S7 (then called R7) at posit::conf(2022) (link in references--thank you [Dr Bodwin](https://www.kelly-bodwin.com/) for showing this to me!), and reading the S7 webpage to get arguments for S7 from very bright people. This section can be skipped--or at least skimmed--if you (like me) are convinced that S7 is the way to go.
3030+3131+Here's an unordered list of some nice things about S7. I won't directly address these ideas, but you can observe them throughout the code.
3232+3333+1. Just the right amount of formal
3434+2. Just the right amount of flexible
3535+3. Cogent API
3636+4. Easy to extend
3737+5. Classes, properties, validators, etc. give nice guarantees
3838+3939+S7 is elegantly formal. I first encountered S3 when speaking to Dr Bodwin; the topic came up somehow and she showed me how simple and flexible S3 is with an example, something like:
14401541```{r}
1642x <- 1:10
···3359mean(structure(1:10, class = "test"))
3460```
35613636-but I think this is harder to reason about. The idea of just giving `1:10` a class without really defining what that class is, is strange to me. S7 makes it very clear what things are; I find this easier to reason about.
6262+but I think this is harder to reason about. The idea of just giving a garden variety vector `1:10` a whole class without really defining what that class is, is strange to me. I find it hard sometimes to understand what things are. S7 makes it very clear what things are; I find this easier to reason about. This is something I noted firsthand when swapping to S7 in some Tidyverse packages. Even with well documented code, it can be hard to understand how things work.
6363+6464+S7 may be formal, but it is also elegant–there are nice design patterns that can be implemented effortlessly. Take, for example, this implementation of some `Shape`s.
6565+6666+```{r}
6767+library(S7)
37683838-## Overview
6969+Shape <- new_class("Shape", abstract = TRUE)
7070+Circle <- new_class("Circle", Shape, properties = list(radius = class_numeric))
7171+Rect <- new_class("Rect", Shape, properties = list(width = class_numeric, height = class_numeric))
39724040-***This project is a work in progress, needs reviews and revisions to check for consistency and such. Some best practices for S7 development (e.g. [documentation](https://github.com/RConsortium/S7/issues/315)) haven't been established yet though.***
7373+Area <- new_generic("Area", "x")
7474+method(Area, Circle) <- \(x) pi * x@radius^2
7575+method(Area, Rect) <- \(x) x@width * x@height
7676+7777+circ <- Circle(4 / (sqrt(pi)))
7878+rect <- Rect(10, 4)
41794242-What is S7? What is BigNum? Why can't I subtract two `big_num`s?
8080+Area(circ)
8181+Area(rect)
8282+```
43834444-Let's start with the most interesting part: S7.
8484+This was a quick and dirty implementation I wrote in a few minutes (for something else.)
45854646-### S7
8686+It can easily be extended to admit a `Square` class:
47874848-["The S7 package is a new OOP system designed to be a successor to S3 and S4." - R Consortium Object-Oriented Programming Working Group.](https://rconsortium.github.io/S7/)
8888+```{r}
8989+Square <- new_class("Square", Rect, constructor = function(side) new_object(Square, width = side, height = side))
9090+square <- Square(5)
49915050-S7 is a new way to do OOP in R, and I think it is fantastic. The quote above links to the official S7 website, which contains a great deal of information regarding S7--its origins, features, compatibility, specifications, etc. I think any developer who wishes to use S7 should certainly study that website. It is quite cogent and detailed, and I use it as a reference all the time–its practically an extra chapter of Advanced R. This package is meant to be used in conjunction with the S7 website, hopefully serving as a (slightly non-contrived) implementation which can be used to understand how S7 can work in practice.
9292+Area(square)
9393+```
51945252-Some goals of the project, viz. with regards to S7:
9595+And, more usefully, our classes can be (minimally) changed to guarantee that the provided values are positive–being numeric is already ensured by using `class_numeric`, even in the original definitions.
53965454-Since S7 is so new, and is still technically experimental, major changes to the API [aren't off the table](https://rconsortium.github.io/S7/index.html?q=experimental#s7). As such, for this project to be effective, it will be updated with S7 as the OOP system matures. The package's major version will follow S7, which is why this (will) release into 2.0.0. Best practices, as and when they are developed, will be implemented to serve as an effective, worked out example for S7 package development.
9797+```{r}
9898+positive_numeric <- new_property(class_numeric, validator = function(value) if(value <= 0) "must be greater than 0")
9999+100100+Circle <- new_class("Circle", Shape, properties = list(radius = positive_numeric))
101101+Rect <- new_class("Rect", Shape, properties = list(width = positive_numeric, height = positive_numeric))
102102+103103+# Rect(0, 4)
104104+#> ! <Rect> object properties are invalid:
105105+#> - @width must be greater than 0
106106+107107+# Circle(-10)
108108+#> ! <Circle> object properties are invalid:
109109+#> - @radius must be greater than 0
110110+111111+# and of course this still holds for Squares
112112+# Square(-1)
113113+#> ! <Square> object properties are invalid:
114114+#> - @width must be greater than 0
115115+#> - @height must be greater than 0
116116+```
117117+118118+This is hardly the most interesting example (hence the package!), and these aren't the most groundbreaking principles, but having these OOP ideas are very nice. They're presented in a cogent API and allow you to spell out what you need to do: `new_class()`, `new_generic()`, `new_external_generic()`, `method()`, etc. The formality and structure that S7 provides manifests as interpretable, clean code. Most importantly, it is readable code.
119119+120120+#### Some Random Thoughts/Interesting Points
121121+122122+##### Read Only Properties
123123+124124+You can set read only properties with S7, which you can observe in the package (ALLCAPS properties are constants or "final".) That is a very nice way to expose values which you wish users to be aware of but don't want to mess with, like the value of a linked list node. You can, of course, bypass this:
125125+126126+```{r}
127127+# https://rconsortium.github.io/S7/articles/classes-objects.html#frozen-properties
128128+eg <- new_class("eg", properties = list(VALUE = new_property(class_any, setter = function(self, value){
129129+ if(!is.null(self@VALUE)) stop("@VALUE is read only.")
130130+ self@VALUE <- value
131131+ self
132132+})))
133133+134134+tmp <- eg(10)
135135+tmp
136136+#> <eg>
137137+#> @ VALUE: num 10
138138+139139+# tmp@VALUE <- 1
140140+#> ! @VALUE is read only.
141141+142142+attr(tmp, "VALUE") <- 1
143143+tmp
144144+#> <eg>
145145+#> @ VALUE: num 1
146146+```
147147+148148+but you clearly have to go out of your way to. Normal usage of `eg` objects, with the exposed API, would ensure that you don't accidentally change constants.
149149+150150+You can also do cool stuff with [computed/dynamic properties](https://rconsortium.github.io/S7/articles/classes-objects.html#properties).
151151+152152+##### Var Args
153153+154154+I don't think you can't easily do anything like this in S7 ([yet](https://github.com/RConsortium/S7/issues/515)):
155155+156156+```{r}
157157+function(...){
158158+ structure(..., class = "test")
159159+}
160160+```
161161+162162+##### State
163163+164164+You have to use environments to get state in S7 (again, see package)--but I have it on very strong authority that a stateful S7 is being thought of. Don't quote me on that.
165165+166166+S7 marries (most of) the flexibility of S3 with (most of) the formality of S4. I find it strikes a perfect middle ground which makes it easier to dictate what objects of type `<T>` can and can't do.
5516756168### BigNum
571695858-So what is BigNum? And why this project?
170170+So finally what is BigNum? And why this project?
5917160172Firstly, it is important to note that this is wholly a *toy* package. Whilst the package will build, and expose an API one can use to create `big_num` objects, I do not think one *should* use these as arbitrary precision numbers (look towards packages like [Rmpfr](https://cran.r-project.org/web/packages/Rmpfr/index.html).) This package's implementation is very rough and many properties one would expect from "numbers" are missing–negation, subtraction, division, modulus, etc. are all not implemented. The point of this package is not to veritably implement infinite precision numbers, but rather to show how S7 can be used in a package to make some basic data structures and work with some generics/functions. The package itself is very simple and has a relatively concise implementation. Since this package's purpose is pedagogical, there isn't much point in implementing the aforementioned features.
61173···74186Maechler M (2024). *Rmpfr: Interface R to MPFR - Multiple Precision Floating-Point Reliable*. R package version 1.0-0, <https://CRAN.R-project.org/package=Rmpfr>.
7518776188Wickham H (2019). *Advanced R* (2nd ed.). CRC Press.
189189+190190+Wickham H (2022). *An Introduction to R7*. <https://www.youtube.com/watch?v=P3FxCvSueag>
7719178192Wickham H, Bryan J (2023). *R Packages* (2nd ed.). O'Reilly Media.
79193