Global variable in a package - which approach is more recommended?
Some packages use hidden variables (variables that begin with a .
), like .Random.seed
and .Last.value
do in base R. In your package you could do
e <- new.env()
assign(".sessionId", "xyz123", envir = e)
ls(e)
# character(0)
ls(e, all = TRUE)
# [1] ".sessionId"
But in your package you don't need to assign e
. You can use a .onLoad()
hook to assign the variable upon loading the package.
.onLoad <- function(libname, pkgname) {
assign(".sessionId", "xyz123", envir = parent.env(environment()))
}
See this question and its answers for some good explanation on package variables.
Global variables in packages in R
In general global variables are evil. The underlying principle why they are evil is that you want to minimize the interconnections in your package. These interconnections often cause functions to have side-effects, i.e. it depends not only on the input arguments what the outcome is, but also on the value of some global variable. Especially when the number of functions grows, this can be hard to get right and hell to debug.
For global variables in R see this SO post.
Edit in response to your comment:
An alternative could be to just pass around the needed information to the functions that need it. You could create a new object which contains this info:
token_information = list(token1 = "087091287129387",
token2 = "UA2329723")
and require all functions that need this information to have it as an argument:
do_stuff = function(arg1, arg2, token)
do_stuff(arg1, arg2, token = token_information)
In this way it is clear from the code that token information is needed in the function, and you can debug the function on its own. Furthermore, the function has no side effects, as its behavior is fully determined by its input arguments. A typical user script would look something like:
token_info = create_token(token1, token2)
do_stuff(arg1, arg2, token_info)
I hope this makes things more clear.
When to use global variables
One usual way is to use Method Value
Consider a
struct type T
with two methods,Mv
, whose receiver is of typeT
, andMp
, whose receiver is of type*T
.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
The expression
T.Mv
yields a function equivalent to Mv but with an explicit receiver as its first argument; it has signature
func(tv T, a int) int
You can see an example of Method Value in this thread
// TODO: Get rid of the global variable.
var foo service
func handleFoo(w http.ResponseWriter, req *http.Request) {
// code that uses foo
}
func main() {
foo = initFoo()
http.HandleFunc("/foo", handleFoo)
}
One way to get rid of that global variable is to use method values:
type fooHandler struct {
foo service
}
func (h fooHandler) handle(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.HandleFunc("/foo", fooHandler{foo}.handle)
}
A new official approach for your global values is introduced in Go 1.7 with context.Context#Values
.
Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.
See "How to correctly use context.Context in Go 1.7"
Finally, in addition of being hard to test, global values can prevent vendoring.
See "To vendor or not to vendor, that is a question"
Many Go’s libaries have exported package variables. Those variables can be viewed as certain global states of a certain package.
Prior vendoring era, we can go get each imported package once and the global state of each imported package can be shared within all other imported packages.
Some devs may take it as granted and simply manipulate those global states at will.
However, with vendoring each imported package may have its own view of global states. Now a dev may found it impossible to change other package’s view of global state
Java - best practice for creating package-wide or global variables
If you're talking about constants, then they should be declared as static final
fields in a class (never in an interface, according to Joshua Bloch).
If you're talking about settings which can change on the fly, then these could be either static
fields in a class, or you could create a ConfigHandler class to manage the setting and fetching of configurable values.
Using class fields for mutable values might lead to concurrency problems, so if your application is multi-threaded it might be better to create a ConfigHandler class which manages concurrent access carefully and provides synchronized
methods to avoid problems.
When is it ok to use a global variable in C?
Variables should always have a smaller scope possible. The argument behind that is that every time you increase the scope, you have more code that potentially modifies the variable, thus more complexity is induced in the solution.
It is thus clear that avoiding using global variables is preferred if the design and implementation naturally allow that. Due to this, I prefer not to use global variables unless they are really needed.
I can not agree with the 'never' statement either. Like any other concept, global variables are something that should be used only when needed. I would rather use global variables than using some artificial constructs (like passing pointers around), which would only mask the real intent.
Some good examples where global variables are used are singleton pattern implementations or register access in embedded systems.
On how to actually detect excessive usages of global variables: inspection, inspection, inspection. Whenever I see a global variable I have to ask myself: Is that REALLY needed at a global scope?
Global variables in Java
To define Global Variable you can make use of static Keyword
public class Example {
public static int a;
public static int b;
}
now you can access a and b from anywhere
by calling
Example.a;
Example.b;
Using global variables in a function
You can use a global variable within other functions by declaring it as global
within each function that assigns a value to it:
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print(globvar) # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
Since it's unclear whether globvar = 1
is creating a local variable or changing a global variable, Python defaults to creating a local variable, and makes you explicitly choose the other behavior with the global
keyword.
See other answers if you want to share a global variable across modules.
Related Topics
How to Extract Multiples of a Number from a Vector
2 Knitr/R Markdown/Rstudio Issues: Highcharts and Morris.Js
Get the Vector of Values from Different Columns of a Matrix
Plot Negative Values in Logarithmic Scale with Ggplot 2
Cbind Two Lists of Data.Frames to a New List
How to Divide Between Groups of Rows Using Dplyr
R Cannot Allocate Memory Though Memory Seems to Be Available
R - Scaling Numeric Values Only in a Dataframe with Mixed Types
Calling Library() in R with a Variable as the Argument
R Crashing While Displaying Ggplot After Update (Process Memory Read Out of Range)
If Column Contains String Then Enter Value for That Row
Send a Text String Containing Double Quotes to Function
Ggplot2 One Line Per Each Row Dataframe
Error in Terms.Formula(Formula):'.' in Formula and No 'Data' Argument
R: Replacing Nas in a Data.Frame with Values in the Same Position in Another Dataframe
Changing Styles When Selecting and Deselecting Multiple Polygons with Leaflet/Shiny