[Rd] function can permanently modify calling function via substitute?
Peter Dalgaard
p.dalgaard at biostat.ku.dk
Wed Sep 24 07:54:11 CEST 2008
Perry de Valpine wrote:
> Dear R-devel:
>
> The following code seems to allow one function to permanently modify a
> calling function. I did not expect this would be allowed (short of
> more creative gymnastics) and wonder if it is really intended. (I can
> see other ways to accomplish the intended task of this code [e.g. via
> match.call instead of substitute below] that do not trigger the
> problem, but I don't think that is the point.)
>
> do.nothing <- function(blah) {force(blah)}
>
> do.stuff.with.call <- function(mycall) {
> raw.mycall <- substitute(mycall); # expected raw.mycall would be local
> print( sys.call() )
>
> # do.nothing( raw.mycall ); # See below re: commented lines.
> # .Call( "showNAMED", raw.mycall[[2]] )
>
> force( mycall ); # not relevant where (or whether) this is done
> raw.mycall[[2]] <- runif(1); # permanently modifies try.me on the
> first time only
>
> # .Call( "showNAMED", raw.mycall[[2]] )
>
> raw.mycall
> }
>
> gumbo <- function(x) {
> writeLines( paste( "gumbo : x =" , x ) )
> return(x);
> }
>
> try.me <- function() {
> one.val <- 111;
> one.ans <- do.stuff.with.call( mycall = gumbo( x = one.val ) );
> one.ans
> }
>
> # after source()ing the above:
>
>> deparse(try.me)
>>
> [1] "function () "
> [2] "{"
> [3] " one.val <- 111"
> [4] " one.ans <- do.stuff.with.call(mycall = gumbo(x = one.val))"
> [5] " one.ans"
> [6] "}"
>
>> try.me()
>>
> do.stuff.with.call(mycall = gumbo(x = one.val))
> gumbo : x = 0.396524668671191
> gumbo(x = 0.396524668671191)
>
>> deparse(try.me)
>>
> [1] "function () "
> [2] "{"
> [3] " one.val <- 111"
> [4] " one.ans <- do.stuff.with.call(mycall = gumbo(x = 0.396524668671191))"
> [5] " one.ans"
> [6] "}"
>
>> try.me()
>>
> do.stuff.with.call(mycall = gumbo(x = 0.396524668671191))
> gumbo : x = 0.396524668671191
> gumbo(x = 0.0078618151601404)
>
>> deparse(try.me)
>>
> [1] "function () "
> [2] "{"
> [3] " one.val <- 111"
> [4] " one.ans <- do.stuff.with.call(mycall = gumbo(x = 0.396524668671191))"
> [5] " one.ans"
> [6] "}"
>
> So, after the first call of try.me(), do.stuff.with.call has
> permanently replaced the name one.val in line 2 of try.me with a
> numeric (0.396...). Subsequent calls from try.me to
> do.stuff.with.call now reflect that change, but do.stuff.with.call
> does not modify the try.me object again. (Note this means one needs to
> keep reloading try.me to investigate).
>
> If this is a problem worth investigating, here are a couple of other
> observations that may be relevant but are obviously speculative.
>
> 1. If the third line of do.stuff.with.call is uncommented (and try.me
> also reloaded), the unexpected behavior does not occur. Since
> do.nothing is eponymous, I was surprised because I believed it should
> not impact any other behavior. Speculating with limited knowledge, I
> thought this might implicate something that is supposed to stay
> under-the-hood, such as the "`call by value' illusion" described in
> the "R internals" documentation.
>
> 2. Poking slightly further, I looked at the NAMED values using this C
> code via R CMD SHLIB and dyn.load:
> #include "R.h"
> #include "Rdefines.h"
> SEXP showNAMED(SEXP obj) {
> Rprintf("%i\n", NAMED(obj));
> return(R_NilValue);
> }
> Uncommenting the .Call lines in do.stuff.with.call (with the
> do.nothing line re-commented) reveals that on the first time
> do.stuff.with.call is called from try.me, raw.mycall[[2]] has NAMED ==
> 1 both before and after the `[[<-` line. On subsequent calls it has
> NAMED == 2 before and NAMED == 1 after. If I follow how NAMED is
> used, this seems relevant.
>
>
Yes and no. This does sound like a bug and NAMED is likely involved, but
I don't think raw.mycall[[2]] is the thing to look at. More likely, the
issue is that raw.mycall[ itself has NAMED == 1 because otherwise [[<-
assignment would duplicate it first. This suggests that substitute has
the bug.
--
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
More information about the R-devel
mailing list