[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