Anonymous user
Scope modifiers: Difference between revisions
→{{header|R}}: substantially expanded discussion
(→{{header|R}}: substantially expanded discussion) |
|||
Line 475:
=={{header|R}}==
In R, functions use lexical scope: a function acquires its parent
scope at the time of definition, and each invocation creates a new
local environment within that parent scope. Variable lookup during
evaluation starts in the function's local environment and proceeds
up the chain of parent environments.
<lang R>X <- "global x"
f <- function() {
print(x) #"local x"
}
f() #prints "local x"
attach() will attach an environment or data set to the chain of
enclosing environments.
<lang R>d <- data.frame(a=c(2,4,6), b = c(5,7,9))
attach(d)
b - a #success
detach(d)
b - a #produces error</lang>
Assignment using <- or -> by default happens in the local
(innermost) environment. The <<- and ->> operators assign a
variable in the innermost enclosing scope in which that variable is
already defined, or the global environment if no enclosing
definition is found.
<lang R>x <- "global x"
print(x) #"global x"
local({ ## local({...}) is a shortcut for evalq({...}, envir=new.env())
## and is also equivalent to (function() {...})()
x <- "outer local x"
print(x) #"outer local x"
x <<- "modified global x"
print(x) #"outer local x" still
y <<- "created global y"
print(y) #"created global y"
local({
## Note, <<- is _not_ a global assignment operator. If an
## enclosing scope defines the variable, that enclosing scope gets
## the assignment. This happens in the order of evalution; a local
## variable may be defined later on in the same scope.
x <- "inner local x"
print(x) #"inner local x"
x <<- "modified outer local x"
print(x) #"inner local x"
y <<- "modified global y"
print(y) #"modified global y"
y <- "local y"
print(y) #"local y"
##this is the only way to reliably do a global assignment:
assign("x", "twice modified global x", globalenv())
print(evalq(x, globalenv())) #"twice modified global x"
})
print(x) #"modified outer local x"
})
print(x) #"twice modified global x"
print(y) #"modified global y"</lang>
However, the scope and other aspects of evaluation can be
explicitly manipulated at runtime. assign() and eval(), for
instance, allow you to specify where an evaluation or assignment is
to take place. parent.env() returns the lexically enclosing scope,
while parent.frame() returns the immediate scope of the calling
function.
<lang R>x <- "global x"
f <- function() {
cat("Lexically enclosed x: ", x,"\n")
cat("Lexically enclosed x: ", evalq(x, parent.env(sys.frame())),"\n")
cat("Dynamically enclosed x: ", evalq(x, parent.frame()),"\n")
}
local({
x <- "local x"
f()
})</lang>
A function's arguments are not evaluated until needed; the function
may change the evaluation rules for expressions given to its arguments
by capturing its quoted argument via substitute() and evaluating it in a different
environment. For instance, with() evaluates its second argument in the environment
defined by its first argument, enclosed within the current scope.
<lang R>d <- data.frame(a=c(2,4,6), b = c(5,7,9))
also <- c(1, 0, 2)
with(d, mean(b - a + also)) #returns 4
## with() is built in, but you might have implemented it like this:
with.impl <- function(env, expr) {
env <- as.environment(env)
parent.env(env) <- parent.frame()
eval(substitute(expr), envir=env)
}
=={{header|Tcl}}==
|