I have two files I'm working with, main.rs and lib.rs.
main.rs:
use std::io;
use std::io::Write; //My library depends on this line :(
use input_macro_attempt::input;
fn main() {
let x = input!("Enter a variable: ");
println!("The variable is: {}", x);
}
lib.rs:
use std::io;
use std::io::Write; //This one is irrelevant?
#[macro_export]
macro_rules! input{
($a:expr) =>{
{
print!("{}", $a);
std::io::stdout().flush().unwrap();
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
input
}
};
(_) =>{{
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
input
}
};
}
I've experimented but when I remove the use "std::io::Write" from main.rs my code breaks but why?
I didn't like how the output came out with println! so I switched to print! and manually flushed it so that you could put the input on the same line as the message.
Example: Enter the input: Your input
I add it to my lib.rs
and it doesn't make a difference, it only works if my main.rs
has it and I'm a little frustrated because in my lib it ignores the whole use term.
In Rust as in other languages macro expansion is just a sort of text replacement mechanism, (well, ok Rust also checks token types etc but for your question we can ignore that) so you can think of input!("Enter a variable: ")
as being replaced with the contents of the macro at the call site.
If you want to use an include, you have to include it within the macro itself, not the module it's defined in.
#[macro_export]
macro_rules! input {
($a:expr) => {{
use ::std::io::Write;
print!("{}", $a);
::std::io::stdout().flush().unwrap();
let mut input = String::new();
::std::io::stdin().read_line(&mut input).unwrap();
input
}};
(_) => {{
use ::std::io::Write;
let mut input = String::new();
::std::io::stdin().read_line(&mut input).unwrap();
input
}};
}
I use ::
in front of the use
and other std
elements to guarantee I'm not accidentially including a submodule std
of the call site.