Skip to content
Prev 393631 / 398503 Next

return value of {....}

Again, John, we are comparing different designs in languages that are often
decades old and partially retrofitted selectively over the years.

Is it poor form to use global variables? Many think so. Discussions have
been had on how to use variables hidden in various ways that are not global,
such as within a package.

But note R still has global assignment operators like <<- and its partner
->> that explicitly can even create a global variable that did not exist
before the function began and that persists for that session. This is
perhaps a special case of the assign() function which can do the same for
any designated environment.

Although it may sometimes be better form to avoid things like this, it can
also be worse form when you want to do something decentralized with no
control over passing additional arguments to all kinds of functions.  

Some languages try to finesse their way past this by creating concepts like
closures that hold values and can even change the values without them being
globally visible. Some may use singleton objects or variables that are part
of a class rather than a single object (which is again a singleton.)

So is the way R allows really a bad thing, especially if rarely used?

All I know is MANY languages use scoping including functions that declare a
variable then create an inner function or many and return the inner
function(s) to the outside where the one getting it can later use that
function and access the variable and even use it as a way to communicate
with the multiple functions it got that were created in that incubator.
Nifty stuff but arguably not always as easy to comprehend!

This forum is not intended for BASHING any language, certainly not R. There
are many other languages to choose from and every one of them will have some
things others consider flaws. How many opted out of say a ++ operator as in
y = x++ for fairly good reasons and later added something like the Walrus
operator so you can now write y = (x := x + 1) as a way to do the same thing
and other things besides?

But to address your point, about a variable outside a function as defined in
a set of environments to search that includes a global context, I want to
note that it is just a set of maskings and your variable "x" can appear in
EVERY environment above you and you can get in real trouble if the order the
environments are put in place changes in some way. The arguably safer way
would be to get a specific value of x would be to not ask for it directly
but as get("x", envir=...) and specify the specific environment that ideally
is in existence at that time. Other arguments to get() let you specify a few
more things such as whether to search other places or supply a default.

Is it then poor technique to re-use the same name "x" in the same code for
some independent use? Probably, albeit if the new value plays a similar
role, just in another stretch of code, maybe not. I would comment it
carefully, and spell that out.

S first came out and before I even decided to become a Computer Scientist in
the mid to late  70's  and evolved multiple times. I first noticed it at
Bell Labs in the 80's. To a certain extent, R started as heavily influenced
by S and many programs could run on both. It too has changed over about
three decades. What kind of perfection can anyone expect over more recent
languages carefully produced with little concern about backward
compatibility?

And it remains very useful not necessarily based on the original language or
even the evolving core, but because of changes that maintained compatibility
as well as so many packages that met needs. Making changes, even if
"improvements" is likely to break all kinds of code unless it is something
like the new pipe operator that simply uses aspects that nobody would have
used before such as the new "|>" operator. 

The answer to too many questions about R remains BECAUSE that is how it was
done and whether you like it or not, may not change much any time soon. That
is why so many people like packages such as in the tidyverse because they
manage to make some changes, for better and often for verse.



-----Original Message-----
From: R-help <r-help-bounces at r-project.org> On Behalf Of Sorkin, John
Sent: Sunday, January 15, 2023 8:08 PM
To: Richard O'Keefe <raoknz at gmail.com>; Valentin Petzel <valentin at petzel.at>
Cc: R help Mailing list <r-help at r-project.org>
Subject: Re: [R] return value of {....}

Richard,
I sent my prior email too quickly:

A slight addition to your code shows an important aspect of R, local vs.
global variables:

x <- 137
f <- function () {
       a <- x
       x <- 42
       b <- x
       list(a=a, b=b)
   }
 f()
print(x)

When run the program produces the following:
+        a <- x
+        x <- 42
+        b <- x
+        list(a=a, b=b)
+    }
$a
[1] 137

$b
[1] 42
[1] 137

The fist x, a <- x, invokes an x variable that is GLOBAL. It is known both
inside and outside the function.
The second x, x <- 42, defines an x that is LOCAL to the function, it is not
known to the program that called the function. The LOCAL value of x is used
in the expression  b <- x. As can be seen by the print(x) statement, the
LOCAL value of x is NOT known by the program that calls the function. The
class of a variable, scoping (i.e. local vs. variable) can be a source of
subtle programming errors. A general recommendation is to AVOID use of a
global variable in a function, i.e. don't use a variable in function that is
not passed as a parameter to the function (as was done in the function above
in the statment a <- x). If you need to use a variable in a function that is
known by the program that calls the function, pass the variable as a
argument to the function e.g. 

Use this code:

# Set values needed by function
y <- 2
b <- 30

myfunction <- function(a,b){
cat("a=",a,"b=",b,"\n")
  y <- a
  y2 <- y+b
  cat("y=",y,"y2=",y2,"\n")
}
# Call the function and pass all needed values to the function
myfunction(y,b)
 
Don't use the following code that depends on a global value that is known to
the function, but not passed as a parameter to the function:

y <- 2
myNGfunction <- function(a){
  cat("a=",a,"b=",b,"\n")
  y <- a
  y2 <- y+b
  cat("y=",y,"y2=",y2,"\n")
}
# b is a global variable and will be know to the function, # but should be
passed as a parameter as in example above.
b <- 100
myNGfunction(y)

John

Thread (32 messages)

akshay kulkarni return value of {....} Jan 9 Valentin Petzel return value of {....} Jan 9 Rui Barradas return value of {....} Jan 9 Bert Gunter return value of {....} Jan 9 akshay kulkarni return value of {....} Jan 9 akshay kulkarni return value of {....} Jan 9 Bert Gunter return value of {....} Jan 9 akshay kulkarni return value of {....} Jan 9 Andrew Simmons return value of {....} Jan 9 akshay kulkarni return value of {....} Jan 9 @vi@e@gross m@iii@g oii gm@ii@com return value of {....} Jan 9 Jeff Newmiller return value of {....} Jan 9 Bert Gunter return value of {....} Jan 9 akshay kulkarni return value of {....} Jan 10 @vi@e@gross m@iii@g oii gm@ii@com return value of {....} Jan 10 akshay kulkarni return value of {....} Jan 10 Richard O'Keefe return value of {....} Jan 10 akshay kulkarni return value of {....} Jan 11 Valentin Petzel return value of {....} Jan 12 Heinz Tuechler return value of {....} Jan 13 Bill Dunlap return value of {....} Jan 13 akshay kulkarni return value of {....} Jan 15 akshay kulkarni return value of {....} Jan 15 akshay kulkarni return value of {....} Jan 15 Richard O'Keefe return value of {....} Jan 15 Sorkin, John return value of {....} Jan 15 Bert Gunter return value of {....} Jan 15 Sorkin, John return value of {....} Jan 15 Bert Gunter return value of {....} Jan 15 @vi@e@gross m@iii@g oii gm@ii@com return value of {....} Jan 15 @vi@e@gross m@iii@g oii gm@ii@com return value of {....} Jan 15 Sorkin, John return value of {....} Jan 15