1

How can I create a new vector with the iterator Rust macro syntax?

I am trying this:

unsafe { 
    MUT_STATIC_VAR = vec![
       #(#my_outher_vector_data)*,
    ];
}

Full explanation: I am trying to reasign data that I write in one mut static var of type: Vec when the macro it's spanded at compile time. When I try to retrieve the data at runtime, the global it's empty, so I am rewiring the data that I want in main().

Recap. I am just want to assign the content of one vector to another, but neither array or Vec<T> implements ToTokens.

Compiler error:

`main` function not found in crate `my_crate`

Thanks

Alex Vergara
  • 1,766
  • 1
  • 10
  • 29
  • I'm confused. What is `ToTokens`? What does your entire macro look like? How does this relate to global variables? Can you show us the global variable and how you try to reassign it? – Locke Mar 13 '22 at 20:45
  • 1
    Please make a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) that shows exactly what you're writing and what errors you get. – Sprite Mar 13 '22 at 20:46
  • Maybe the explanations of the answer below could clarify someone – Alex Vergara Mar 13 '22 at 21:08
  • The other Vec in the macro is `vec!["dog".to_string(), "cat".to_string(), "mouse".to_string()]` in the main fn as You need it. I took `String` as example for type `T`, as it was not specified in the question. – Kaplan Mar 13 '22 at 21:15
  • Is the code snippet part of your macro, or part of the code that you want your macro to generate? – Peter Hall Mar 13 '22 at 21:54
  • Part of the macro – Alex Vergara Mar 13 '22 at 22:00
  • So... the purpse of this static variable is to cache some tokens so they can be used in multiple places? I think that is unnecessary. – Peter Hall Mar 13 '22 at 22:41
  • They do not caché tokens. They caché other interesting data – Alex Vergara Mar 13 '22 at 23:49

2 Answers2

1

To initialize the content, Iterators are able to use macro #(#...)*, syntax.

let other_as_iter = my_outher_vector_data.iter();


quote {
    unsafe { 
        MUT_STATIC_VAR = vec![
           #(#other_as_iter)*,
        ];
    }
}
Alex Vergara
  • 1,766
  • 1
  • 10
  • 29
  • Despite the complexity of the initialization, the macro can't process dynamic data at runtime… – Kaplan Aug 31 '22 at 11:19
  • This only works for iterators with a single value. For more than one value, a comma needs to be added after each element: `#(#other_as_iter,)*` – Tim Nieradzik Nov 07 '22 at 06:20
-1

I think lazy_static should do the job:

#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;

lazy_static! {
    static ref MUT_STATIC_VAR: Mutex<Vec<String>> = Mutex::new(vec![]);
}

fn other_vec(v: Vec<String>) {
    let mut r = MUT_STATIC_VAR.lock().unwrap();
    r.extend_from_slice(v.as_slice());
}

fn main() {
    other_vec(vec!["dog".to_string(), "cat".to_string(), "mouse".to_string()]);
}

…or draining the other vec after initializing MUT_STATIC_VAR:

fn other_vec(v: &mut Vec<String>) {
    let mut r = MUT_STATIC_VAR.lock().unwrap();
    r.extend_from_slice(v.drain(..).as_slice());
}

fn main() {
    other_vec(&mut vec!["dog".to_string(), "cat".to_string(), "mouse".to_string()]);
}

…or my_other_vector_data wrapped in other_vec! macro:
Playground

macro_rules! other_vec {
    () => {
        vec!["dog", "cat", "mouse"] // my_other_vector_data here
    };
}
Kaplan
  • 2,572
  • 13
  • 14
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/243031/discussion-on-answer-by-kaplan-create-a-vector-with-macro-iterator-syntax). – Samuel Liew Mar 17 '22 at 14:06