2

Criteria for answer to this question

Given the following function (within its own script)

# something.R
hello <- function(x){
    paste0("hello ", x)
}

What is the most minimal amount of setup which will enable the following

library(something)
x <- something::hello('Sue')
# x now has value: "hello Sue"

Context

In python it's very simple to have a directory containing some code, and utilise it as

# here foo is a directory
from foo import bar
bar( ... ) 

I'm not sure how to do something similar in R though.

I'm aware there's source(file.R), but this puts everything into the global namespace. I'm also aware that there's library(package) which provides package::function. What I'm not sure about is whether there's a simple approach to using this namespacing within R. The packaging tutorials that I've searched for seem to be quite involved (in comparison to Python).

baxx
  • 3,956
  • 6
  • 37
  • 75
  • Have you tried this http://r-pkgs.had.co.nz/namespace.html? – Eric Hua Aug 31 '20 at 01:17
  • For a basic package all you need, if you use RStudio, is new project/create package. Then add your functions, and document, build and install from the right side panel. – moodymudskipper Aug 31 '20 at 01:24
  • you can use `sys.source` to load it it an environment – user20650 Aug 31 '20 at 01:28
  • @user20650 this will provide me with something such as `sys.source(foo); foo::bar()` ? – baxx Aug 31 '20 at 01:29
  • @EricHua that does not seem to be a clear answer to the question, is that as basic as it gets? – baxx Aug 31 '20 at 01:29
  • @Moody_Mudskipper build? I need to compile things before importing with R? – baxx Aug 31 '20 at 01:30
  • 1
    @baxx; `sys.source("something.R", envir = something<-new.env()); something$hello("Sue")` – user20650 Aug 31 '20 at 01:30
  • @user20650 here is it necessary that `something.R` is in same dir as `getwd()` ? – baxx Aug 31 '20 at 01:33
  • @baxx; not necessary but you will need to use the full path to your something.r script – user20650 Aug 31 '20 at 01:34
  • https://stackoverflow.com/questions/39620669/source-script-to-separate-environment-in-r-not-the-global-environment, https://stackoverflow.com/questions/55521517/how-to-import-an-r-file-and-assign-an-alias-to-it-like-import-myfile-r-as-mf/55524674#55524674 – user20650 Aug 31 '20 at 01:36
  • 1
    @user20650 I was interested in the minimal amount of code necessary in order to use the `script::function()` syntax, and would still like to see that. However, `sys.source` is definitely useful and probably solves the immediate problem for me, thank you. – baxx Aug 31 '20 at 01:39
  • good, but @baxx; I would second Moodys suggestion of building a package ... it really is quite easy to do – user20650 Aug 31 '20 at 01:40
  • Coming from python it's pretty confusing though, I can build a package for pypi or just something local (without setup etc). With R it seems that it's all or nothing? Talking about building things and stuff feels overkill for what I had in mind, I was expecting a directory and one or two scripts at most. Which is the reason for this question I guess – baxx Aug 31 '20 at 01:43
  • 1
    Either you source a file with source() , or you create a package. You don't import and namespace files in R. But creating a package is easy, and it's really not worth trying to work around it. – moodymudskipper Aug 31 '20 at 01:45
  • 1
    If I'm understanding correctly - creating a package is easy, but too verbose to paste into a stackoverflow answer – baxx Aug 31 '20 at 01:47
  • 1
    You think it's overkill because you didn't try it, but I assure you your package with the function above is 40 seconds of work – moodymudskipper Aug 31 '20 at 01:47
  • I'll just use sys for now then, I'll leave this open in-case anyone provides a solution in future. Thanks – baxx Aug 31 '20 at 01:51

2 Answers2

3

I don't know if there is a real benefit in creating a namespace just for one quick function. It is just not the way it is supposed to be (I think).

But anyway here is a rather minimalistic solution:

First install once: install.packages("namespace")

The function you wanted to call in the namespace:

hello <- function(x){
  paste0("hello ", x)
}

Creating your namespace, assigning the function and exporting

ns <- namespace::makeNamespace("newspace")
assign("hello",hello ,env = ns)
base::namespaceExport(ns, ls(ns))

Now you can call your function with your new namespace

newspace::hello("you")
Steffen Moritz
  • 7,277
  • 11
  • 36
  • 55
3

Here's the quickest workflow I know to produce a package, using RStudio. The default package already contains a hello function, that I overwrote with your code.

Notice there was also a box "create package based on source files", which I didn't use but you might.

enter image description here

A package done this way will contain exported undocumented untested functions.

If you want to learn how to document, export or not, write tests and run checks, include other objects than functions, include compiled code, share on github, share on CRAN.. This book describes the workflow used by thousands of users, and is designed so you can usually read sections independently.


If you don't want to do it from GUI you can useutils::package.skeleton() to build a package folder, and remotes::install_local() to install it :

Reproducible setup

# create a file containing function definition

# where your current function is located
function_path <- tempfile(fileext = ".R")
cat('
hello <- function(x){
  paste0("hello ", x)
}
', file = function_path)

# where you store your package code
package_path <- tempdir()

Solution :

# create package directory at given location
package.skeleton("something", code_file = file_path, path = package_path)
# remove sample doc to make remotes::install_local happy
unlink(file.path(package_path, "something", "man/"), TRUE) 
# install package
remotes::install_local(file.path(package_path, "something"))
moodymudskipper
  • 46,417
  • 11
  • 121
  • 167