How can I debug efficiently in R if packages are unknown due to lazy evaluation. I would like to keep the basic browser() functionality as it works great - even with the testthat package. As explained in the following post, --with-keep.source is set for my project in "project options => Build Tools".
To reproduce the behavior, create a package TestDebug containing
myfun <- function(a,b) {return(a+b)}
and a script example.R
{
browser()
TestDebug::myfun(1,2)
}
Edit: The situation where TestDebug::myfun(1,2) calls otherpackage::myfun2(1,2) should be also covered. I think the situation should occur in every "real" package?
The following works for me.
I have my package TestDebug with my function
myfun <- function(a,b) {return(a+b)}
If I run the script
debug(TestDebug::myfun)
TestDebug::myfun(1,2)
The debugger steps right into the source of TestDebug::myfun() not into the :: function as it does when you place a browser() before the call to TestDebug::myfun(1,2).
As you mention in your question: in real-life situations TestDebug::myfun(1,2) often calls otherpackage::myfun2(1,2). If you try to step into otherpackage::myfun2(1,2) you will end up inside the :: function again.
To prevent this I add this functions called inside other functions to the debug index on the fly:
As soon as you are on the line inside TestDebug::myfun() where otherpackage::myfun2(1,2) is called I run debug(otherpackage::myfun2(1,2)) in the console. After that I can step into otherpackage::myfun2(1,2) without problems and end up in the source code of otherpackage::myfun2(1,2). (..and not in the source code of ::)
Don't forget to call undebug(otherpackage::myfun2(1,2)) after you're sure that your problem is not inside otherpackage::myfun2(1,2) to prevent the debugger to jump into otherpackage::myfun2(1,2) the next time it is called.
If you prefer you can also use debugonce(otherpackage::myfun(1,2)) (instead of debug(..)) to only debug a function once.
Related
I am working on a package and currently it has a lot of functions. Inorder to load them every time I open up RStudio, I use this line of code from devtools:
library(devtools)
suppressMessages(load_all("~/Codes/package1/"))
It works fine, but the problem is whenever I change a function that has been used in another function, R doesn't recognize the changes.
For Example if I have:
func1 <- function() {
print("version1")
}
func2 <- function() {
func1()
}
And then change func1 to print("Vesion2"), rerun it and then run func2, it would still print version1 for me.
Anyone knows whats the problem and how can I solve it?
The devtools load_all function simulates loading a package. All functions from a package are stored in a package namespace. Functions remember what namespace they come from via their environment().
Any code you run in the console runs in the global environment. So when you run
func1 <- function() {print("version2")}
you are creating a new function called func1 in your global environment but the func1 from the package namespace is still there. You've created a "shadow" function that masks the original function.
When you got to run func2 which is still in the package namespace, it sees a call to a function named func1. When it goes to look for this function, it looks first in it's own namespace due to R's lexical scoping rules. It finds the original funct1 and not the one you created in the global environment so it runs that.
Packages generally aren't meant to have their functions swapped or altered after they are loaded. You would save to save the source and call load_all to reload that folder as a package with the new changes. If you aren't really trying to simulate a package, importing functions with source() will not create a new namespace and would therefore be easier to edit after import.
I'm writing a package and as I add more functions to it, running the check() function is taking more and more time to run. This is fine if I am checking a whole new function or set of functions I've written, but if I'm only fixing something minor from the previous instance of check() its rather time consuming. Is there a way to only do a partial check of the error, warning, or note that was thrown or should I just work on my patience?
I have a user defined function in R
blah=function(a,b){
something with a and b
}
is it possile to put this somewhere so that I do not need to remember to load in the workspace every time I start up R? Similar to a built in function like
summary(); t.test(); max(); sd()
You can put the function into your .rprofile file.
However, be very careful with what you put there, since it essentially makes your code non-reproducible — it now depends on your .rprofile:
Let’s say you have an R code file performing some analysis, and the code uses the function blah. Executing the code on any other system will fail due to the non-existence of the blah function.
As a consequence, this file should only contain system-specific setup. Don’t define helper functions in there — or if you do, make them defined only in interactive sessions, so that you have a clear environment when R is running a non-interactive script:
if (interactive()) {
# Helper functions go here.
}
And if you find yourself using the same helper functions over and over again, bundle them into packages (or modules) and reuse those.
I have a main R script which does a multiplication using a function called Multiply().
debugSource("C:/Users/R_debug_breakpoint/myFunction.R")
a<-1
b<-2
mult<-Multiply(a,b)
I write Multiply() in a different R script called "myFunction.R"
"myFunction.R" looks like this:
Multiply<-function(a,b){
c<-a+b
e<-a/b
d<-a*b
return(d)
}
If I want to set a breakpoint inside Multiply() function at the line:
d<-a*b and enter source mode to see what the value of c,e.
However, when I press Source option in my main.R, the debugger does not halt at the breakpoint I set inside the Muliply function. It just runs all the codes in main.R.
I search this problem in many webpages, and the most close one is
How to set a breakpoint in function body in R-studio?
However, I use debugSource here but it still fails.
Another blog about the breakpoint I found out useful is:
https://support.rstudio.com/hc/en-us/articles/200534337-Breakpoint-Troubleshooting
It says:In order to hit breakpoints during sourcing, you need to use the special debug sourcing command debugSource included in RStudio. If you are calling source manually on your file, breakpoints will still work, but will not be enabled until after all the code in the file has been executed.
I think this is reason why it doesn't work, but it doesn't mention a work around for it.
Much appreciated if any help from you guys.
I want R to load a certain file on initialization, so naturally I added a source command to my Rprofile so:
.First <- function()
{
cat("\n Welcome to R MotherFnorder!!!\n\n")
setwd("/home/username/Code/R/")
source("/home/username/Code/R/file.R")
}
But now when I start R it throws a 'function not found' error for default functions like runif or rnorm. When I load the same file manually into the workspace I get no errors.
You don't need (or, really, want) to create a .First . If you put those lines into your .Rprofile they'll execute just fine. -- With the proviso #Pascal pointed out, that any function called in your file.R must have its library loaded first. So,
near the bottom of your .Rprofile, just put
library(whatever_packages_needed)
cat("\n Welcome to R MotherFnorder!!!\n\n")
setwd("/home/username/Code/R/")
source("/home/username/Code/R/file.R")
EDIT: I cannot reproduce your problem. I added these lines to the end of my .Rprofile:
#testing SO problem with libloading
library(stats)
runif(10)
And the console returns ten nice numbers.
The reason for the error is that when .First() the packages are not yet loaded.
Although runif and rnorm might seem like default functions, they are actually part of the stats package. And as such, they are NOT available when .First() is called (unless you specifically call that package from within .First)
... which also explains this:
When I load the same file manually into the workspace I get no errors.
After .First() but before you have the chance to run anything manually, the default packages are attached. And hence available to your functions when you call it manually.
The solution is to create a file (if it does not already exist) called
"~/.Rprofile" and put in there the lines you currently have in .First()