Problem with nalgebra::DMatrix as a global variable

Hello everyone!

I am brand new to Rust since I am trying to switch away from good old Fortran :slight_smile: I am writing a library for a research project but I got stuck in an apparently very simple problem. I have to make a module variable of type nalgebra::DMatrix global. The module I wrote is very simple containing only the following:

extern crate nalgebra as na;

use na::DMatrix;

let testmat = DMatrix::zeros(10,10);

When building with cargo, these simple lines give me the following error:

error: expected item, found keyword `let`
  --> src/grisbolt_common.rs:11:1
   |
11 | let testmat = DMatrix::zeros(10,10);
   | ^^^ consider using `const` or `static` instead of `let` for global variables

I was not even at the stage of making it a global variable but I do not understand why it doesn't work since the use of "let" is exactly what it is shown in the examples

Thank you in advance for helping me in such a dumb problem :slight_smile:

By convention, and how the tooling works by default, code examples in Rust documentation are the kind of code you can put in functions: statements and items. Outside of functions, you can only put items, and let is not an item, but a kind of statement. let only introduces local, stack-allocated variables, not global ones.

Practically: The code example will compile if you put fn main() { ... } around it.

Rust's global variables are known as static items. However, you should generally use them sparingly, mostly for constant data and rarely for mutable data. If you're used to Fortran, this may be a significant paradigm shift, but it's an important one: we use local variables for all the state of our algorithms, so that those algorithms can be composed into much larger programs without two different invocations of the algorithm (perhaps in different threads, perhaps not) interfering with each other.

1 Like

Thank you for the answer!

In my case since I will determine the shape of this matrix at runtime and at the same time I would like to modify it more than once (this operation would be done on the single-thread part of the code therefore no problem) there are two possibilities that I will write in the following hoping it will be of help for people that may have the same problem in the future:

  1. I use a "static mut" variable. The problem is that changing the constructor line with:
static mut testmat: DMatrix<f64> = DMatrix::zeros(10,10);

lead to the following error:

error[E0015]: cannot call non-const fn `base::construction::<impl Matrix<f64, Dyn, Dyn, <DefaultAllocator as na::allocator::Allocator<f64, Dyn, Dyn>>::Buffer>>::zeros` in statics
  --> src/grisbolt_common.rs:11:36
   |
11 | static mut testmat: DMatrix<f64> = DMatrix::zeros(10,10);
   |                                    ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: calls in statics are limited to constant functions, tuple structs and tuple variants
   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell

therefore I'd have to use an external crate like the suggested "once_cell" or "lazy_static".

OR

  1. I can pass the ownership of the matrix to the different section of the code trying to avoid global variables.

I will try the second since I think is more in the spirit of Rust :slight_smile: thank you again

In new code that you have control over, there's basically never any good reason to use mutable globals. They are unsafe anyway (and for a good reason); you should avoid them. If you need the data in different functions, pass arguments. That's what arguments are for.

1 Like

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.