Scope modifiers: Difference between revisions
Content deleted Content added
→{{header|R}}: substantially expanded discussion |
|||
Line 475: | Line 475: | ||
=={{header|R}}== |
=={{header|R}}== |
||
{{incorrect|R|<<- is not a "global assignment" operator. It would also be worth showing R constructs that can emulate dynamic scope, call-by-name, etc.}} |
|||
In R, functions use lexical scope: a function acquires its parent |
|||
R uses lexical scoping – there is a nice introduction to this in the [http://cran.r-project.org/doc/FAQ/R-FAQ.html#Lexical-scoping FAQ on R]. There are no keywords related to scoping, but the [http://stat.ethz.ch/R-manual/R-patched/library/base/html/assign.html assign] function allows you to choose the environment in which a variable is assigned. The global assignment operators , '<<-' and '->>' are effectively shorthand for 'assign(..., envir=globalenv()). |
|||
scope at the time of definition, and each invocation creates a new |
|||
<lang r>x <- "defined in global env" |
|||
local environment within that parent scope. Variable lookup during |
|||
foo <- function() |
|||
evaluation starts in the function's local environment and proceeds |
|||
{ |
|||
up the chain of parent environments. |
|||
# Print existing value |
|||
print(x) # "defined in global env" |
|||
<lang R>X <- "global x" |
|||
# define a local value and print it |
|||
f <- function() { |
|||
x <- "defined inside foo" |
|||
x <- "local x" |
|||
print(x) #"local x" |
|||
# remove local value, reassign global value from within foo |
|||
} |
|||
rm(x) |
|||
f() #prints "local x" |
|||
assign("x", "reassigned global value", envir=globalenv()) |
|||
print(x) #prints "global x"</lang> |
|||
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) |
|||
} |
} |
||
with.impl(d, mean(b - a + also))</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |