Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I create a function-local static `HashSet<char>` and initialize it once? [duplicate]

I have read through the first half of the book's second edition as well as this chapter in the first edition. I am still confused how to initialize static variables.

In the end I'd like to have a function local static HashSet<char> containing all digit characters.

Attempt 1:

fn is_digit(c: char) -> bool {
    static set: std::collections::HashSet<char> =
        ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
            .iter()
            .cloned()
            .collect();

    return set.contains(&c);
}

The compiler yields:

error[E0015]: calls in statics are limited to struct and enum constructors
 --> src/main.rs:3:9
  |
3 | /         ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
4 | |             .iter()
  | |___________________^
  |
note: a limited form of compile-time function evaluation is available on a nightly compiler via `const fn`
 --> src/main.rs:3:9
  |
3 | /         ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
4 | |             .iter()
  | |___________________^

Attempt 2: (No data, only construction)

static set: std::collections::HashSet<char> = std::collections::HashSet::new();

The compiler yields:

error[E0015]: calls in statics are limited to struct and enum constructors
 --> src/main.rs:1:47
  |
1 | static set: std::collections::HashSet<char> = std::collections::HashSet::new();
  |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |

This on the other hand works:

let set: std::collections::HashSet<char> = std::collections::HashSet::new();

HashSet is a struct.

That is why I don't understand the error from attempt 2. I am trying to call the struct's constructor and the compiler says I can only call the constructor of a struct or enum.

I guess new() is not a constructor call after all...?

like image 928
Noel Widmer Avatar asked Nov 03 '25 00:11

Noel Widmer


1 Answers

To use a static variable like in other languages (for example C++), you can use this crate. It does lazy initialization to simulate this behavior.

But IMO, in your example, such a feature is overkill. You can simply do this:

fn is_digit(c: char) -> bool {
    match c {
        '0'...'9' => true,
        _ => false,
    }
}

fn main() {
    assert_eq!(is_digit('0'), true);
    assert_eq!(is_digit('5'), true);
    assert_eq!(is_digit('9'), true);
    assert_eq!(is_digit('a'), false);
}

Or even better, use the standard:

fn is_digit(c: char) -> bool {
    c.is_digit(10)
}

About the struct, you are right: constructors do not exist in Rust. The compiler speaks about enum constructors that are different from constructors in other object languages. The best for you is to continue reading the book if you want more information.

like image 92
Boiethios Avatar answered Nov 05 '25 16:11

Boiethios