[R] printing a generated function crashes R
Gabor Grothendieck
ggrothendieck at gmail.com
Tue Sep 19 14:39:12 CEST 2006
You could alternately use substitute:
make.function2 <- function() {
fun <- function(x, y) x*y+z
body(fun) <- do.call(substitute, list(body(fun), list(z = 1)))
fun
}
ff <- make.function2()
ff(3,2) # 7
On 9/19/06, Mstislav Elagin <elagin at wias-berlin.de> wrote:
> Peter Dalgaard wrote:
> > Mstislav Elagin <elagin at wias-berlin.de> writes:
> >
> >> Dear All,
> >>
> >> the last expression in the following code snippet crashes R (version
> >> 2.3.1 on Windows XP) when run interactively:
> >>
> >> make.bad.function <- function(kind)
> >> {
> >> zz <- switch(kind,
> >> "1" = 1,
> >> "2" = 2)
> >>
> >> stopifnot( !is.null(zz) )
> >>
> >> eval( bquote( function(x)
> >> {
> >> x + .(zz)
> >> }))
> >> }
> >>
> >> # bad.function <- make.bad.function("5") ## error as expected
> >>
> >> bad.function <- make.bad.function("1")
> >> print(bad.function(10)) ## -> 11
> >>
> >> bad.function <- make.bad.function("2")
> >> print(bad.function(10)) ## -> 12
> >>
> >> bad.function ## this works if the code is source()'d
> >> print(bad.function) ## oops!
> >>
> >> However, it does work (i.e. prints the body of bad.function) if run
> >> non-interactively
> >> (R --vanilla < bad-function.R).
> >>
> >> Any ideas why this happens?
> >
> > Well, bquote seems to be doing nasty things if passed an expression with a
> > function inside:
> >
> >> f <- bquote(function(x) {
> > + x + 1
> > + }
> > + )
> >> f
> > function(x) {
> > x + 1
> > }
> >> eval(f)
> > À
> > ÈH~
> >
> > ÈH~
> >
> > Program received signal SIGSEGV, Segmentation fault.
> >
> >
> > I think the story is that the source attribute is getting messed up.
> >
> >> z <- eval(f)
> >> attr(z,"source")
> > "function(x) {"("x+1}")
> >> z
> > ÈX~
> > ÈX~
> > ..poof..
>
> Hallo,
>
> after having played a bit more, I found out that the reason is not, or
> at least not only the source attribute.
>
> If we try to construct a function of more than one argument in the same
> way as a function of no or one argument, we get an error message:
>
> make.bad.function <- function()
> {
> zz <- 1
>
> eval( bquote( function(x, y)
> {
> x*y + .(zz)
> }))
> }
>
> bad.fun <- make.bad.function()
>
> > Error in eval(expr, envir, enclos) : invalid formal argument list for
> > "function"
>
> However, if, following an older post by Brian Ripley, we specify the
> list of formal arguments explicitly, everything works fine (albeit looks
> uglier):
>
> make.function <- function()
> {
> zz <- 1
> fun <-
> eval( bquote( function()
> {
> x*y + .(zz)
> }))
> formals(fun) <- alist(x=, y=)
> return(fun)
> }
> fun <- make.function()
> fun(3, 2) ## -> 7
>
> Printing the function works, too:
>
> fun
>
> > function (x, y)
> > {
> > x * y + 1
> > }
> > <environment: 01A5884C>
>
> My earlier example with the function of one argument works fine when
> rewritten in the same spirit.
>
> In my opinion, bquote behaves "inhomogeneously" in the sense that the
> definition of the functions taking no of one params differs from that of
> the functions taking more params. I wonder whether such behaviour of
> bquote is a bug and should be reported.
>
> Have a nice day
> Mstislav Elagin
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
More information about the R-help
mailing list