I learned this way from the Johns Hopkins MOOC R Programming a long time ago on Coursera. The idea was to return a list of functions that were defined in a father function's scope. For example:
newString <- function(s) {
l <- nchar(s)
return(list(
get = function() return(s),
len = function() return(l),
concate = function(cat) {
s <<- paste0(s, cat)
l <<- nchar(s)
},
find = function(pattern) return(grepl(pattern, s)),
substitute = function(pattern, sub) {
s <<- gsub(pattern, sub, s)
l <<- nchar(s)
}
))
}
This function returns a list of functions/methods which can manipulate the item "s". I can "new" this "object" calling the father function:
my <- newString("hellow")
And using the "methods" with $
just looks like OOP.
my$get()
# [1] "hellow"
my$len()
# [1] 6
my$substitute("w$", "")
my$get()
# [1] "hello"
my$len()
# [1] 5
my$concate(", world")
my$get()
# [1] "hello, world"
my$find("world$")
# [1] TRUE
To print the "object" directly, we can see it is a list of functions. And all these functions located in the same environment 0x103ca6e08
, where the item s
was also in.
my
# $get
# function ()
# return(s)
# <bytecode: 0x1099ac1e0>
# <environment: 0x103ca6e08>
#
# $len
# function ()
# return(l)
# <bytecode: 0x109a58058>
# <environment: 0x103ca6e08>
#
# $concate
# function (cat)
# {
# s <<- paste0(s, cat)
# l <<- nchar(s)
# }
# <bytecode: 0x1074fd4e8>
# <environment: 0x103ca6e08>
#
# $find
# function (pattern)
# return(grepl(pattern, s))
# <bytecode: 0x1076c8470>
# <environment: 0x103ca6e08>
#
# $substitute
# function (pattern, sub)
# {
# s <<- gsub(pattern, sub, s)
# l <<- nchar(s)
# }
# <bytecode: 0x1077ad270>
# <environment: 0x103ca6e08>
So is this style of programming (?) considered OOP or OOP-like? What is the difference of this from S3/S4?
Thanks to @G.Grothendieck, @r2evans and @Jozef. The demo documentation for scoping
in R says "functions can encapsulate state information", because of the scoping rules in R. And the RC system "uses environment", so I think what I did was similar to a primitive RC system.
"An object is data with functions. A closure is a function with data." -- John D. Cook
Closures get their name because they enclose the environment of the parent function and can access all its variables.
In http://adv-r.had.co.nz/Functional-programming.html#closures I found the most proper name for this is a closure.
Aspose.CAD for .NET is the enterprise-grade API that allows various manipulations of CAD or BIM files.
Given that, it's hard to talk about "pure OOP" requiring a single return. I would agree with single return approach because if you write multiple returns and then you come to know that you have to do another processing on the return value then having only one return makes it simple to make that change.
In the case of returning an object by reference, no new object is created, rather a reference to the original object in the called function is returned to the calling function.
c++ - Returning object from function by Dinesh Thakur Category: Classes in C++ A function can also return objects either by value or by reference. When an object is returned by value from a function, a temporary object is created within the function, which holds the return value.
What you are trying to do here reminds me of reference classes
or an alternative implementation of the concept by the R6
package - essentially trying to make a OO system similar to other "classic" OOP languages (e.g. Java):
Reference classes:
R6
For example, you could define an R6 class like so:
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"))
}
)
)
And then one can create an instance from that class:
ann <- Person$new("Ann", "black")
For a quick introduction: https://r6.r-lib.org/articles/Introduction.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With