Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a list of functions, is this considered an OOP?

Tags:

r

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.

like image 892
Lytze Avatar asked Dec 31 '18 09:12

Lytze


People also ask

What is a function in OOP?

Aspose.CAD for .NET is the enterprise-grade API that allows various manipulations of CAD or BIM files.

Do you prefer single return or multiple returns in OOP?

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.

What happens when a function returns an object by reference?

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.

How to return an object from a function in C++?

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.


Video Answer


1 Answers

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:

  • https://www.rdocumentation.org/packages/methods/versions/3.5.1/topics/ReferenceClasses

R6

  • https://github.com/r-lib/R6/blob/master/README.md

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

like image 197
Jozef Avatar answered Oct 16 '22 23:10

Jozef