Scope modifiers: Difference between revisions

Content added Content deleted
(→‎{{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 &ndash; 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"
print(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) # "reassigned global value"
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)
}
}
foo()</lang>
with.impl(d, mean(b - a + also))</lang>


=={{header|Tcl}}==
=={{header|Tcl}}==