Full_Name: Robert Denham Version: R-2.4.1 OS: Windows Xp Submission from: (NULL) (61.88.57.1) R gui exits without warning when I run a function which has an argument with a default that is not found. This was a result of an error in a function I wrote, but I thought that it should exit more gracefully than it does. Here is an example: testfun <- function(aa=aa) { aa <- lm(y~x,data=aa) return(aa) } testfun() #R then exits. Note that testfun <- function(aa=bb) { aa <- lm(y~x,data=aa) return(aa) } works as it should, giving "object bb not found".
The problem is rather that 'aa' *is* found: default arguments are looked for within the body of the function, and so the calculation of 'aa' is recursive. Consider the simpler case> testfun <- function(aa=aa) {aa <- c(aa); aa} > testfun()Error in testfun() : recursive default argument reference On Linux I got> testfun() #R then exits.Error: segfault from C stack overflow Now C stack overflows are instantly fatal on Windows and cannot be caught there. However, using Linux enabled me to locate the loop in a debugger, and it is recursion in isMissing to which I have added a stack check. The remedy is I hope obvious: 'don't do that'. Adding these checks do have a small but measurable performance cost so we have been conservative in adding them. On Thu, 21 Dec 2006, robert.denham at nrm.qld.gov.au wrote:> Full_Name: Robert Denham > Version: R-2.4.1 > OS: Windows Xp > Submission from: (NULL) (61.88.57.1) > > > R gui exits without warning when I run a function which has an argument with a > default that is not found. > > This was a result of an error in a function I wrote, but I thought that it > should exit more gracefully than it does. Here is an example: > > > testfun <- function(aa=aa) { > aa <- lm(y~x,data=aa) > return(aa) > } > > testfun() #R then exits. > > Note that > > testfun <- function(aa=bb) { > aa <- lm(y~x,data=aa) > return(aa) > } > > works as it should, giving "object bb not found". > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
robert.denham at nrm.qld.gov.au wrote:> Full_Name: Robert Denham > Version: R-2.4.1 > OS: Windows Xp > Submission from: (NULL) (61.88.57.1) > > > R gui exits without warning when I run a function which has an argument with a > default that is not found. > > This was a result of an error in a function I wrote, but I thought that it > should exit more gracefully than it does. Here is an example: > > > testfun <- function(aa=aa) { > aa <- lm(y~x,data=aa) > return(aa) > } > > testfun() #R then exits. > > Note that > > testfun <- function(aa=bb) { > aa <- lm(y~x,data=aa) > return(aa) > } > > works as it should, giving "object bb not found". > >This seems reproducible on Linux, except that it goes into an infinite loop. The lm call seems to be the real culprit: > testfun <- function(aa=aa) return(aa) > testfun() Error in testfun() : recursive default argument reference > testfun <- function(aa=aa) lm(x~y,data=aa) > testfun() (*poof*)> ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >
On Thu, 21 Dec 2006, Peter Dalgaard wrote: [...]> This seems reproducible on Linux, except that it goes into an infinite > loop. The lm call seems to be the real culprit: > > > testfun <- function(aa=aa) return(aa) > > testfun() > Error in testfun() : recursive default argument reference > > testfun <- function(aa=aa) lm(x~y,data=aa) > > testfun() > (*poof*)The difference is in argument evaluation between closures and internal functions (c() in my example, return() in yours). -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Prof Brian Ripley wrote:> On Thu, 21 Dec 2006, Peter Dalgaard wrote: > > [...] > > >> This seems reproducible on Linux, except that it goes into an infinite >> loop. The lm call seems to be the real culprit: >> >> >>> testfun <- function(aa=aa) return(aa) >>> testfun() >>> >> Error in testfun() : recursive default argument reference >> >>> testfun <- function(aa=aa) lm(x~y,data=aa) >>> testfun() >>> >> (*poof*) >> > > The difference is in argument evaluation between closures and internal > functions (c() in my example, return() in yours). >Er? I'd rather say that the issue is in the semantics of missing():> f <- function(x) missing(x) > testfun <- function(aa=aa) f(aa) > testfun()Error: segfault from C stack overflow which is a bit nasty. AFAICS the thing is that the logic for detection of recursive arguments works by forcing promises (if you at some point need the result of the same promise you are forcing, you know that something is wrong), but missing() tries hard not to force promises. We already have the following anomaly,> g <- function(v) missing(v) > f <- function(v) g(v) > f()[1] TRUE> f <- function(v=!h, h=!v) g(v) > f()[1] FALSE> f <- function(v=!h, h) g(v) > f()[1] FALSE so the fix could be to realize that we cannot detect missingness in a perfectly reliable way and just pretend that arguments are always non-missing when they have a default. [r-bugs reinserted as cc:] -- O__ ---- Peter Dalgaard ?ster Farimagsgade 5, Entr.B c/ /'_ --- Dept. of Biostatistics PO Box 2099, 1014 Cph. K (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk) FAX: (+45) 35327907