I written an R package, and now a collaborator (recent CS grad who is new to R) is editing and refactoring the code. In the process, he is dividing up my functions into smaller, more generic functions.
What he is doing makes sense, but when I started with package.skeleton()
, I had one file per function. Now, he has added functions on which the primary function depends, but that may have limited use outside the function itself.
He suggests that all the functions go into a single file, but I am against that because it is easier to do version control when we work on different files.
I have since started using roxygen to document each function within the text.
What is the recommended way to handle functions: clearly the helper functions should stay with the the main function, but to what extent do I need to document helper functions?
The @export
suggestion in the comments is helpful, but I am curious to know how others organize their code.
Use the help() command To find information for a particular function, such as the function print, type help('print') on the R command line and press enter (I recommend using quotes whenever you use this command, but there are some special cases when they are unnecessary).
A "helper function" is a function you write because you need that particular functionality in multiple places, and because it makes the code more readable. A good example is an average function. You'd write a function named avg or similar, that takes in a list of numbers, and returns the average value from that list.
Generally, the most important things should come first, with less important things later. In a class this means that the members and the constructor should come first, followed by public methods that make up the API of the class. After that, (private) helpers are listed.
You should not nest it, because otherwise the nested function will be re-created every time you call the outer function. Show activity on this post. Since function B isn't used anywhere else you might as well just make it an inside funtion within function A because that's the only reason why it exists.
I cut up my functions under two conditions :
I do include the so-called helper functions in the file of the main function, but only as long as those helper functions are not used in any other function. Actually, I consider them nested within the main function. I do understand your argument for version control, but changing the helper function comes down to changing the performance of the main function, so I see no problem in keeping them in the same file.
Some helper functions might be used in different other functions, and then I save them in their own file. Often I do export those functions, as they might be of interest for the user. Compare this to eg lm
and the underlying lm.fit
, where advanced users could make decent use of lm.fit
for speeding up code etc.
I use the naming convention used in quite some packages (and derived from linux), by preceding every "hidden" function by a dot. So that makes
.helper.function <- function(x, ...){ ... some code ... } main.function <- function(x, ...){ ...some code, including .helper.function(y, ...) }
I explicitly @export all functions that need exporting, never the helper functions. It's not always easy to judge whether a function might be of interest to an end user, but in most cases it's pretty clear.
To give an example : A few lines of code to cut off NA lines I consider a helper function. A more complex function to convert the dataset to the correct format I export and document.
YMMV
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