Skip to content

'require' equivalent for local functions

6 messages · Gabor Grothendieck, Wacek Kusnierczyk, Duncan Murdoch +2 more

#
Hello everyone,

I often create some local "libraries" of functions (.R files with only  
functions in them) that I latter call. In scripts that call a function  
from such library, I would like to be able to test whether the  
function is already known in the namespace and, only if it is not,  
source the library file. I.e. what `require` does for packages, I want  
to do with my local functions.

Example:
lib.R
	foo <- function(x) { x*2 }

script.R
	require.local(foo,"lib.R")
	# that searches for function "foo" and, if not found, executes  
source("lib.R")
	foo(2)

Obviously, I want the test to be quite efficient otherwise I might as  
well source the local library every time. I am aware that it would  
probably not be able to check for changes in lib.R (i.e. do  
complicated things such as re-source lib.R if foo in the namespace and  
foo in lib.R are different), but that I can handle manually.

This seems like a common enough workflow but I cannot find a pre- 
existing solution. Does anyone have pointers?

Otherwise I tried to put that together:

require.local <- function(fun, lib)
#
#	Searches for function "fun" and sources "lib" in
#	case it is not found
#
{
	if (! (deparse(substitute(fun)) %in% ls(".GlobalEnv") && class(fun)  
== "function") ) {
		cat("Sourcing", lib,"...\n")
		source(lib)
	}
}

but I am really not confident with all those deparse/substitute things  
and the environment manipulation, so I guess there should be a better  
way.

JiHO
---
http://jo.irisson.free.fr/
#
Try this:

if (!exists("myfun", mode = "function")) source("myfile.R")

Also check the other arguments of exists in case you want to
restrict the search.
On Sun, Mar 22, 2009 at 5:05 PM, JiHO <jo.lists at gmail.com> wrote:
#
JiHO wrote:
perhaps

    find(deparse(substitute(fun)), mode='function')

but note that this will *not* tell you whether *the* function you want
to import is already known, but rather whether *some* function with the
specified name is already known.

vQ
#
On 22/03/2009 5:05 PM, JiHO wrote:
That's pretty hard to make bulletproof.  Why not just put those 
functions in a package, and use that package?  If the functions are all 
written in R, creating the package is very easy:  see package.skeleton. 
  (And if you have a perfect memory and don't plan to distribute the 
package to anyone, you can skip documenting the functions:  then it's 
almost no work at all.)

Duncan Murdoch
#
I agree with Duncan.  I used to do exactly what you did - source()ing data
files inside a wrapper not unlike C #define wrappers, but it became a
headache with more files and the files began looking more cluttered.

It has taken me several days to learn about how create a package properly,
along with package RUnit for unit-testing, and with documentation.  The "R
Extensions" file is often a good source of information.  Be sure you find
information about Rcmd install and Rcmd check, which are also very useful. 
prompt() can help you build your .Rd (help files).  Alternatively, you may
use Rdoc$compile() (from package R.oo) if you intend to embed your
Rdoc-style comments inside your R code, as I do.  I also use R.oo as a more
traditional object-oriented alternative to S3/S4.  Once set-up, you can
automagically generate .pdf files and .chm (windows-based help) for your
package.  Help for my own package has helped me keep my code consistent,
clean, and re-factorable.  Best of all, you can use put require( my.package
) or data( my.data) and voila.

It has been a bit of a learning curve, but the packaging facilities in R are
actually very well developed.  Once set-up, maintenance becomes less of a
chore.  Good luck.
Duncan Murdoch-2 wrote:
#
Thanks very much to everyone. I think I will use a combination of both  
techniques.
On 2009-March-22 , at 20:08 , Duncan Murdoch wrote:

            
I know it will be impossible to make bullet proof and efficient at the  
same time. However, my functions are pretty specific to each project,  
have long names and do not collide with variable names (because I use  
dots in function names but camel case in variable names) so just  
looking for the name should be OK. Plus I have a simple keyboard  
shortcut in my text editor to source the current file in the currently  
R session, so it will be easy to re-source some files after I modify  
them.

On the other hand I have a bundle of general enough functions that I  
import in many projects (http://github.com/jiho/r-utils/ for those  
that might be interested in netCDF data handling, 2D arrow fields and  
ggplot2 stuff) and this one is a good candidate to be turned into a  
package.

So thanks again to everyone. Sincerely,

JiHO
---
http://jo.irisson.free.fr/