Longtime OOP developer here spinning up on R and R6. I'm used to having namespaces to hold the classes (e.g., Geom::Point, Vital::BloodPressure). I haven't found a way to do that in R. I'm not building a package but I'm not against it if that is the solution.
2 Answers
The usual way to do this is to put your class(es) in a package. Base R infrastructure knows nothing about R6, so you'll definitely want to use roxygen2
to handle the documentation for the classes and methods.
The package always defines a namespace, and you can refer to objects exported from it as pkgname::objectname
. While debugging, you can also refer to internal objects that are not exported from the namespace, using pkgname:::objectname
(i.e. three colons). Don't do that in the published version of the package. Neither of those qualifiers is necessary for functions/methods defined within the package. That's all standard R scoping. R6 also has its own rules.
Edited to add:
In the comments you said a motivation was this:
In Ruby I have "Lib1" and "Lib2" as namespaces with Lib1::DoSomething and Lib2:PrintTheThing
Those are likely too closely related to want to put them in separate packages, so in R they likely wouldn't be in separate namespaces. I assume the point of Lib1
and Lib2
is to isolate local helper functions. In R, one way to do that is to define the helpers within the main functions, e.g.
DoSomething <- function(...) {
var1 <- "var1 at top level"
Helper1 <- function(...) {
cat("I can see", var1, "\n")
var1 <- "local value" # Has no effect at the top level
}
Helper2 <- function(...) {
cat("I can modify var1:\n")
var1 <<- "modified var1" # Changed at the top level
}
Helper1(...)
Helper2(...)
}
Scoping rules in R mean that the two helpers have read access to all local variables in DoSomething
, and can modify values there using the <<-
"super-assignment" operator.
Some people don't like this style, and some tools don't support it properly. For example, RStudio can't set breakpoints in the local functions. (This is despite the fact that the base function utils::setBreakpoint
can do so.)
The base debug()
function only works on the local functions
if you run it within DoSomething
after they have been created: the definitions are executable code, not declarations.
One more addition:
Another difference between R and some other languages is the fact that ::
is an executable operator, it's not just a declaration of where to look for a variable. Once you realize that, you'll realize that the $
operator gives another way to fake a namespace. You create an environment, and put your functions into that environment. If you do it properly, they can see each other.
And for yet another way to do it, you can use the local()
function to create hidden functions. For example, the code above could have been written like this:
Lib1 <- local({
var1 <- "var1 at top level"
Helper1 <- function(...) {
cat("I can see", var1, "\n")
var1 <- "local value" # Has no effect at the top level
}
Helper2 <- function(...) {
cat("I can modify var1:\n")
var1 <<- "modified var1" # Changed at the top level
}
DoSomething <- function(...) {
Helper1(...)
Helper2(...)
}
environment() # This captures the definitions above
})
# Now call it using
Lib1$DoSomething(...)

- 37,248
- 4
- 43
- 90
-
Can't you also create a standalone namespace as well? https://stackoverflow.com/q/47941426/2954547 – shadowtalker Mar 04 '23 at 17:37
-
@shadowtalker: R is very flexible so you can redefine a lot of things, but I'd recommend against doing stuff that is too esoteric. Packages are easy and there's a ton of support for them. – user2554330 Mar 04 '23 at 17:39
-
I might be inferring too much about the question, but they might be looking for something like a namespace as a standalone "thing" that could be part of a package. In Python you might use a submodule for this. In Lisp you would put a dot or slash in the package name as convention to indicate some kind of membership or containment. R packages tend to have very "flat" namespaces in my experience. – shadowtalker Mar 04 '23 at 17:46
-
@shadowtalker hit the nail on the head - that is exactly my mindset (although I may need to alter my mind :) ) In Ruby I have "Lib1" and "Lib2" as namespaces with Lib1::DoSomething and Lib2:PrintTheThing – Michael Lee Squires Mar 04 '23 at 19:33
-
Added something kind of like the Ruby example. – user2554330 Mar 04 '23 at 20:28
Consider using the box
package available on CRAN. You can find the GitHub here or view the author's website documentation here
It allows you to turn basic R scripts into modules - effectively namespacing the code. It sounds like this is what you may want. You will need to use very simple roxygen2
syntax to get it to work.

- 1,981
- 7
- 9