I am very new to Rust and I was wondering if it's possible to define a tuple as a struct member. Something like:
struct MyStruct {
(x, y) : (u32, f32)
}
The compiler complains about the first comma, so this obviously isn't the right syntax. Is it even possible? I Can't find anything in the documentation, and if I search for tuple and struct I get results for tuple structs which is not what I'm looking for.
For anyone interested why I want to know this, I have a function that returns a tuple and I want to store the result inside a member of a struct. Currently I am calling the function on two temporary variables and then moving the results into two different struct members, but not sure if this is the right way to do it.
A tuple is a single variable which contains 2 values so when you define it in your struct it is still a single variable/field:
struct MyStruct {
x: (u32, f32),
}
Related
Back here with learning macros,
I'm wondering if a macro can generate a struct and return it.
I'm trying to iterate over multiple components in a ecs. I've managed to write the functions to iterate over one component type, and over all pairs of components, in a way that could be expanded to any number of component types.
So now, I want to make a macro that automate the process. The macro should :
create a struct that will be the iterator, and that will be returned
implement the Iterator trait on that struct
build an instance of that struct and return it.
you can see On the git page the implementations of the iterator, the structs, and the functions for 1 and 2 components, and they can be super easily extended (at the end of the file).
Here is what I'm trying for now :
#[macro_export]
macro_rules! iterate_over_component {
($ecs:expr; $($comp:ty),+) => {
// create the result struct that will act as an iterator
struct ComponentIterator<$($comp),+> {
current_iterator: usize,
current_entity: usize,
$(
array_$comp: Option<&'a Vec<IndexedElem<$comp>>>,
current_index_$comp: usize,
)*
}
};
}
But I'm having lots of issues :
It doesn't seems the ty keyword accepts types ? I would like to call the macro like so : iterate_over_component!(ecs; Position, Velocity) (where Position and Velocity are structs types)
I'm having errors when using the struct keyword at the beginning of the macro, so can I really declare structs in there ?
In rust, I have a function that generates a vector of Strings, and I'd like to return this vector along with a reference to one of the strings. Obviously, I would need to appropriately specify the lifetime of the reference, since it is valid only when the vector is in scope. However, but I can't get this to work.
Here is a minimal example of a failed attempt:
fn foo<'a>() -> ('a Vec<String>, &'a String) {
let x = vec!["some", "data", "in", "the", "vector"].iter().map(|s| s.to_string()).collect::<Vec<String>>();
(x, &x[1])
}
(for this example, I know I could return the index to the vector, but my general problem is more complex. Also, I'd like to understand how to achieve this)
Rust doesn't allow you to do that without unsafe code. Probably your best option is to return the vector with the index of the element in question.
This is conceptually very similar to trying to create a self-referential struct. See this for more on why this is challenging.
So I have a function that returns a tuple of 2 values, and I want to assign these values to two different members of a struct. Is there a way to do this without having to call the function twice and extract each value individually?
I'm thinking something like:
let mut my_struct : MyStruct = MyStruct {
(member1, member2): function_that_returns_tuple()
}
Currently I am calling the function on two temporary variables and then moving them to the struct members but I'm wondering if there's a way to do it directly in the initialization.
I believe that your existing approach is the correct one. If you name the variables as the struct members, you can avoid the explicit member: value syntax:
let (member1, member2) = function_that_returns_tuple();
MyStruct { member1, member2, }
I found four different ways to create a struct with no data:
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
struct C(()); // unit-valued tuple struct
struct D; // unit struct
(I'm leaving arbitrarily nested tuples that contain only ()s and single-variant enum declarations out of the question, as I understand why those shouldn't be used).
What are the differences between these four declarations? Would I use them for specific purposes, or are they interchangeable?
The book and the reference were surprisingly unhelpful. I did find this accepted RFC (clarified_adt_kinds) which goes into the differences a bit, namely that the unit struct also declares a constant value D and that the tuple structs also declare constructors B() and C(_: ()). However it doesn't offer a design guideline on why to use which.
My guess would be that when I export them with pub, there are differences in which kinds can actually be constructed outside of my module, but I found no conclusive documentation about that.
There are only two functional differences between these four definitions (and a fifth possibility I'll mention in a minute):
Syntax (the most obvious). mcarton's answer goes into more detail.
When the struct is marked pub, whether its constructor (also called struct literal syntax) is usable outside the module it's defined in.
The only one of your examples that is not directly constructible from outside the current module is C. If you try to do this, you will get an error:
mod stuff {
pub struct C(());
}
let _c = stuff::C(()); // error[E0603]: tuple struct `C` is private
This happens because the field is not marked pub; if you declare C as pub struct C(pub ()), the error goes away.
There's another possibility you didn't mention that gives a marginally more descriptive error message: a normal struct, with a zero-sized non-pub member.
mod stuff {
pub struct E {
_dummy: (),
}
}
let _e = stuff::E { _dummy: () }; // error[E0451]: field `_dummy` of struct `main::stuff::E` is private
(Again, you can make the _dummy field available outside of the module by declaring it with pub.)
Since E's constructor is only usable inside the stuff module, stuff has exclusive control over when and how values of E are created. Many structs in the standard library take advantage of this, like Box (to take an obvious example). Zero-sized types work in exactly the same way; in fact, from outside the module it's defined in, the only way you would know that an opaque type is zero-sized is by calling mem::size_of.
See also
What is an idiomatic way to create a zero-sized struct that can't be instantiated outside its crate?
Why define a struct with single private field of unit type?
struct D; // unit struct
This is the usual way for people to write a zero-sized struct.
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
These are just special cases of basic struct and tuple struct which happen to have no parameters. RFC 1506 explains the rational to allow those (they didn't used to):
Permit tuple structs and tuple variants with 0 fields. This restriction is artificial and can be lifted trivially. Macro writers dealing with tuple structs/variants will be happy to get rid of this one special case.
As such, they could easily be generated by macros, but people will rarely write those on their own.
struct C(()); // unit-valued tuple struct
This is another special case of tuple struct. In Rust, () is a type just like any other type, so struct C(()); isn't much different from struct E(u32);. While the type itself isn't very useful, forbidding it would make yet another special case that would need to be handled in macros or generics (struct F<T>(T) can of course be instantiated as F<()>).
Note that there are many other ways to have empty types in Rust. Eg. it is possible to have a function return Result<(), !> to indicate that it doesn't produce a value, and cannot fail. While you might think that returning () in that case would be better, you might have to do that if you implement a trait that dictates you to return Result<T, E> but lets you choose T = () and E = !.
Situation:
I have a situation where I would like to call some method defined on the Iterator trait on a function parameter. The function that I would like to call it is taking a parameter of a type which is a trait called VecLike. The function is called get_all_matching_rules.
get_all_matching_rules can receive either a Vec or another similar home made type which also implements Iterator. Of course both of these implement VecLike. I was thinking of adding a function on VecLike to have it return an Iterator so that I could use it in get_all_matching_rules.
If my parameter is named: matching_rules I could then do matching_rules.iter().filter(.
Question:
How do I return a non consuming iterator from a Vec?
I'd like to be able to return a non consuming iterator on a Vec<T> of type Iterator<T>. I am not looking to iterate the items by calling .iter().
If I have (where self is a Vec):
fn iter<'a>(&'a self) -> Iterator<T> {
self.iter()
}
I get the following error:
error: mismatched types: expected `core::iter::Iterator<T>+'a`, found `core::slice::Items<'_,T>` (expected trait core::iter::Iterator, found struct core::slice::Items)
I would like to return the Iterator<t>. If there is a better way to go at this rather than returning an Iterator, I'm all ears.
.iter() on [T], which Vec<T> automatically dereferences to, takes self by reference and produces a type implementing Iterator<&T>. Note that the return type is not Iterator<&T>; Iterator is a trait which is implemented by concrete types, and the concrete type Items<T> is the return type in that case, not Iterator<&T>. There is not currently any syntax for specifying a return type merely as a trait that is implemented by it, though the syntax impl Iterator<&T> has been suggested.
Now you wish something implementing Iterator<T> rather than Iterator<&T>. Under Rust’s memory model where each object is owned by exactly one thing, this is not possible with the same objects; there must be some constraint to allow you to get a new T from the &T. There are two readily provided solutions for this:
The Copy trait, for types that can just be copied bitwise. Given a variable of a type implementing Iterator<&T> where T is Copy, this can be written .map(|&x| x) or .map(|x| *x) (the two are equivalent).
The Clone trait, for any types where the operation can be caused to make sense, regardless of Copy bounds. Given a variable of a type implementing Iterator<&T> where T is Clone, this can be written .map(|x| x.clone()).
Thus, given a vector v, v.iter().map(|x| x.clone()). Generically, something like this:
fn iter<T: Clone>(slice: &[T]) -> Map<&T, T, Items<T>> {
slice.iter().map(|x| x.clone())
}
I'm not sure what you're asking here.
.iter() creates an iterator (Items) which does not move the Vec (You'll get an Iterator over &T).
Filter (and most other iterator adapters) are lazy. Perhaps you should chain() the two iterators before filtering them?
Otherwise, if you don't want the Filter to be consumed, clone it.