Global Iterators

How to store iterator in some globals static varaible in rust and use it?

You don't. There's basically no situation in which this would be the right solution. What problem are you trying to solve, and why do you think you need this?

5 Likes

If a static variable could hold an iterator to a non-static container, then that iterator would outlive the container. Its internal references would point to objects which no longer exist, which is a safety violation.

There's another case where the container itself lives in a static variable, but then there are other issues that get in the way of allowing a mutable iterator to it to live in a static variable involving alias rules (and lifetime rules if you wrap the container in one of the cell types to allow mutability).

Rust makes global variables difficult to use, deliberately. Many languages make the problems with using global variables look lesser than they truly are. There are various concerns that need to be addressed; from thread-safety (multiple threads could access the global variable), to memory management (who owns the global? In turn, what can the global borrow or own?), and initialization (when does initialization happen?), as well as mutability (globals are inherently shared, if they’re also mutable, then we have shared mutability, which should be avoided whenever possible [<- this is one of Rust’s basic philosophy]).

There’s also different flavors of global… maybe you want the global thing restricted to a thread (usually that’s in the form of a one-copy-per-thread approach), or maybe not.

Most often, a global variable is not necessary at all. Various reasons for unnecessarily choosing a global variable is

  • (unfortunately!) in many programming languages, using a global variable is syntactically one of the most simply ways to use a variable, so one might want to use globals in Rust just out of habit
  • global variables could be desired for the purpose of being lazy about making sure references to the relevant values are passed to the places that need them. If it’s straightforward to just pass around the relevant references, do that instead. If there should be a single variable in the whole program, just use a local variable in main

There exist valid use-cases of global variables. Most often for basic infrastructure in library crates. Like the most fundamental stuff there is… for example the asynchronous executor, or a thread-pool, or a default random number generator may be defined with convenient library API by using some global variable internally as to make sure there’s just one of those things. Also, occasionally, a generic interface may prevent passing the relevant information explicitly. Or maybe some FFI requires operations to be globally mutually exclusive. (Sometimes a C library is using global state unnecessarily.)

Since there are valid use-cases, Rust does support global static variables. You need the data inside to be thread-safe, free of references to any non-static data, immutable, of using safe shared-mutability abstractions such as Mutex. Also, Rust currently has some limitations on naming types involving closures, so for an iterator that might be mapped, you may need to fall back to trait objects in order to be able to write down a type for the global. If all that is done, it’s possible – but I’m having a hard time imagining when this may be a good idea…

#![allow(uncommon_codepoints)]

use std::sync::Mutex;
static Ꮆし〇ᗷᗩし_ᓰƬᕮᖇᗩƬ〇ᖇ: Mutex<Option<Box<dyn Iterator<Item = u32> + Send>>> = Mutex::new(None);

fn initialize(x: impl Iterator<Item = u32> + 'static + Send) {
    *Ꮆし〇ᗷᗩし_ᓰƬᕮᖇᗩƬ〇ᖇ.lock().unwrap() = Some(Box::new(x) as _);
}

fn next_item() -> Option<u32> {
    Ꮆし〇ᗷᗩし_ᓰƬᕮᖇᗩƬ〇ᖇ.lock().unwrap().as_mut()?.next()
}

fn main() {
    initialize((1..5).map(|n| n * n));

    while let Some(i) = next_item() {
        println!("item {i}");
    }
}

Rust Playground

item 1
item 4
item 9
item 16
8 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.