f <- function() {
x <- 10
if (runif(1) > .5) x else y
}
y <- 5
f()
Hadley
> --
> You received this message because you are subscribed to the Google Groups "Houston R users" group.
> To post to this group, send email to hous...@googlegroups.com.
> To unsubscribe from this group, send email to houston-r+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/houston-r?hl=en.
>
>
--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/
as Ed pointed out, the function will trigger an error each time runif(1)
returns a value <= .5, as x does not get assigned and, therefore, is a
non-existent object. This is actually a very good thing, because it
means R is doing the right thing. To prove your point, you need to make
sure x is defined before calling the function, as below
> f =function() {
+ if (runif(1) > .5)
+ x = 10
+ x
+ }
> y<-7
> x=4
> for (i in 1:10) {
+ y<-f()
+ cat("y=", y, " \n")
+ }
y= 4
y= 10
y= 10
y= 4
y= 10
y= 4
y= 4
y= 4
y= 4
y= 4
This way the function returns the global value when the x is not
assigned inside the function (runif is <= .5) and the local when it is
defined. You are right about this double-standard of R, but you have to
admit that this short function is carelessly coded. You should make sure
that x has a value (for example initializing x at the beginning of the
function, or with an else clause). In fact this function, provided
nobody has assigned a value to the "global" x before calling it, should
trigger the error if the "if" does not succeed (no global value to
return). So you solve your problem not by using unique names for your
variables inside functions and elsewhere in the code, but by making sure
those variables are *always* (not randomly) initialized inside your
function (even a NA - not avalilable - value). See that with this simple
modification (x=NA), the function never returns 4.
> f =function() {
+ x=NA
+ if (runif(1) > .5)
+ x = 10
+ x
+ }
>
> y<-7
> x=4
> for (i in 1:10) {
+ y<-f()
+ cat("y=", y, " \n")
+ }
y= 10
y= NA
y= NA
y= 10
y= NA
y= NA
y= 10
y= NA
y= 10
y= NA
Consider this code
> f =function() {
+ a = r + 3
+ a
+ }
> f()
Error in f() : object 'r' not found
"r" is not assigned a value inside the function, but I pretend to assign
"a" the value of r + 3. It will trigger an error. If now I pre-define r
(globally) before calling the function:
> r=2
> f()
[1] 5
it works. I find it very difficult to blame R for this.
Best
Roberto
I don't think it's a weakness of R - I think it's a strength. This
paper has lots of examples showing how useful lexical scope can be: R.
Gentleman and R. Ihaka. Lexical scope and statistical computing.
Journal of Computational and Graphical Statistics, 9: 491–508, 2000.
Hadley
Best
Roberto
For quite some time now, one of the automated tests run as part of the
package checking process has caught this. See checkUsage() in the
codetools package if you want to do it yourself.
Best
Roberto
As you might imagine, this presents a difficulty in compiling R. ;-)
In fact, a non-trivial part of RCC is devoted to figuring out whether
variable uses are local, global, or ambiguous.
It's interesting to note how Python gets around this problem. In
Python, if there's an assignment to x anywhere in a function, then
it's a local variable throughout the function, whether the assignment
actually happens or not. Translate Bill's example to Python--
import random
def f():
if random.random() > 0.5: x = 10
return x
x = 7
for i in range(10): f()
--and if x is not 10 you get an UnboundLocalError.
John
John