I've seen a lot of usage of Box::new in Rust language.
https://doc.rust-lang.org/book/ch15-01-box.html
fn main() {
let b = Box::new(5);
println!("b = {}", b);
}
However, I think this is a bit redundant, especially, in the code like this:
enum List {
Cons(i32, Box<List>),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
Now, I want to write in a concise way using Macro as we've seen as vec!
https://doc.rust-lang.org/book/ch19-06-macros.html?highlight=vec#declarative-macros-with-macro_rules-for-general-metaprogramming
let v: Vec<u32> = vec![1, 2, 3];
so that with box! macro, we could write:
fn main() {
let b = box!(5);
println!("b = {}", b);
}
or
fn main() {
let list = Cons(1, box!(Cons(2, box!(Cons(3, box!(Nil))))));
}
My question is
Is there any reason that box! macro is not popular even it's
used frequently in Rust?
What is the proper way to define the macro? Is there any points of attention?
This is a bit subjective, but vectors are used far more often, I believe. And the vec! macro saves you a lot more code compared to the box! macro you are referring to.
As for the macro implementation, you can write something like this:
macro_rules! bx {
($e:expr) => {
Box::new($e)
};
}
Here is an example usage:
let b = Box::new(3);
let m = bx!(7);
Note that I named it bx! and not box!, as the latter is a reserved word in Rust.
however, for some unknown reason Rust guys prefer to use macro for vec! or println!
I suggest asking this the other way around: why couldn't vec! and println! be functions? And the answer is, both are variadic (can take variable number of arguments) and there are no variadic functions in Rust. It's much worse for println!, whose arguments can have different types too; and constraints on those types depend on the first argument! Try writing down a type for println as a function, and you'll find it would be much less usable and less efficient.
The problem vec! solves is smaller. But as Chayim Friedman's comment says, until quite recently you couldn't even have had
Vec::from([1,2,3])
if there were no vec! macro. I think the best you could have done was
Vec::from(&[1,2,3])
As Chayim points out, this is strictly worse than vec!.
Of course, Box::new doesn't have this problem at all. So it's a function just because it didn't have to be a macro.
but as I post the Cons list expample, it's obvious the latter syntax is redundant and does have an issue for readability
In that case box! is no less redundant; instead a way to get rid of redundancy is
fn cons(head: i32, tail: List) -> List {
List::Cons(head, Box::new(tail))
}
and then
let list = cons(1, cons(2, cons(3, Nil)));
Or even a list! macro and
let list = list![1,2,3];
Thanks to #at54321, I googled and found
https://doc.rust-lang.org/beta/unstable-book/language-features/box-syntax.html
#![feature(box_syntax)]
fn main() {
let b = box 5;
}
So, already there.
Related
I'm getting into Rust and Arduino at the same time.
I was programming my LCD display to show a long string by rotating it through the top column of characters. Means: Every second I shift all characters by one position and show the new String.
This was fairly complex in the Arduino language, especially because I had to know the size of the String at compile time (given my limited knowledge).
Since I'd like to use Rust in the long term, I was curious to see if that could be done more easily in a modern language. Not so much.
This is the code I came up with, after hours of experimentation:
#![no_std]
extern crate alloc;
use alloc::{vec::Vec};
fn main() {
}
fn rotate_by<T: Copy>(rotate: Vec<T>, by: isize) -> Vec<T> {
let real_by = modulo(by, rotate.len() as isize) as usize;
Vec::from_iter(rotate[real_by..].iter().chain(rotate[..real_by].iter()).cloned())
}
fn modulo(a: isize, b: isize) -> isize {
a - b * (a as f64 /b as f64).floor() as isize
}
mod tests {
use super::*;
#[test]
fn test_rotate_five() {
let chars: Vec<_> = "I am the string and you should rotate me! ".chars().collect();
let res_chars: Vec<_> = "the string and you should rotate me! I am ".chars().collect();
assert_eq!(rotate_by(chars, 5), res_chars);
}
}
My questions are:
Could you provide an optimized version of this function? I'm aware that there already is Vec::rotate but it uses unsafe code and can panic, which I would like to avoid (by returning a Result).
Explain whether or not it is possible to achieve this in-place without unsafe code (I failed).
Is Vec<_> the most efficient data structure to work with? I tried hard to use [char], which I thought would be more efficient, but then I have to know the size at compile time, which hardly works. I thought Rust arrays would be similar to Java arrays, which can be sized at runtime yet are also fixed size once created, but they seem to have a lot more constraints.
Oh and also what happens if I index into a vector at an invalid index? Will it panic? Can I do this better? Without "manually" checking the validity of the slice indices?
I realize that's a lot of questions, but I'm struggling and this is bugging me a lot, so if somebody could set me straight it would be much appreciated!
You can use slice::rotate_left and slice::rotate_right:
#![no_std]
extern crate alloc;
use alloc::vec::Vec;
fn rotate_by<T>(data: &mut [T], by: isize) {
if by > 0 {
data.rotate_left(by.unsigned_abs());
} else {
data.rotate_right(by.unsigned_abs());
}
}
I made it rotate in-place because that is more efficient. If you don't want to do it in-place you still have the option of cloning the vector first, so this is more flexible than if the function creates a new vector, as you have done, because you aren't be able to opt out of that when you call it.
Notice that rotate_by takes a mutable slice, but you can still pass a mutable reference to a vector, because of deref coercion.
#[test]
fn test_rotate_five() {
let mut chars: Vec<_> = "I am the string and you should rotate me! ".chars().collect();
let res_chars: Vec<_> = "the string and you should rotate me! I am ".chars().collect();
rotate_by(&mut chars, 5);
assert_eq!(chars, res_chars);
}
There are some edge cases with moving chars around like this because some valid UTF-8 will contain grapheme clusters that are made up of multiple codepoints (chars in Rust). This will result in strange effects when a grapheme cluster is split between the start and end of the string. For example, rotating "abcdéfghijk" by 5 will result in "efghijkabcd\u{301}", with the acute accent stranded on its own, away from the 'e'.
If your strings are ASCII then you don't have to worry about that, but then you can also just treat them as byte strings anyway:
#[test]
fn test_rotate_five_ascii() {
let mut chars = b"I am the string and you should rotate me! ".clone();
let res_chars = b"the string and you should rotate me! I am ";
rotate_by(&mut chars, 5);
assert_eq!(chars, &res_chars[..]);
}
I'm writing my first rust program and as expected I'm having problems making the borrow checker happy. Here is what I'm trying to do:
I would like to have a function that allocates some array, stores the array in some global data structure, and returns a reference to it. Example:
static mut global_data = ...
fn f() -> &str {
let s = String::new();
global.my_string = s;
return &s;
};
Is there any way to make something like this work? If not, what is "the rust way"(tm) to get an array and a pointer into it?
Alternatively, is there any documentation I could read? The rust book is unfortunately very superficial on most topics.
There are a couple things wrong with your code:
Using global state is very unidiomatic in rust. It can be done in some specific scenarios, but it should never be a go to method. You cold try wrapping your state in Rc or Arc and share it this way in your program. If you also want to mutate this state (as you show in your example) you must to wrap it also in some kind of interior mutability type. So try Rc<RefCell<State>> if you want to use state in only one thread or Arc<Mutex<State>> if you want to use it from multiple different threads.
Accessing mutable static memory is unsafe. So even the following code won't compile:
static mut x: i32 = 0;
// neither of this lines work!
println!("{}", x);
x = 42;
You must use unsafe to access or modify any static mutable variables, because you must de facto prove to the compiler that you assure it that no data races (from accessing this data from different threads) will occur.
I can't be sure, since you didn't show what type is global_data, but I assume, that my_string is a field of type String. When you write
let s = String::new();
global.my_string = s;
You move ownership of that string to the global. You therefore cannot return (or even create) reference to it. You must do this though it's new owner. &global.my_string could work, but not if you do what I written in 1. You could try to return RefMut of MutexGuard, but that is probably not what you want.
Okay, just in case someone else is having the same question, the following code seems to work:
struct foo {
b : Option<Box<u32>>,
}
static mut global : foo = foo { b : None };
fn f<'a>() -> &'a u32 {
let b : Box<u32> = Box::new(5);
unsafe {
global.b = Some(b);
match &global.b {
None => panic!(""),
Some(a) => return &a,
}
}
}
At least it compiles. Hopefully it will also do the right thing when run.
I'm aware that this is not how you are supposed to do things in rust. But I'm currently trying to figure out how to implement various data structures from scratch, and the above is just a reduced example of one of the problems I encountered.
This question popped into my head (while I wasn't programming), and it actually made me question a lot of things about programming (like in C++, C#, Rust, in particular).
I want to point out, I'm aware there is a similar question on this issue:
Cannot borrow as mutable because it is also borrowed as immutable.
But I believe this question is aiming at a particular situation; a sub-problem. And I want to better understand how to resolve a thing like this in Rust.
The "thing" that I realised recently was that: "If I have a pointer/reference to an element in a dynamic array, and then I add an element, causing the array to expand and reallocate, that would break the pointer. Therefore, I need a special refererence that will always point to the same element even if it re-allocates".
This made me start thinking differently about a lot of things. But outside of that, I am aware that this problem is trivial to experienced c++ programmers. I have simply not come across this situation in my experiences, unfortunately.
So I wanted to see if Rust either had an existing 'special type' for this type of issue, and if not, what would happen if I made my own (for testing). The idea is that this "special pointer" would simply be a pointer to the Vector (List) itself, but also have a i32 field for the index; so it's all bundled under 1 variable that can be 'dereferenced' whenever you need.
Note: "VecPtr" is meant to be a immutable reference.
struct VecPtr<'a, T> {
vec: &'a Vec<T>,
index: usize
}
impl<T: Copy> VecPtr<'_, T> {
pub fn value(&self) -> T {
return self.vec[self.index];
}
}
fn main() {
let mut v = Vec::<i32>::with_capacity(6);
v.push(3);
v.push(1);
v.push(4);
v.push(1);
let r = VecPtr {vec: &v,index: 2};
let n = r.value();
println!("{}",n);
v.push(5); // error!
v.push(9); // error!
v.push(6); // re-allocation triggered // also error!
let n2 = r.value();
println!("{}",n2);
return;
}
So the above example code is showing that you can't have an existing immutable reference while also trying to have a mutable reference at the same time. good!
From what I've read from the other StackOverflow question, one of the reasons for the compiler error is that the Vector could re-allocate it's internal array at any time when it is calling "push". Which would invalidate all references to the internal array.
Which makes 100% sense. So as a programmer, you may desire to still have references to the array, but they are designed to be a bit more safer. Instead of a direct pointer to the internal array, you just have a pointer to the vector itself in question, and include an i32 index so you know the element you are looking at. Which means the dangling pointer issue that would occur at v.push(6); shouldn't happen any more. But yet the compiler still complains about the same issue. Which I understand.
I suppose it's still concerned about the reference to the vector itself, not the internals. Which makes things a bit confusing. Because there are different pointers here that the compiler is looking at and trying to protect. But to be honest, in the example code, the pointer to vec itself looks totally fine. That reference doesn't change at all (and it shouldn't, from what I can tell).
So my question is, is there a practice at which you can tell the compiler your intentions with certain references? So the compiler knows there isn't an issue (other than the unsafe keyword).
Or alternatively, is there a better way to do what I'm trying to do in the example code?
After some more research
It looks like one solution here would be to use reference counting Rc<T>, but I'm not sure that's 100% it.
I would normally not ask this question due to there being a similar existing question, but this one (I think) is investigating a slightly different situation, where someone (or me) would try to resolve an unsafe reference situation, but the compiler still insists there is an issue.
I guess the question comes down to this: would you find this acceptable?
fn main() {
let mut v = Vec::<i32>::with_capacity(6);
v.push(3);
v.push(1);
v.push(4);
v.push(1);
let r = VecPtr { vec: &v, index: 2 };
let n = r.value();
println!("{}",n);
v[2] = -1;
let n2 = r.value(); // This returned 4 just three lines ago and I was
// promised it wouldn't change! Now it's -1.
println!("{}",n2);
}
Or this
fn main() {
let mut v = Vec::<i32>::with_capacity(6);
v.push(3);
v.push(1);
v.push(4);
v.push(1);
let r = VecPtr { vec: &v, index: 2 };
let n = r.value();
println!("{}",n);
v.clear();
let n2 = r.value(); // This exact same thing that worked three lines ago will now panic.
println!("{}",n2);
}
Or, worst of all:
fn main() {
let mut v = Vec::<i32>::with_capacity(6);
v.push(3);
v.push(1);
v.push(4);
v.push(1);
let r = VecPtr { vec: &v, index: 2 };
let n = r.value();
println!("{}",n);
drop(v);
let n2 = r.value(); // Now you do actually have a dangling pointer.
println!("{}",n2);
}
Rust's answer is an emphatic "no" and that is enforced in the type system. It's not just about the unsoundness of dereferencing dangling pointers, it's a core design decision.
Can you tell the compiler your intentions with certain references? Yes! You can tell the compiler whether you want to share your reference, or whether you want to mutate through it. In your case, you've told the compiler that you want to share it. Which means you're not allowed to mutate it anymore. And as the examples above show, for good reason.
For the sake of this, the borrow checker has no notion of the stack or the heap, it doesn't know what types allocate and which don't, or when a Vec resizes. It only knows and cares about moving values and borrowing references: whether they're shared or mutable and for how long they live.
Now, if you want to make your structure work, Rust offers you some possibilities: One of those is RefCell. A RefCell allows you to borrow a mutable reference from an immutable one at the expense of runtime checking that nothing is aliased incorrectly. This together with an Rc can make your VecPtr:
use std::cell::RefCell;
use std::rc::Rc;
struct VecPtr<T> {
vec: Rc<RefCell<Vec<T>>>,
index: usize,
}
impl<T: Copy> VecPtr<T> {
pub fn value(&self) -> T {
return self.vec.borrow()[self.index];
}
}
fn main() {
let v = Rc::new(RefCell::new(Vec::<i32>::with_capacity(6)));
{
let mut v = v.borrow_mut();
v.push(3);
v.push(1);
v.push(4);
v.push(1);
}
let r = VecPtr {
vec: Rc::clone(&v),
index: 2,
};
let n = r.value();
println!("{}", n);
{
let mut v = v.borrow_mut();
v.push(5);
v.push(9);
v.push(6);
}
let n2 = r.value();
println!("{}", n2);
}
I'll leave it to you to look into how RefCell works.
So for easy initialization of a vector there is there vec! macro.
let mut vec_of_zeroes: Vec<usize> = vec![0;10];
I was wondering if there was an easy standard macro for initializing a linked list too?
use std::collections::LinkedList;
let mut list_of_zeroes: LinkedList<usize> = /*macro here?*/;
If not, no worries. Thanks for you time.
No, there is no such macro in the standard library. Indeed, there is no analogous macro for any other data structure, even HashMap / BTreeMap, which are much more frequently used.
However, the crate velcro provides a linked_list! macro that does what you want (and has some other neat features).
Note that std::collections::LinkedList lacks some features that make linked lists attractive - there is no cursor-based API, for instance. In most cases you should probably use Vec or VecDeque instead.
There is no linked list macro, but you could use the .extend() method to achieve something similar:
use std::collections::LinkedList;
fn main() {
let mut a: LinkedList<u32> = LinkedList::new();
a.extend(&[0; 10]);
println!("{:?}", a);
}
Playground
If you want to have a single line initialization, you could use some other iterator methods as suggested by #Stargateur in the comments. This method also allows the variable to be immutable, if you wanted that for some reason.
use std::collections::LinkedList;
fn main() {
let a: LinkedList<u32> = [0; 10].iter().copied().collect();
println!("{:?}", a);
}
Playground
I want to write a macro_rules based macro that will be used to wrap a series of type aliases and struct definitions. I can match on "items" with $e:item, but this will match both aliases and structs. I would like to treat the two separately (I need to add some #[derive(...)] just on the structs). Do I have to imitate their syntax directly by matching on something like type $name:ident = $type:ty; or is there a better way? This route seems annoying for structs because of regular vs tuple like. If I also wanted to distinguish functions that would be really painful because they have a lot of syntactical variation.
I believe for that problem somewhat simple cases can be solved with macro_rules!, but that probably would be limited (you can't lookahead) and super error-prone. I only cover an example for types, I hope that would be convincing enough to avoid macro_rules!. Consider this simple macro:
macro_rules! traverse_types {
($(type $tp:ident = $alias:ident;)*) => {
$(type $tp = $alias;)*
}
}
traverse_types!(
type T = i32;
type Y = Result<i32, u64>;
);
That works fine for the trivial aliases. At some point you probably also would like to handle generic type aliases (i.e. in the form type R<Y> = ...). Ok, your might still rewrite the macro to the recursive form (and that already a non-trivial task) to handle all of cases. Then you figure out that generics can be complex (type-bounds, lifetime parameters, where-clause, default types, etc):
type W<A: Send + Sync> = Option<A>;
type X<A: Iterator<Item = usize>> where A: 'static = Option<A>;
type Y<'a, X, Y: for<'t> Trait<'t>> = Result<&'a X, Y>;
type Z<A, B = u64> = Result<A, B>;
Probably all of these cases still can be handled with a barely readable macro_rules!. Nevertheless it would be really hard to understand (even to the person who wrote it) what's going on. Besides, it is hard to support new syntax (e.g. impl-trait alias type T = impl K), you may even need to have a complete rewrite of the macro. And I only cover the type aliases part, there's more to handle for the structs.
My point is: one better avoid macro_rules! for that (and similar) problem(-s), procedural macros is a way much a better tool for that. It easier to read (and thus extend) and handles new syntax for free (if syn and quote crates are maintained). For the type alias this can be done as simple as:
extern crate proc_macro;
use proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream};
struct TypeAliases {
aliases: Vec<syn::ItemType>,
}
impl Parse for TypeAliases {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut aliases = vec![];
while !input.is_empty() {
aliases.push(input.parse()?);
}
Ok(Self { aliases })
}
}
#[proc_macro]
pub fn traverse_types(token: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(token as TypeAliases);
// do smth with input here
// You may remove this binding by implementing a `Deref` or `quote::ToTokens` for `TypeAliases`
let aliases = input.aliases;
let gen = quote::quote! {
#(#aliases)*
};
TokenStream::from(gen)
}
For the struct parsing code is the same using ItemStruct type and also you need a lookahead to determine wether it's an type-alias or a struct, there's very similar example at syn for that.