Chapter 27: R Global Variables
Part 1: What are Global Variables?
Global variables are variables that are defined outside of any function and are accessible from anywhere in your R environment – including inside functions, loops, and other structures.
The Basic Concept
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token comment"># This is a global variable</span> global_x <span class="token operator"><-</span> <span class="token number">10</span> print<span class="token punctuation">(</span>global_x<span class="token punctuation">)</span> <span class="token comment"># Can access anywhere</span> my_function <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Can access global variable inside function</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Inside function, global_x ="</span><span class="token punctuation">,</span> global_x<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> my_function<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Output:
|
0 1 2 3 4 5 6 7 |
[1] 10 [1] "Inside function, global_x = 10" |
Part 2: Global vs. Local Variables
Local Variables
Variables created inside functions are local – they only exist within that function:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span class="token comment"># Global variable</span> city <span class="token operator"><-</span> <span class="token string">"New York"</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Global city:"</span><span class="token punctuation">,</span> city<span class="token punctuation">)</span><span class="token punctuation">)</span> show_city <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Local variable with same name</span> city <span class="token operator"><-</span> <span class="token string">"Boston"</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Inside function, city ="</span><span class="token punctuation">,</span> city<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> show_city<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"After function, city ="</span><span class="token punctuation">,</span> city<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Global unchanged</span> |
Output:
|
0 1 2 3 4 5 6 7 8 |
[1] "Global city: New York" [1] "Inside function, city = Boston" [1] "After function, city = New York" |
The Search Path
When R looks for a variable, it follows a specific search order:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
x <span class="token operator"><-</span> <span class="token number">100</span> <span class="token comment"># Global</span> test_scope <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> x <span class="token operator"><-</span> <span class="token number">50</span> <span class="token comment"># Local - R finds this first</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Inside, x ="</span><span class="token punctuation">,</span> x<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># To access global, use global assignment or get()</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Global x ="</span><span class="token punctuation">,</span> get<span class="token punctuation">(</span><span class="token string">"x"</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> .GlobalEnv<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> test_scope<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Outside, x ="</span><span class="token punctuation">,</span> x<span class="token punctuation">)</span><span class="token punctuation">)</span> |
Part 3: Reading Global Variables
Functions can read global variables without any special syntax:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token comment"># Global configuration</span> app_name <span class="token operator"><-</span> <span class="token string">"MyApp"</span> version <span class="token operator"><-</span> <span class="token string">"1.0.0"</span> debug_mode <span class="token operator"><-</span> <span class="token boolean">TRUE</span> show_config <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Reading global variables</span> cat<span class="token punctuation">(</span><span class="token string">"Application:"</span><span class="token punctuation">,</span> app_name<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Version:"</span><span class="token punctuation">,</span> version<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Debug mode:"</span><span class="token punctuation">,</span> debug_mode<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> show_config<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Global Variables as Default Parameters
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="token comment"># Global defaults</span> default_color <span class="token operator"><-</span> <span class="token string">"blue"</span> default_size <span class="token operator"><-</span> <span class="token number">12</span> create_button <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>color <span class="token operator">=</span> default_color<span class="token punctuation">,</span> size <span class="token operator">=</span> default_size<span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Creating button - Color:"</span><span class="token punctuation">,</span> color<span class="token punctuation">,</span> <span class="token string">"Size:"</span><span class="token punctuation">,</span> size<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> create_button<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment"># Uses global defaults</span> create_button<span class="token punctuation">(</span><span class="token string">"red"</span><span class="token punctuation">,</span> <span class="token number">16</span><span class="token punctuation">)</span> <span class="token comment"># Override defaults</span> |
Part 4: Modifying Global Variables
The Problem – Assignment Creates Local Variables
When you use <- inside a function, you create a local variable, even if a global with the same name exists:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
counter <span class="token operator"><-</span> <span class="token number">0</span> increment_bad <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># This creates a LOCAL variable, doesn't modify global</span> counter <span class="token operator"><-</span> counter <span class="token operator">+</span> <span class="token number">1</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Inside function, counter ="</span><span class="token punctuation">,</span> counter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> increment_bad<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Outside function, counter ="</span><span class="token punctuation">,</span> counter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Still 0!</span> |
Output:
|
0 1 2 3 4 5 6 7 |
[1] "Inside function, counter = 1" [1] "Outside function, counter = 0" |
Solution 1: The Super Assignment Operator (<<-)
The <<- operator modifies variables in the parent environment (ultimately the global environment):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
counter <span class="token operator"><-</span> <span class="token number">0</span> increment_good <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># This modifies the GLOBAL counter</span> counter <span class="token operator"><<-</span> counter <span class="token operator">+</span> <span class="token number">1</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Inside function, counter ="</span><span class="token punctuation">,</span> counter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> increment_good<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Outside function, counter ="</span><span class="token punctuation">,</span> counter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Now 1!</span> increment_good<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Outside function, counter ="</span><span class="token punctuation">,</span> counter<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Now 2!</span> |
Solution 2: Using assign() with Global Environment
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
total <span class="token operator"><-</span> <span class="token number">100</span> add_to_total <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>amount<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Modify global using assign()</span> assign<span class="token punctuation">(</span><span class="token string">"total"</span><span class="token punctuation">,</span> total <span class="token operator">+</span> amount<span class="token punctuation">,</span> envir <span class="token operator">=</span> .GlobalEnv<span class="token punctuation">)</span> <span class="token punctuation">}</span> add_to_total<span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>total<span class="token punctuation">)</span> <span class="token comment"># 150</span> |
Solution 3: Returning and Reassigning (Recommended)
The cleanest approach is often to return values and reassign:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
count <span class="token operator"><-</span> <span class="token number">0</span> increment_clean <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>x <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> count <span class="token operator"><-</span> increment_clean<span class="token punctuation">(</span>count<span class="token punctuation">)</span> print<span class="token punctuation">(</span>count<span class="token punctuation">)</span> <span class="token comment"># 1</span> count <span class="token operator"><-</span> increment_clean<span class="token punctuation">(</span>count<span class="token punctuation">)</span> print<span class="token punctuation">(</span>count<span class="token punctuation">)</span> <span class="token comment"># 2</span> |
Part 5: Practical Examples
Example 1: Simple Counter System
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="token comment"># Global counter</span> visitor_count <span class="token operator"><-</span> <span class="token number">0</span> record_visit <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> visitor_count <span class="token operator"><<-</span> visitor_count <span class="token operator">+</span> <span class="token number">1</span> cat<span class="token punctuation">(</span><span class="token string">"Visitor"</span><span class="token punctuation">,</span> visitor_count<span class="token punctuation">,</span> <span class="token string">"recorded at"</span><span class="token punctuation">,</span> Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> get_visitor_count <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>visitor_count<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Simulate visits</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> <span class="token number">1</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> record_visit<span class="token punctuation">(</span><span class="token punctuation">)</span> Sys.sleep<span class="token punctuation">(</span><span class="token number">0.5</span><span class="token punctuation">)</span> <span class="token comment"># Wait half a second</span> <span class="token punctuation">}</span> cat<span class="token punctuation">(</span><span class="token string">"\nTotal visitors today:"</span><span class="token punctuation">,</span> get_visitor_count<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> |
Example 2: Configuration Management
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<span class="token comment"># Global configuration list</span> config <span class="token operator"><-</span> list<span class="token punctuation">(</span> app_name <span class="token operator">=</span> <span class="token string">"Data Analyzer"</span><span class="token punctuation">,</span> version <span class="token operator">=</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span> debug <span class="token operator">=</span> <span class="token boolean">FALSE</span><span class="token punctuation">,</span> max_iterations <span class="token operator">=</span> <span class="token number">1000</span><span class="token punctuation">,</span> tolerance <span class="token operator">=</span> <span class="token number">1e-6</span><span class="token punctuation">,</span> output_dir <span class="token operator">=</span> <span class="token string">"./results"</span> <span class="token punctuation">)</span> <span class="token comment"># Function to update configuration</span> update_config <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token percent-operator operator">%in%</span> names<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> config<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator"><<-</span> value cat<span class="token punctuation">(</span><span class="token string">"Config updated:"</span><span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token string">"="</span><span class="token punctuation">,</span> value<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Warning: Unknown config key:"</span><span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Function to get configuration</span> get_config <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key <span class="token operator">=</span> <span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>config<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token percent-operator operator">%in%</span> names<span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>config<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span><span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Function using configuration</span> run_analysis <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Running"</span><span class="token punctuation">,</span> get_config<span class="token punctuation">(</span><span class="token string">"app_name"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"version"</span><span class="token punctuation">,</span> get_config<span class="token punctuation">(</span><span class="token string">"version"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>get_config<span class="token punctuation">(</span><span class="token string">"debug"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Debug mode: ON\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Max iterations:"</span><span class="token punctuation">,</span> get_config<span class="token punctuation">(</span><span class="token string">"max_iterations"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Tolerance:"</span><span class="token punctuation">,</span> get_config<span class="token punctuation">(</span><span class="token string">"tolerance"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Simulate work</span> cat<span class="token punctuation">(</span><span class="token string">"Results will be saved to:"</span><span class="token punctuation">,</span> get_config<span class="token punctuation">(</span><span class="token string">"output_dir"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Use it</span> run_analysis<span class="token punctuation">(</span><span class="token punctuation">)</span> update_config<span class="token punctuation">(</span><span class="token string">"debug"</span><span class="token punctuation">,</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span> update_config<span class="token punctuation">(</span><span class="token string">"max_iterations"</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span> run_analysis<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Example 3: Logging System
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<span class="token comment"># Global log storage</span> log_messages <span class="token operator"><-</span> character<span class="token punctuation">(</span><span class="token punctuation">)</span> log_level <span class="token operator"><-</span> <span class="token string">"INFO"</span> <span class="token comment"># Can be DEBUG, INFO, WARN, ERROR</span> <span class="token comment"># Logging functions</span> log_debug <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>log_level <span class="token operator">==</span> <span class="token string">"DEBUG"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> timestamp <span class="token operator"><-</span> format<span class="token punctuation">(</span>Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"%Y-%m-%d %H:%M:%S"</span><span class="token punctuation">)</span> entry <span class="token operator"><-</span> paste<span class="token punctuation">(</span><span class="token string">"[DEBUG]"</span><span class="token punctuation">,</span> timestamp<span class="token punctuation">,</span> <span class="token string">"-"</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span> log_messages <span class="token operator"><<-</span> c<span class="token punctuation">(</span>log_messages<span class="token punctuation">,</span> entry<span class="token punctuation">)</span> cat<span class="token punctuation">(</span>entry<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> log_info <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>log_level <span class="token percent-operator operator">%in%</span> c<span class="token punctuation">(</span><span class="token string">"DEBUG"</span><span class="token punctuation">,</span> <span class="token string">"INFO"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> timestamp <span class="token operator"><-</span> format<span class="token punctuation">(</span>Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"%Y-%m-%d %H:%M:%S"</span><span class="token punctuation">)</span> entry <span class="token operator"><-</span> paste<span class="token punctuation">(</span><span class="token string">"[INFO]"</span><span class="token punctuation">,</span> timestamp<span class="token punctuation">,</span> <span class="token string">"-"</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span> log_messages <span class="token operator"><<-</span> c<span class="token punctuation">(</span>log_messages<span class="token punctuation">,</span> entry<span class="token punctuation">)</span> cat<span class="token punctuation">(</span>entry<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> log_warn <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>log_level <span class="token percent-operator operator">%in%</span> c<span class="token punctuation">(</span><span class="token string">"DEBUG"</span><span class="token punctuation">,</span> <span class="token string">"INFO"</span><span class="token punctuation">,</span> <span class="token string">"WARN"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> timestamp <span class="token operator"><-</span> format<span class="token punctuation">(</span>Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"%Y-%m-%d %H:%M:%S"</span><span class="token punctuation">)</span> entry <span class="token operator"><-</span> paste<span class="token punctuation">(</span><span class="token string">"[WARN]"</span><span class="token punctuation">,</span> timestamp<span class="token punctuation">,</span> <span class="token string">"-"</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span> log_messages <span class="token operator"><<-</span> c<span class="token punctuation">(</span>log_messages<span class="token punctuation">,</span> entry<span class="token punctuation">)</span> cat<span class="token punctuation">(</span>entry<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> log_error <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token punctuation">{</span> timestamp <span class="token operator"><-</span> format<span class="token punctuation">(</span>Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"%Y-%m-%d %H:%M:%S"</span><span class="token punctuation">)</span> entry <span class="token operator"><-</span> paste<span class="token punctuation">(</span><span class="token string">"[ERROR]"</span><span class="token punctuation">,</span> timestamp<span class="token punctuation">,</span> <span class="token string">"-"</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span> log_messages <span class="token operator"><<-</span> c<span class="token punctuation">(</span>log_messages<span class="token punctuation">,</span> entry<span class="token punctuation">)</span> cat<span class="token punctuation">(</span>entry<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> set_log_level <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>level<span class="token punctuation">)</span> <span class="token punctuation">{</span> log_level <span class="token operator"><<-</span> level log_info<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Log level changed to"</span><span class="token punctuation">,</span> level<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> get_logs <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>log_messages<span class="token punctuation">)</span> <span class="token punctuation">}</span> clear_logs <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> log_messages <span class="token operator"><<-</span> character<span class="token punctuation">(</span><span class="token punctuation">)</span> log_info<span class="token punctuation">(</span><span class="token string">"Logs cleared"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test the logging system</span> set_log_level<span class="token punctuation">(</span><span class="token string">"DEBUG"</span><span class="token punctuation">)</span> log_debug<span class="token punctuation">(</span><span class="token string">"This is a debug message"</span><span class="token punctuation">)</span> log_info<span class="token punctuation">(</span><span class="token string">"Application started"</span><span class="token punctuation">)</span> log_warn<span class="token punctuation">(</span><span class="token string">"Low disk space"</span><span class="token punctuation">)</span> log_error<span class="token punctuation">(</span><span class="token string">"Failed to save file"</span><span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"\nAll logs:\n"</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>get_logs<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Example 4: Cache System
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<span class="token comment"># Global cache</span> .cache <span class="token operator"><-</span> new.env<span class="token punctuation">(</span>parent <span class="token operator">=</span> emptyenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># Cache functions</span> cache_set <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span> .cache<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator"><<-</span> list<span class="token punctuation">(</span> value <span class="token operator">=</span> value<span class="token punctuation">,</span> timestamp <span class="token operator">=</span> Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> invisible<span class="token punctuation">(</span><span class="token boolean">TRUE</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cache_get <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>exists<span class="token punctuation">(</span>key<span class="token punctuation">,</span> envir <span class="token operator">=</span> .cache<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>.cache<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token operator">$</span>value<span class="token punctuation">)</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span><span class="token keyword">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cache_has <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>exists<span class="token punctuation">(</span>key<span class="token punctuation">,</span> envir <span class="token operator">=</span> .cache<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cache_clear <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> rm<span class="token punctuation">(</span>list <span class="token operator">=</span> ls<span class="token punctuation">(</span>envir <span class="token operator">=</span> .cache<span class="token punctuation">)</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> .cache<span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Cache cleared\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cache_stats <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> keys <span class="token operator"><-</span> ls<span class="token punctuation">(</span>envir <span class="token operator">=</span> .cache<span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Cache contains"</span><span class="token punctuation">,</span> length<span class="token punctuation">(</span>keys<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"items\n"</span><span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>key <span class="token keyword">in</span> keys<span class="token punctuation">)</span> <span class="token punctuation">{</span> item <span class="token operator"><-</span> .cache<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span> cat<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token string">"- stored at"</span><span class="token punctuation">,</span> format<span class="token punctuation">(</span>item<span class="token operator">$</span>timestamp<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Expensive computation function that uses cache</span> compute_expensive <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> <span class="token punctuation">{</span> cache_key <span class="token operator"><-</span> paste0<span class="token punctuation">(</span><span class="token string">"result_"</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>cache_has<span class="token punctuation">(</span>cache_key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Cache hit for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>cache_get<span class="token punctuation">(</span>cache_key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cat<span class="token punctuation">(</span><span class="token string">"Cache miss for n ="</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> <span class="token string">"- computing...\n"</span><span class="token punctuation">)</span> Sys.sleep<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment"># Simulate heavy computation</span> result <span class="token operator"><-</span> sum<span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">:</span>n<span class="token punctuation">)</span><span class="token operator">^</span><span class="token number">2</span> cache_set<span class="token punctuation">(</span>cache_key<span class="token punctuation">,</span> result<span class="token punctuation">)</span> return<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test the cache</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token keyword">in</span> c<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Result:"</span><span class="token punctuation">,</span> compute_expensive<span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> cache_stats<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Part 6: Global Variables in Packages
When creating R packages, global variables need special handling:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span class="token comment"># In a package, use .onLoad to set up globals</span> .onLoad <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>libname<span class="token punctuation">,</span> pkgname<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Package-level global variable</span> assign<span class="token punctuation">(</span><span class="token string">"pkg_counter"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> topenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Function to use the package global</span> increment_counter <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> current <span class="token operator"><-</span> get<span class="token punctuation">(</span><span class="token string">"pkg_counter"</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> topenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> assign<span class="token punctuation">(</span><span class="token string">"pkg_counter"</span><span class="token punctuation">,</span> current <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> topenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> return<span class="token punctuation">(</span>current <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Part 7: The Dangers of Global Variables
Problem 1: Unintended Side Effects
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span class="token comment"># Global variable</span> important_value <span class="token operator"><-</span> <span class="token number">100</span> function_a <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># This function modifies the global</span> important_value <span class="token operator"><<-</span> important_value <span class="token operator">*</span> <span class="token number">2</span> <span class="token punctuation">}</span> function_b <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># This function also modifies the global</span> important_value <span class="token operator"><<-</span> important_value <span class="token operator">+</span> <span class="token number">50</span> <span class="token punctuation">}</span> function_c <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># This function reads the global</span> return<span class="token punctuation">(</span>important_value <span class="token operator">/</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># What's the value? Depends on call order!</span> function_a<span class="token punctuation">(</span><span class="token punctuation">)</span> function_b<span class="token punctuation">(</span><span class="token punctuation">)</span> result <span class="token operator"><-</span> function_c<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token comment"># Hard to predict without knowing call history</span> |
Problem 2: Name Conflicts
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span class="token comment"># Global variable</span> data <span class="token operator"><-</span> c<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span> analyze_data <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Did you mean to use the global data?</span> <span class="token comment"># Or create a new local variable?</span> data <span class="token operator"><-</span> data <span class="token operator">*</span> <span class="token number">2</span> <span class="token comment"># Creates local, doesn't modify global</span> <span class="token comment"># This uses the local data, not global</span> mean_val <span class="token operator"><-</span> mean<span class="token punctuation">(</span>data<span class="token punctuation">)</span> return<span class="token punctuation">(</span>mean_val<span class="token punctuation">)</span> <span class="token punctuation">}</span> result <span class="token operator"><-</span> analyze_data<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>result<span class="token punctuation">)</span> <span class="token comment"># Mean of local data</span> print<span class="token punctuation">(</span>data<span class="token punctuation">)</span> <span class="token comment"># Original global unchanged (maybe unexpected!)</span> |
Problem 3: Debugging Difficulty
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<span class="token comment"># Multiple functions modifying the same global</span> user_status <span class="token operator"><-</span> <span class="token string">"active"</span> login <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> user_status <span class="token operator"><<-</span> <span class="token string">"active"</span> log_event<span class="token punctuation">(</span><span class="token string">"User logged in"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> logout <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> user_status <span class="token operator"><<-</span> <span class="token string">"inactive"</span> log_event<span class="token punctuation">(</span><span class="token string">"User logged out"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> timeout <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> user_status <span class="token operator"><<-</span> <span class="token string">"timed_out"</span> log_event<span class="token punctuation">(</span><span class="token string">"Session timed out"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># If something goes wrong, tracking which function</span> <span class="token comment"># last modified user_status can be challenging</span> |
Part 8: Best Practices for Global Variables
1. Use All Caps for Global Constants
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token comment"># Clearly mark as global constants</span> MAX_RETRIES <span class="token operator"><-</span> <span class="token number">3</span> DEFAULT_COLOR <span class="token operator"><-</span> <span class="token string">"blue"</span> API_ENDPOINT <span class="token operator"><-</span> <span class="token string">"https://api.example.com"</span> DEBUG_MODE <span class="token operator"><-</span> <span class="token boolean">FALSE</span> use_constant <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>DEBUG_MODE<span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Debug:"</span><span class="token punctuation">,</span> MAX_RETRIES<span class="token punctuation">,</span> <span class="token string">"max retries\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
2. Use Lists to Group Related Globals
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="token comment"># Group related globals</span> app_config <span class="token operator"><-</span> list<span class="token punctuation">(</span> name <span class="token operator">=</span> <span class="token string">"MyApp"</span><span class="token punctuation">,</span> version <span class="token operator">=</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span> debug <span class="token operator">=</span> <span class="token boolean">FALSE</span><span class="token punctuation">,</span> max_retries <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">,</span> timeout <span class="token operator">=</span> <span class="token number">30</span> <span class="token punctuation">)</span> <span class="token comment"># Single point of access</span> get_config <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>app_config<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> update_config <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span> app_config<span class="token punctuation">[</span><span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator"><<-</span> value <span class="token punctuation">}</span> |
3. Use Environments for Encapsulation
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="token comment"># Create a private environment for globals</span> .state <span class="token operator"><-</span> new.env<span class="token punctuation">(</span>parent <span class="token operator">=</span> emptyenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> .state<span class="token operator">$</span>counter <span class="token operator"><-</span> <span class="token number">0</span> .state<span class="token operator">$</span>data <span class="token operator"><-</span> <span class="token keyword">NULL</span> .state<span class="token operator">$</span>initialized <span class="token operator"><-</span> <span class="token boolean">FALSE</span> <span class="token comment"># Public functions to interact with state</span> initialize_app <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> .state<span class="token operator">$</span>counter <span class="token operator"><-</span> <span class="token number">0</span> .state<span class="token operator">$</span>data <span class="token operator"><-</span> data.frame<span class="token punctuation">(</span><span class="token punctuation">)</span> .state<span class="token operator">$</span>initialized <span class="token operator"><-</span> <span class="token boolean">TRUE</span> cat<span class="token punctuation">(</span><span class="token string">"App initialized\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> increment <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> .state<span class="token operator">$</span>counter <span class="token operator"><-</span> .state<span class="token operator">$</span>counter <span class="token operator">+</span> <span class="token number">1</span> return<span class="token punctuation">(</span>.state<span class="token operator">$</span>counter<span class="token punctuation">)</span> <span class="token punctuation">}</span> get_state <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>as.list<span class="token punctuation">(</span>.state<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Test</span> initialize_app<span class="token punctuation">(</span><span class="token punctuation">)</span> increment<span class="token punctuation">(</span><span class="token punctuation">)</span> increment<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>get_state<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
4. Document Global Variables
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token comment">#' Global configuration settings</span> <span class="token comment">#' </span> <span class="token comment">#' @format A list with elements:</span> <span class="token comment">#' \describe{</span> <span class="token comment">#' \item{app_name}{Character string, name of the application}</span> <span class="token comment">#' \item{version}{Character string, version number}</span> <span class="token comment">#' \item{debug}{Logical, whether debug mode is enabled}</span> <span class="token comment">#' }</span> app_config <span class="token operator"><-</span> list<span class="token punctuation">(</span> app_name <span class="token operator">=</span> <span class="token string">"MyApp"</span><span class="token punctuation">,</span> version <span class="token operator">=</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span> debug <span class="token operator">=</span> <span class="token boolean">FALSE</span> <span class="token punctuation">)</span> |
5. Minimize Global Variables
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<span class="token comment"># ❌ Bad - many globals</span> user_name <span class="token operator"><-</span> <span class="token string">""</span> user_age <span class="token operator"><-</span> <span class="token number">0</span> user_email <span class="token operator"><-</span> <span class="token string">""</span> user_logged_in <span class="token operator"><-</span> <span class="token boolean">FALSE</span> <span class="token comment"># ✅ Better - encapsulated in functions</span> create_user_session <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> session <span class="token operator"><-</span> new.env<span class="token punctuation">(</span>parent <span class="token operator">=</span> emptyenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> session<span class="token operator">$</span>name <span class="token operator"><-</span> <span class="token string">""</span> session<span class="token operator">$</span>age <span class="token operator"><-</span> <span class="token number">0</span> session<span class="token operator">$</span>email <span class="token operator"><-</span> <span class="token string">""</span> session<span class="token operator">$</span>logged_in <span class="token operator"><-</span> <span class="token boolean">FALSE</span> return<span class="token punctuation">(</span>session<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Even better - use reference class or R6</span> UserSession <span class="token operator"><-</span> setRefClass<span class="token punctuation">(</span><span class="token string">"UserSession"</span><span class="token punctuation">,</span> fields <span class="token operator">=</span> list<span class="token punctuation">(</span> name <span class="token operator">=</span> <span class="token string">"character"</span><span class="token punctuation">,</span> age <span class="token operator">=</span> <span class="token string">"numeric"</span><span class="token punctuation">,</span> email <span class="token operator">=</span> <span class="token string">"character"</span><span class="token punctuation">,</span> logged_in <span class="token operator">=</span> <span class="token string">"logical"</span> <span class="token punctuation">)</span><span class="token punctuation">,</span> methods <span class="token operator">=</span> list<span class="token punctuation">(</span> login <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> logged_in <span class="token operator"><<-</span> <span class="token boolean">TRUE</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> logout <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> logged_in <span class="token operator"><<-</span> <span class="token boolean">FALSE</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> session <span class="token operator"><-</span> UserSession<span class="token operator">$</span>new<span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">"Alice"</span><span class="token punctuation">,</span> age <span class="token operator">=</span> <span class="token number">30</span><span class="token punctuation">,</span> email <span class="token operator">=</span> <span class="token string">"alice@example.com"</span><span class="token punctuation">,</span> logged_in <span class="token operator">=</span> <span class="token boolean">FALSE</span><span class="token punctuation">)</span> session<span class="token operator">$</span>login<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Part 9: Testing with Global Variables
Testing code that uses global variables requires special care:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<span class="token comment"># Function that uses global</span> tax_rate <span class="token operator"><-</span> <span class="token number">0.08</span> calculate_total <span class="token operator"><-</span> price <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>amount<span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>amount <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">+</span> tax_rate<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Testing approach</span> test_calculate_total <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Save original</span> original_rate <span class="token operator"><-</span> tax_rate <span class="token comment"># Test case 1</span> tax_rate <span class="token operator"><<-</span> <span class="token number">0.1</span> stopifnot<span class="token punctuation">(</span>calculate_total<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">110</span><span class="token punctuation">)</span> <span class="token comment"># Test case 2</span> tax_rate <span class="token operator"><<-</span> <span class="token number">0.2</span> stopifnot<span class="token punctuation">(</span>calculate_total<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">120</span><span class="token punctuation">)</span> <span class="token comment"># Restore original</span> tax_rate <span class="token operator"><<-</span> original_rate cat<span class="token punctuation">(</span><span class="token string">"All tests passed!\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> test_calculate_total<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Better: Dependency Injection
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span class="token comment"># Better design - pass dependencies explicitly</span> calculate_total <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>amount<span class="token punctuation">,</span> tax_rate <span class="token operator">=</span> <span class="token number">0.08</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> return<span class="token punctuation">(</span>amount <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator">+</span> tax_rate<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># Easy to test</span> stopifnot<span class="token punctuation">(</span>calculate_total<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">0.1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">110</span><span class="token punctuation">)</span> stopifnot<span class="token punctuation">(</span>calculate_total<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">0.2</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">120</span><span class="token punctuation">)</span> stopifnot<span class="token punctuation">(</span>calculate_total<span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">108</span><span class="token punctuation">)</span> <span class="token comment"># Uses default</span> |
Part 10: Advanced Patterns
Pattern 1: Singleton Pattern
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<span class="token comment"># Ensure only one instance of a global object exists</span> DatabaseConnection <span class="token operator"><-</span> local<span class="token punctuation">(</span><span class="token punctuation">{</span> connection <span class="token operator"><-</span> <span class="token keyword">NULL</span> list<span class="token punctuation">(</span> get <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>is.null<span class="token punctuation">(</span>connection<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> connection <span class="token operator"><<-</span> list<span class="token punctuation">(</span> id <span class="token operator">=</span> paste0<span class="token punctuation">(</span><span class="token string">"conn_"</span><span class="token punctuation">,</span> sample<span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> connected <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">,</span> time <span class="token operator">=</span> Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> cat<span class="token punctuation">(</span><span class="token string">"Created new database connection\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> return<span class="token punctuation">(</span>connection<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> reset <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> connection <span class="token operator"><<-</span> <span class="token keyword">NULL</span> cat<span class="token punctuation">(</span><span class="token string">"Connection reset\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment"># Use it</span> db <span class="token operator"><-</span> DatabaseConnection<span class="token operator">$</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>db<span class="token punctuation">)</span> db2 <span class="token operator"><-</span> DatabaseConnection<span class="token operator">$</span>get<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment"># Returns same connection</span> print<span class="token punctuation">(</span>identical<span class="token punctuation">(</span>db<span class="token punctuation">,</span> db2<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment"># TRUE</span> |
Pattern 2: Observer Pattern
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<span class="token comment"># Global event system</span> .events <span class="token operator"><-</span> new.env<span class="token punctuation">(</span>parent <span class="token operator">=</span> emptyenv<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> .events<span class="token operator">$</span>listeners <span class="token operator"><-</span> list<span class="token punctuation">(</span><span class="token punctuation">)</span> on <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span> callback<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>event <span class="token percent-operator operator">%in%</span> names<span class="token punctuation">(</span>.events<span class="token operator">$</span>listeners<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> .events<span class="token operator">$</span>listeners<span class="token punctuation">[</span><span class="token punctuation">[</span>event<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator"><<-</span> list<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> .events<span class="token operator">$</span>listeners<span class="token punctuation">[</span><span class="token punctuation">[</span>event<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator"><<-</span> c<span class="token punctuation">(</span>.events<span class="token operator">$</span>listeners<span class="token punctuation">[</span><span class="token punctuation">[</span>event<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span> callback<span class="token punctuation">)</span> <span class="token punctuation">}</span> emit <span class="token operator"><-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span> <span class="token ellipsis">...</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>event <span class="token percent-operator operator">%in%</span> names<span class="token punctuation">(</span>.events<span class="token operator">$</span>listeners<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>callback <span class="token keyword">in</span> .events<span class="token operator">$</span>listeners<span class="token punctuation">[</span><span class="token punctuation">[</span>event<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> callback<span class="token punctuation">(</span><span class="token ellipsis">...</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment"># Register listeners</span> on<span class="token punctuation">(</span><span class="token string">"user_login"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span> cat<span class="token punctuation">(</span><span class="token string">"Log: User"</span><span class="token punctuation">,</span> user<span class="token punctuation">,</span> <span class="token string">"logged in at"</span><span class="token punctuation">,</span> Sys.time<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">"\n"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> on<span class="token punctuation">(</span><span class="token string">"user_login"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment"># Update counter</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>exists<span class="token punctuation">(</span><span class="token string">"login_count"</span><span class="token punctuation">,</span> envir <span class="token operator">=</span> .events<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> .events<span class="token operator">$</span>login_count <span class="token operator"><<-</span> <span class="token number">0</span> <span class="token punctuation">}</span> .events<span class="token operator">$</span>login_count <span class="token operator"><<-</span> .events<span class="token operator">$</span>login_count <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment"># Trigger event</span> emit<span class="token punctuation">(</span><span class="token string">"user_login"</span><span class="token punctuation">,</span> <span class="token string">"Alice"</span><span class="token punctuation">)</span> emit<span class="token punctuation">(</span><span class="token string">"user_login"</span><span class="token punctuation">,</span> <span class="token string">"Bob"</span><span class="token punctuation">)</span> print<span class="token punctuation">(</span>paste<span class="token punctuation">(</span><span class="token string">"Total logins:"</span><span class="token punctuation">,</span> .events<span class="token operator">$</span>login_count<span class="token punctuation">)</span><span class="token punctuation">)</span> |
Summary: The Global Variable Philosophy
Global variables are a powerful but dangerous tool. Master these concepts:
When to use globals:
-
Configuration settings that rarely change
-
Logging systems
-
Cache systems
-
Shared resources (database connections)
-
Constants
When NOT to use globals:
-
For data that changes frequently
-
When functions need to be independent
-
In packages you’ll share with others
-
When you need thread safety
-
For anything that makes testing difficult
Best practices:
-
Use ALL_CAPS for global constants
-
Group related globals in lists or environments
-
Document all global variables
-
Minimize the number of globals
-
Consider dependency injection instead
-
Use
<<-sparingly and document its use -
Reset globals between tests
Alternatives to globals:
-
Function parameters and return values
-
Closure-based encapsulation
-
Reference classes (R6)
-
Environments as private state
-
Dependency injection
The key insight is that global variables are like public squares – useful for announcements and gatherings, but if everyone tries to build their house there, chaos ensues. Use them sparingly, document them clearly, and always consider whether there’s a better way.
Would you like me to elaborate on any specific aspect of global variables or explore more advanced patterns for managing state in R?
