[R] printing a generated function crashes R
Mstislav Elagin
elagin at wias-berlin.de
Tue Sep 19 09:37:46 CEST 2006
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
More information about the R-help
mailing list