Title: | Light-Weight 'python'-Like Object-Oriented System |
---|---|
Description: | A light-weight object-oriented system with 'python'-like syntax which supports multiple inheritances and incorporates a 'python'-like method resolution order. |
Authors: | Weihao Li [aut, cre, cph] |
Maintainer: | Weihao Li <[email protected]> |
License: | MIT + file LICENSE |
Version: | 1.0.0 |
Built: | 2024-11-05 03:26:32 UTC |
Source: | https://github.com/tengmcing/bandicoot |
Subtraction operator
x %-% y
x %-% y
x |
Object. |
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..sub.. = function(y) { company(self$name[self$name != y], self$age[self$name != y]) }) good_company <- company(c("patrick", "james"), c(33, 34)) new_company <- good_company %-% "patrick" new_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..sub.. = function(y) { company(self$name[self$name != y], self$age[self$name != y]) }) good_company <- company(c("patrick", "james"), c(33, 34)) new_company <- good_company %-% "patrick" new_company$name
bandicoot_oop
objectThis function performs the subtraction operator using the
..sub..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %-% y
## S3 method for class 'bandicoot_oop' x %-% y
x |
|
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..sub.. = function(y) { company(self$name[self$name != y], self$age[self$name != y]) }) good_company <- company(c("patrick", "james"), c(33, 34)) new_company <- good_company %-% "patrick" new_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..sub.. = function(y) { company(self$name[self$name != y], self$age[self$name != y]) }) good_company <- company(c("patrick", "james"), c(33, 34)) new_company <- good_company %-% "patrick" new_company$name
In-place subtraction operator
x %-=% y
x %-=% y
x |
Object. |
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..isub.. = function(y) { self$age <- self$age[self$name != y] self$name <- self$name[self$name != y] }) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %-=% "patrick" good_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..isub.. = function(y) { self$age <- self$age[self$name != y] self$name <- self$name[self$name != y] }) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %-=% "patrick" good_company$name
bandicoot_oop
objectThis function performs the in-place subtraction operator using the
..iadd..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %-=% y
## S3 method for class 'bandicoot_oop' x %-=% y
x |
|
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..isub.. = function(y) { self$age <- self$age[self$name != y] self$name <- self$name[self$name != y] }) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %-=% "patrick" good_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..isub.. = function(y) { self$age <- self$age[self$name != y] self$name <- self$name[self$name != y] }) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %-=% "patrick" good_company$name
Addition operator
x %+% y
x %+% y
x |
Object. |
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..add.. = function(y) { company(c(self$name, y$name), c(self$age, y$age)) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) new_company <- good_company %+% bad_company new_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..add.. = function(y) { company(c(self$name, y$name), c(self$age, y$age)) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) new_company <- good_company %+% bad_company new_company$name
bandicoot_oop
objectThis function performs the addition operator using the
..add..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %+% y
## S3 method for class 'bandicoot_oop' x %+% y
x |
|
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..add.. = function(y) { company(c(self$name, y$name), c(self$age, y$age)) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) new_company <- good_company %+% bad_company new_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..add.. = function(y) { company(c(self$name, y$name), c(self$age, y$age)) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) new_company <- good_company %+% bad_company new_company$name
In-place addition operator
x %+=% y
x %+=% y
x |
Object. |
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iadd.. = function(y) { self$name <- c(self$name, y$name) self$age <- c(self$age, y$age) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) good_company %+=% bad_company good_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iadd.. = function(y) { self$name <- c(self$name, y$name) self$age <- c(self$age, y$age) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) good_company %+=% bad_company good_company$name
bandicoot_oop
objectThis function performs the in-place addition operator using the
..iadd..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %+=% y
## S3 method for class 'bandicoot_oop' x %+=% y
x |
|
y |
Another object. |
Depends on the method.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iadd.. = function(y) { self$name <- c(self$name, y$name) self$age <- c(self$age, y$age) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) good_company %+=% bad_company good_company$name
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iadd.. = function(y) { self$name <- c(self$name, y$name) self$age <- c(self$age, y$age) }) good_company <- company(c("patrick", "james"), c(33, 34)) bad_company <- company(c("pat", "jam"), c(3, 4)) good_company %+=% bad_company good_company$name
Membership test operator
x %contains% y
x %contains% y
x |
Object. |
y |
Another object. |
A Boolean value.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..contains.. = function(y) y %in% self$name) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %contains% "patrick"
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..contains.. = function(y) y %in% self$name) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %contains% "patrick"
bandicoot_oop
objectThis function performs the membership test operator using the
..contains..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %contains% y
## S3 method for class 'bandicoot_oop' x %contains% y
x |
|
y |
Another object. |
A Boolean value.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..contains.. = function(y) y %in% self$name) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %contains% "patrick"
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..contains.. = function(y) y %in% self$name) good_company <- company(c("patrick", "james"), c(33, 34)) good_company %contains% "patrick"
The equals to operator
x %eq% y
x %eq% y
x |
Object. |
y |
Another object. |
A Boolean value.
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..eq.. = function(y) self$current == y$current) patrick <- age(33) james <- age(33) patrick %eq% james
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..eq.. = function(y) self$current == y$current) patrick <- age(33) james <- age(33) patrick %eq% james
bandicoot_oop
objectThis function performs the equals to operator using the ..eq..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %eq% y
## S3 method for class 'bandicoot_oop' x %eq% y
x |
|
y |
Object. |
A Boolean value.
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..eq.. = function(y) self$current == y$current) patrick <- age(33) james <- age(33) patrick %eq% james
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..eq.. = function(y) self$current == y$current) patrick <- age(33) james <- age(33) patrick %eq% james
The greater or equals to operator
x %ge% y
x %ge% y
x |
Object. |
y |
Another object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..ge.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name >= y$first_name) } return(self$last_name >= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %ge% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..ge.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name >= y$first_name) } return(self$last_name >= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %ge% james
bandicoot_oop
objectThis function performs the greater or equals operator using the ..ge..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %ge% y
## S3 method for class 'bandicoot_oop' x %ge% y
x |
|
y |
Object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..ge.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name >= y$first_name) } return(self$last_name >= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %ge% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..ge.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name >= y$first_name) } return(self$last_name >= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %ge% james
The greater than operator
x %gt% y
x %gt% y
x |
Object. |
y |
Another object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..gt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name > y$first_name) } return(self$last_name > self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %gt% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..gt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name > y$first_name) } return(self$last_name > self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %gt% james
bandicoot_oop
objectThis function performs the greater than operator using the ..gt..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %gt% y
## S3 method for class 'bandicoot_oop' x %gt% y
x |
|
y |
Object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..gt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name > y$first_name) } return(self$last_name > self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %gt% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..gt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name > y$first_name) } return(self$last_name > self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %gt% james
The less or equals to operator
x %le% y
x %le% y
x |
Object. |
y |
Another object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..le.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name <= y$first_name) } return(self$last_name <= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %le% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..le.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name <= y$first_name) } return(self$last_name <= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %le% james
bandicoot_oop
objectThis function performs the less or equals operator using the ..le..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %le% y
## S3 method for class 'bandicoot_oop' x %le% y
x |
|
y |
Object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..le.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name <= y$first_name) } return(self$last_name <= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %le% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..le.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name <= y$first_name) } return(self$last_name <= self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %le% james
The less than operator
x %lt% y
x %lt% y
x |
Object. |
y |
Another object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..lt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name < y$first_name) } return(self$last_name < self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %lt% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..lt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name < y$first_name) } return(self$last_name < self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %lt% james
bandicoot_oop
objectThis function performs the less than operator using the ..lt..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %lt% y
## S3 method for class 'bandicoot_oop' x %lt% y
x |
|
y |
Object. |
A Boolean value.
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..lt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name < y$first_name) } return(self$last_name < self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %lt% james
NAME <- new_class(class_name = "NAME") name <- NAME$instantiate register_method(NAME, ..init.. = function(first_name, last_name) { self$first_name = first_name self$last_name = last_name }) register_method(NAME, ..lt.. = function(y) { if (self$last_name == y$last_name) { return(self$first_name < y$first_name) } return(self$last_name < self$last_name) }) patrick <- name("Patrick", "Li") james <- name("James", "Li") patrick %lt% james
The not equals to operator
x %ne% y
x %ne% y
x |
Object. |
y |
Another object. |
A Boolean value.
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..ne.. = function(y) self$current != y$current) patrick <- age(33) james <- age(33) patrick %ne% james
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..ne.. = function(y) self$current != y$current) patrick <- age(33) james <- age(33) patrick %ne% james
bandicoot_oop
objectThis function performs the not equals to operator using the ..ne..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' x %ne% y
## S3 method for class 'bandicoot_oop' x %ne% y
x |
|
y |
Object. |
A Boolean value.
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..ne.. = function(y) self$current != y$current) patrick <- age(33) james <- age(33) patrick %ne% james
AGE <- new_class(class_name = "AGE") age <- AGE$instantiate register_method(AGE, ..init.. = function(current) self$current = current) register_method(AGE, ..ne.. = function(y) self$current != y$current) patrick <- age(33) james <- age(33) patrick %ne% james
bandicoot_oop
objectThis function tries to turn an environment into a bandicoot_oop
object.
as_bandicoot_oop( env, ..class.. = NULL, ..type.. = NULL, ..instantiated.. = NULL, overwrite_container = FALSE, register = FALSE, in_place = FALSE, container_name = "..method_env..", self_name = "self" )
as_bandicoot_oop( env, ..class.. = NULL, ..type.. = NULL, ..instantiated.. = NULL, overwrite_container = FALSE, register = FALSE, in_place = FALSE, container_name = "..method_env..", self_name = "self" )
env |
An environment. |
..class.. |
Character. A series of class names. |
..type.. |
Character. The class name of this object. |
..instantiated.. |
Boolean. Whether this object is an instance. |
overwrite_container |
Boolean. Whether or not to overwrite the container. |
register |
Boolean. Whether or not to register functions if there are any. |
in_place |
Boolean. Whether or not to modify the environment in-place. If not, a new environment will be created. |
container_name |
Character. Name of the container. |
self_name |
Character. Name of the self reference. |
A Boolean value.
e <- new.env() e$a <- function() self as_bandicoot_oop(e, ..class.. = "test", ..type.. = "test", ..instantiated.. = FALSE, register = TRUE, in_place = TRUE) e e$a()
e <- new.env() e$a <- function() self as_bandicoot_oop(e, ..class.. = "test", ..type.. = "test", ..instantiated.. = FALSE, register = TRUE, in_place = TRUE) e e$a()
This class provides essential attributes and methods. It makes
the assumption that the container name is ..method_env..
and the name of
the reference to self is self
. If you would like to use other container
names and self names, you need to overwrite the class definition of BASE.
The class environment is defined as an empty environment by new.env()
at build-time, and the class descriptor is run at load-time by
.onLoad()
.
This ensures methods and attributes of the class is built with the
load-time (usually latest) installed dependencies (if it depends on any).
Derived classes should follow the same principle to avoid running the class
descriptor at build-time, and only defines the content of the class at
load-time.
Since bandicoot
does not support dynamic dispatch,
calling the correct parent method can be difficult in a
complex class system.
So, users can use the ..mro..
(method resolution order) attribute and the
super()
function to determine the correct super/next class.
If users decide to store parent environments in
the derived class such that parent method can be called more handily,
awareness needs to be raised when saving and loading these classes/instances.
It is very likely the same class stored in different objects becomes different
environments.
base_(..., env = new.env(parent = parent.frame()), init_call = sys.call())
base_(..., env = new.env(parent = parent.frame()), init_call = sys.call())
... |
Ignored. |
env |
Environment. The instance environment. |
init_call |
Call. Contents of the |
An instance environment.
base_()
: Class constructor, same as BASE$instantiate()
.
B:
C:
I:
M:
D:
G:
H:
I:
L:
M:
N:
R:
S:
Direct parent classes
BASE$..bases.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..bases..
BASE$..bases.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..bases..
A list.
BASE$..class_tree.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..class_tree..
BASE$..class_tree.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..class_tree..
A string vector.
BASE$..class.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..class..
BASE$..class.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..class..
This function returns all names in the environment.
BASE$..dir..()
A vector of string.
BASE$..dir..() # Instantiate test <- BASE$instantiate() test$..dir..()
BASE$..dir..() # Instantiate test <- BASE$instantiate() test$..dir..()
This function will be called after an instance is built. User could override this function in derived class.
BASE$..init..(...)
... |
Ignored by |
Return the object itself.
BASE$..init.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") # Override the `..init..` method register_method(TEST, ..init.. = function(a) {self$x <- a}) # Build a `TEST` instance test <- TEST$instantiate(a = 2) test$x
BASE$..init.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") # Override the `..init..` method register_method(TEST, ..init.. = function(a) {self$x <- a}) # Build a `TEST` instance test <- TEST$instantiate(a = 2) test$x
Whether or not the object is an instance.
BASE$..instantiated.. # Instantiate test <- BASE$instantiate() test$..instantiated..
BASE$..instantiated.. # Instantiate test <- BASE$instantiate() test$..instantiated..
User could override this method in derived class.
BASE$..len..()
BASE$..len..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") # Override the `..len..` method register_method(TEST, ..len.. = function() 1) TEST$..len..()
BASE$..len..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") # Override the `..len..` method register_method(TEST, ..len.. = function() 1) TEST$..len..()
A container where methods will be executed.
BASE$..method_env.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..method_env..
BASE$..method_env.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..method_env..
This function lists all methods of a class or an instance.
BASE$..methods..()
A string vector.
BASE$..methods..()
BASE$..methods..()
Method resolution order defined using C3 algorithm.
BASE$..mro.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..mro..
BASE$..mro.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..mro..
This function will copy all methods and attributes, except
the container, and the instantiate method. Then, the ..init_call..
attribute
will be set to the current system call, and the ..instantiated..
attribute
will be set to TRUE
. Notice, the ..init..
method will not run.
BASE$..new..(env = new.env(parent = parent.frame()), init_call = sys.call())
env |
Environment. The instance environment. |
init_call |
Call. Contents of the |
An instance environment.
BASE$..new..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..new..()
BASE$..new..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..new..()
This function returns a "official" string representation of the object, which may be used to reconstruct the object given an appropriate environment.
BASE$..repr..()
A string.
BASE$..repr..() test <- base_() test$..repr..() test <- BASE$instantiate() test$..repr..() test <- BASE$..new..() test$..repr..()
BASE$..repr..() test <- base_() test$..repr..() test <- BASE$instantiate() test$..repr..() test <- BASE$..new..() test$..repr..()
This function returns a string representation of the object.
BASE$..str..()
A string.
BASE$..str..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..str..() # Instantiate test <- BASE$instantiate() test$..str..()
BASE$..str..() # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..str..() # Instantiate test <- BASE$instantiate() test$..str..()
A string.
BASE$..type.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..type..
BASE$..type.. # Inherit from BASE TEST <- new_class(BASE, class_name = "TEST") TEST$..type..
This function delete an attribute.
BASE$del_attr(attr_name)
attr_name |
Character. Attribute name. |
Return the object itself.
test <- BASE$instantiate() test$set_attr("x", 1) test$x test$del_attr("x") test$x
test <- BASE$instantiate() test$set_attr("x", 1) test$x test$del_attr("x") test$x
This function gets the value of an attribute or a method.
BASE$get_attr(attr_name)
attr_name |
Character. Attribute name. |
The attribute value.
BASE$get_attr("test") BASE$get_attr("..methods..")
BASE$get_attr("test") BASE$get_attr("..methods..")
This function checks whether or not an attribute or method exists.
BASE$has_attr(attr_name)
attr_name |
Character. Attribute name. |
True or FALSE.
BASE$has_attr("test") BASE$has_attr("..len..")
BASE$has_attr("test") BASE$has_attr("..len..")
This function will new an instance using the ..new..
method,
then initialized the instance with the ..init..
method.
BASE$instantiate( ..., env = new.env(parent = parent.frame()), init_call = sys.call() )
... |
Arguments passed to |
env |
Environment. The instance environment. |
init_call |
Call. Contents of the |
An instance environment.
BASE$..dir..() # Build an instance base_instance <- BASE$instantiate() base_instance$..dir..()
BASE$..dir..() # Build an instance base_instance <- BASE$instantiate() base_instance$..dir..()
This function sets the value of an attribute or a method.
BASE$set_attr(attr_name, attr_val)
attr_name |
Character. Attribute name. |
attr_val |
Any value. |
Return the object itself.
test <- BASE$instantiate() test$set_attr("x", 1) test$x
test <- BASE$instantiate() test$set_attr("x", 1) test$x
This function is equivalent to environment(fn) <- env
. Hence functions
must bind to names.
bind_fn_2_env(env, ...)
bind_fn_2_env(env, ...)
env |
Environment. |
... |
Functions. |
Pass character function names to ...
will cause error.
No return value, called for side effects.
# Access the associated environment inside a function self <- NULL e <- new.env() # The associated environment needs to have a reference to itself e$self <- e e$show_self <- function() return(self) # The function can only access the global variable `self` e$show_self() # Bind the function to the environment `e` bind_fn_2_env(env = e, e$show_self) # Both point to the same environment e$show_self() e
# Access the associated environment inside a function self <- NULL e <- new.env() # The associated environment needs to have a reference to itself e$self <- e e$show_self <- function() return(self) # The function can only access the global variable `self` e$show_self() # Bind the function to the environment `e` bind_fn_2_env(env = e, e$show_self) # Both point to the same environment e$show_self() e
::
.Method body could contain names like "mutate" that are from packages,
it usually would not be a problem as long as the package namespace is in
the search path or it is available in the parent environment of the object.
However, if the package is not loaded via functions like library()
and
the name used in the method body is unavailable in the parent environment of
the object, then an error may be raised saying that "object name
not found"
when the method is run.
This function helps detect this kind of
problems. Users needs to specify the names they want to detect, and specify
the package they belong to.
check_method(env, symbol_name, target_namespace)
check_method(env, symbol_name, target_namespace)
env |
Environment. An environment. |
symbol_name |
Character. Names that want to be detected. |
target_namespace |
Character. Name of the package that symbols belong to. |
No return value, called for side effects.
e <- new.env() register_method(e, test = function() cli_alert_info("test")) check_method(e, "cli_alert_info", "cli") register_method(e, test = function() cli::cli_alert_info("test")) check_method(e, "cli_alert_info", "cli")
e <- new.env() register_method(e, test = function() cli_alert_info("test")) check_method(e, "cli_alert_info", "cli") register_method(e, test = function() cli::cli_alert_info("test")) check_method(e, "cli_alert_info", "cli")
This function copy attributes and methods from classes or instances to class or instance.
copy_attr( env, ..., avoid = c("..method_env..", "..init_call.."), class_name = env$..type.. )
copy_attr( env, ..., avoid = c("..method_env..", "..init_call.."), class_name = env$..type.. )
env |
Environment. The destination environment. |
... |
Environments. Source environments. |
avoid |
Character. Names that don't want to be copied. |
class_name |
Character. Name of the class the method is defined.
This is important for |
Multiple classes or instances can be provided in ...
, where the right one
will override the left one if they have the same attribute or method name.
Attributes or methods that don't want to be copied can be specified in
avoid
.
Return the object itself.
test <- new.env() names(BASE) copy_attr(test, BASE, avoid = c("..method_env..", "..init_call..", "..dir..")) names(test)
test <- new.env() names(BASE) copy_attr(test, BASE, avoid = c("..method_env..", "..init_call..", "..dir..")) names(test)
This function loads functions from package namespaces and assigns them to the preferred function names in the current environment.
define_pkg_fn(pkg, ...)
define_pkg_fn(pkg, ...)
pkg |
Package. |
... |
Functions. Preferred names can be provide via named arguments. |
Preferred function names can be provide via named arguments
like info = cli_alert_info
.
No return value, called for side effects.
define_pkg_fn(pkg = cli, cli_alert_info, cli_alert_warning) define_pkg_fn(cli, cli_alert_warning, info = cli_alert_info)
define_pkg_fn(pkg = cli, cli_alert_info, cli_alert_warning) define_pkg_fn(cli, cli_alert_warning, info = cli_alert_info)
bandicoot_oop
objectThis function check whether the object is a bandicoot_oop
object.
is_bandicoot_oop(obj, why = FALSE)
is_bandicoot_oop(obj, why = FALSE)
obj |
Any object. |
why |
Boolean. Whether or not to print the reason when the check fail. |
A Boolean value.
e <- new.env() is_bandicoot_oop(e) e <- new_class(class_name = "test") is_bandicoot_oop(e)
e <- new.env() is_bandicoot_oop(e) e <- new_class(class_name = "test") is_bandicoot_oop(e)
Build an iterator
iter(x, ...)
iter(x, ...)
x |
Object. |
... |
Additional arguments needed for building an iterator. |
An iterator.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iter.. = function(...) { split(data.frame(name = self$name, age = self$age), 1:length(self$name)) }) good_company <- company(c("patrick", "james"), c(33, 34)) for (person in iter(good_company)) { print(person) }
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iter.. = function(...) { split(data.frame(name = self$name, age = self$age), 1:length(self$name)) }) good_company <- company(c("patrick", "james"), c(33, 34)) for (person in iter(good_company)) { print(person) }
bandicoot_oop
objectThis function builds an iterator using the ..iter..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' iter(x, ...)
## S3 method for class 'bandicoot_oop' iter(x, ...)
x |
|
... |
Additional arguments needed for building an iterator. |
An iterator.
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iter.. = function(...) { split(data.frame(name = self$name, age = self$age), 1:length(self$name)) }) good_company <- company(c("patrick", "james"), c(33, 34)) for (person in iter(good_company)) { print(person) }
COMPANY <- new_class(class_name = "COMPANY") company <- COMPANY$instantiate register_method(COMPANY, ..init.. = function(name, age) { self$name <- name self$age <- age }) register_method(COMPANY, ..iter.. = function(...) { split(data.frame(name = self$name, age = self$age), 1:length(self$name)) }) good_company <- company(c("patrick", "james"), c(33, 34)) for (person in iter(good_company)) { print(person) }
Compute the length of the object
len(x, ...)
len(x, ...)
x |
Object. |
... |
Additional arguments needed for computing the length. |
An integer.
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) register_method(EMAIL, ..len.. = function() nchar(self$address)) patrick <- email('[email protected]') len(patrick)
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) register_method(EMAIL, ..len.. = function() nchar(self$address)) patrick <- email('[email protected]') len(patrick)
bandicoot_oop
objectThis function computes the length of the object by using the ..len..()
method. If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' len(x, ...)
## S3 method for class 'bandicoot_oop' len(x, ...)
x |
|
... |
ignored. |
An integer.
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) register_method(EMAIL, ..len.. = function() nchar(self$address)) patrick <- email('[email protected]') len(patrick)
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) register_method(EMAIL, ..len.. = function() nchar(self$address)) patrick <- email('[email protected]') len(patrick)
This function declare a new class, and copies attributes and methods from parent classes.
new_class( ..., env = new.env(parent = parent.frame()), class_name = NULL, empty_class = FALSE )
new_class( ..., env = new.env(parent = parent.frame()), class_name = NULL, empty_class = FALSE )
... |
Environments. Parent class environments. |
env |
Environment. The new class environment. |
class_name |
Name of the new class. |
empty_class |
Boolean. Whether to create an empty class. This should only
be used when you don't want to inherited from BASE, or you want to define
your own base object class. Will be ignored if |
Parents can be provided in ...
, where methods and attributes will be
overrided by the left classes because bandicoot
does not support dynamic
dispatch at the moment. However, this behaviour usually aligns with the method
resolution order defined by the C3 algorithm used in Python.
If ...
is empty and empty_class == FALSE
,
BASE will be used as the parent class.
A class environment with S3 class "bandicoot_oop".
MYCLASS <- new_class(class_name = "MYCLASS") MYCLASS names(MYCLASS) # Inhert from BASE class TEST <- new_class(BASE, class_name = "TEST") TEST names(TEST)
MYCLASS <- new_class(class_name = "MYCLASS") MYCLASS names(MYCLASS) # Inhert from BASE class TEST <- new_class(BASE, class_name = "TEST") TEST names(TEST)
bandicoot_oop
objectThis function print the string representation of the object by using the
..str..()
method.
## S3 method for class 'bandicoot_oop' print(x, ...)
## S3 method for class 'bandicoot_oop' print(x, ...)
x |
|
... |
ignored. |
No return value, called for side effects.
print(base_())
print(base_())
This function register a function as a method of an object environment.
register_method( env, ..., container_name = "..method_env..", self_name = "self", class_name = env$..type.. )
register_method( env, ..., container_name = "..method_env..", self_name = "self", class_name = env$..type.. )
env |
Environment. Object environment. |
... |
Named Functions. Functions needs to be provided in named format,
like |
container_name |
Character. Name of the container. Methods will be executed inside this container. |
self_name |
Character. Name of the self reference. Methods needs to use this name to access the object environment. |
class_name |
Character. Name of the class of the object environment.
This is important for |
Methods will be executed inside a container, which is a child
environment of the parent of the object environment. Thus, methods can not
access variables of the object environment directly, but can access
variables of the parent of the object environment directly. The designed
way for methods to access the object environment is by using the name
"self", this name can be changed by specifying a string in self_name
.
The default name of the container is "..method_env..". This also can be changed
by specifying a string in container_name
. An object can have multiple
containers, but every container is recommended to contain only one self
reference.
Method needs to be provided as a = function() 1
, where a
is the name of
the method and the right hand side of the equal sign is the function.
Warning will be raised if the container contains contents other than the
self reference.
Return the object itself.
a <- function() self$x e <- new.env() e$x <- 1 # Register the method `aa` for environment `e` with `self_name = "self"` register_method(e, aa = a, self_name = "self", class_name = "test") # There is an environment `..method_env..` in the environment `e` names(e) # The container is empty (except `self`) names(e$..method_env..) # `self` is a reference to `e` identical(e, e$..method_env..$self) # The method `aa` will be evaluated in the container identical(environment(e$aa), e$..method_env..) # Therefore, `self$x` is a reference to variable `x` of the environment `e` e$aa()
a <- function() self$x e <- new.env() e$x <- 1 # Register the method `aa` for environment `e` with `self_name = "self"` register_method(e, aa = a, self_name = "self", class_name = "test") # There is an environment `..method_env..` in the environment `e` names(e) # The container is empty (except `self`) names(e$..method_env..) # `self` is a reference to `e` identical(e, e$..method_env..$self) # The method `aa` will be evaluated in the container identical(environment(e$aa), e$..method_env..) # Therefore, `self$x` is a reference to variable `x` of the environment `e` e$aa()
The "official" string representation of an object. If at all possible, this should look like a valid R expression that could be used to recreate an object wit the same value (given an appropriate environment). This description is copied from the python documentation.
repr(x, ...)
repr(x, ...)
x |
Object. |
... |
Additional arguments needed for computing the string. |
A string.
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) patrick <- email('[email protected]') repr(patrick)
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) patrick <- email('[email protected]') repr(patrick)
bandicoot_oop
objectThis function computes the "official" string representation of a
bandicoot_oop
object using the ..repr..()
method.
If it is not applicable, error will be raised.
## S3 method for class 'bandicoot_oop' repr(x, ...)
## S3 method for class 'bandicoot_oop' repr(x, ...)
x |
|
... |
ignored. |
An integer.
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) patrick <- email('[email protected]') repr(patrick)
EMAIL <- new_class(class_name = "EMAIL") email <- EMAIL$instantiate register_method(EMAIL, ..init.. = function(address) self$address = address) patrick <- email('[email protected]') repr(patrick)
This function substitute all old_names
with new_names
in a function
body, and drops all the attributes.
sub_fn_body_name(fn, old_name, new_name)
sub_fn_body_name(fn, old_name, new_name)
fn |
Function. |
old_name |
Character. Name that needs to be replaced. |
new_name |
Character. Replacement of the old name. |
A function.
a <- function() self$x + self$y a sub_fn_body_name(a, "self", "this")
a <- function() self$x + self$y a sub_fn_body_name(a, "self", "this")
This function gets the parent class or the next class based on the method resolution order. This is useful when one wants to access the overwritten parent class method or the overwritten parent class attribute.
super(self_name = "self", mro_current_name = "..mro_current..", where = NULL)
super(self_name = "self", mro_current_name = "..mro_current..", where = NULL)
self_name |
Character. The name of the self reference. |
mro_current_name |
Character. The name of the variable storing the current class. This is used to determine the next class. |
where |
Environment/Character. The target environment to search for the
parent class. If |
Note that this function assumes the parent class can be found in the
parent environment of the current object. If one wants to find the
parent class from a package, it needs to be specified via the where
argument.
A bandicoot
object which is an environment.
# Define class O O <- new_class(class_name = "O") register_method(O, foo = function() { print("Calling class O `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) }) # Define class F F <- new_class(O, class_name = "F") register_method(F, foo = function() { print("Calling class F `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class E E <- new_class(O, class_name = "E") register_method(E, foo = function() { print("Calling class E `foo` method") print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class D D <- new_class(O, class_name = "D") register_method(D, foo = function() { print("Calling class D `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class C C <- new_class(D, F, class_name = "C") register_method(C, foo = function() { print("Calling class C `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class B B <- new_class(E, D, class_name = "B") register_method(B, foo = function() { print("Calling class B `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class A A <- new_class(B, C, class_name = "A") register_method(A, foo = function() { print("Calling class A `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # To understand why the order is A, B, E, C, D, F, O, # please check [https://www.python.org/download/releases/2.3/mro/]. a <- A$instantiate() a$my_name <- "a" a$foo()
# Define class O O <- new_class(class_name = "O") register_method(O, foo = function() { print("Calling class O `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) }) # Define class F F <- new_class(O, class_name = "F") register_method(F, foo = function() { print("Calling class F `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class E E <- new_class(O, class_name = "E") register_method(E, foo = function() { print("Calling class E `foo` method") print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class D D <- new_class(O, class_name = "D") register_method(D, foo = function() { print("Calling class D `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class C C <- new_class(D, F, class_name = "C") register_method(C, foo = function() { print("Calling class C `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class B B <- new_class(E, D, class_name = "B") register_method(B, foo = function() { print("Calling class B `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # Define class A A <- new_class(B, C, class_name = "A") register_method(A, foo = function() { print("Calling class A `foo` method") print(paste0("Self is ", self$my_name)) print(paste0("Next class is ", super()$..type..)) use_method(self, super()$foo)() }) # To understand why the order is A, B, E, C, D, F, O, # please check [https://www.python.org/download/releases/2.3/mro/]. a <- A$instantiate() a$my_name <- "a" a$foo()
This function makes a copy of the function, then set the evaluation environment to the container of the object environment.
use_method(env, fn, container_name = "..method_env..")
use_method(env, fn, container_name = "..method_env..")
env |
Environment. Object. |
fn |
Function. Method. |
container_name |
Character. Name of the container. |
A method.
TEST <- new_class(class_name = "TEST") register_method(TEST, ..str.. = function() "test") test <- TEST$instantiate(dist = "uniform", prm = list(a = 1, b = 2)) test$..str..() # Use method `..str..` from BASE class use_method(test, BASE$..str..)()
TEST <- new_class(class_name = "TEST") register_method(TEST, ..str.. = function() "test") test <- TEST$instantiate(dist = "uniform", prm = list(a = 1, b = 2)) test$..str..() # Use method `..str..` from BASE class use_method(test, BASE$..str..)()