Why is a "tuple struct" in rust called "named tuple" - struct

As per this
Tuple structs, which are, basically, named tuples.
// A tuple struct
struct Pair(i32, f32);
Later in the code
// Instantiate a tuple struct
let pair = Pair(1, 0.1);
// Access the fields of a tuple struct
println!("pair contains {:?} and {:?}", pair.0, pair.1);
If this is a "named tuple" why am I accessing it using .0 and .1? How is that different from a "normal tuple"?
let pair = (1, 0.1);
println!("pair contains {:?} and {:?}", pair.0, pair.1);
In Python a named tuple has a name and also allows access via index
from collections import namedtuple
Pair = namedtuple('Pair', ['x', 'y'])
pair = Pair(1, 0.1)
print(pair[0], pair[1]) # 1 0.1
print(pair.x, pair.y) # 1 0.1
So the question, what is the "name" in the "named tuple" in the above rust example? To me the "The classic C structs" (in the same link) is what sounds like a "named tuple" as I can access it using .x and .y if I initialised the struct (Pair) as such. I fail to understand this from the link.

Tuple structs, which are, basically, named tuples.
It is not the instance or members that are named, but the type as a whole.
How is that different from a "normal tuple"?
A function that accepts a Tuple struct will not accept a regular tuple, and vice-versa.
struct Named(f32,i32);
fn accepts_tuple(t:(f32,i32)) { todo!(); }
fn accepts_named(t:Named) { todo!(); }
fn main() {
let t = (1.0f32, 1i32);
accepts_tuple(t); // OK
// accepts_named(t); // Does not compile
let n=Named(1.0f32, 1i32);
// accepts_tuple(n); // Does not compile
accepts_named(n); // OK
}

Related

How to use map function to collect an array of string? [duplicate]

I want to call .map() on an array of enums:
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos = bar.iter().map(|x| Foo::Value(*x)).collect::<[Foo; 3]>();
}
but the compiler complains:
error[E0277]: the trait bound `[Foo; 3]: std::iter::FromIterator<Foo>` is not satisfied
--> src/main.rs:8:51
|
8 | let foos = bar.iter().map(|x| Foo::Value(*x)).collect::<[Foo; 3]>();
| ^^^^^^^ a collection of type `[Foo; 3]` cannot be built from an iterator over elements of type `Foo`
|
= help: the trait `std::iter::FromIterator<Foo>` is not implemented for `[Foo; 3]`
How do I do this?
The issue is actually in collect, not in map.
In order to be able to collect the results of an iteration into a container, this container should implement FromIterator.
[T; n] does not implement FromIterator because it cannot do so generally: to produce a [T; n] you need to provide n elements exactly, however when using FromIterator you make no guarantee about the number of elements that will be fed into your type.
There is also the difficulty that you would not know, without supplementary data, which index of the array you should be feeding now (and whether it's empty or full), etc... this could be addressed by using enumerate after map (essentially feeding the index), but then you would still have the issue of deciding what to do if not enough or too many elements are supplied.
Therefore, not only at the moment one cannot implement FromIterator on a fixed-size array; but even in the future it seems like a long shot.
So, now what to do? There are several possibilities:
inline the transformation at call site: [Value(1), Value(2), Value(3)], possibly with the help of a macro
collect into a different (growable) container, such as Vec<Foo>
...
Update
This can work:
let array: [T; N] = something_iterable.[into_]iter()
.collect::<Vec<T>>()
.try_into()
.unwrap()
In newer version of rust, try_into is included in prelude, so it is not necessary to use std::convert::TryInto. Further, starting from 1.48.0, array support directly convert from Vec type, signature from stdlib source:
fn try_from(mut vec: Vec<T, A>) -> Result<[T; N], Vec<T, A>> {
...
}
Original Answer
as of rustc 1.42.0, if your element impl Copy trait, for simplicity, this just works:
use std::convert::TryInto;
...
let array: [T; N] = something_iterable.[into_]iter()
.collect::<Vec<T>>()
.as_slice()
.try_into()
.unwrap()
collect as_slice try_into + unwrap()
Iterator<T> ------> Vec<T> -------> &[T] ------------------> [T]
But I would just call it a workaround.
You need to include std::convert::TryInto because the try_into method is defined in the TryInto trait.
Below is the signature checked when you call try_into as above, taken from the source. As you can see, that requires your type T implement Copy trait, so theoritically, it will copy all your elements once.
#[stable(feature = "try_from", since = "1.34.0")]
impl<T, const N: usize> TryFrom<&[T]> for [T; N]
where
T: Copy,
[T; N]: LengthAtMost32,
{
type Error = TryFromSliceError;
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
<&Self>::try_from(slice).map(|r| *r)
}
}
While you cannot directly collect into an array for the reasons stated by the other answers, that doesn't mean that you can't collect into a data structure backed by an array, like an ArrayVec:
use arrayvec::ArrayVec; // 0.7.0
use std::array;
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos: ArrayVec<_, 3> = array::IntoIter::new(bar).map(Foo::Value).collect();
let the_array = foos
.into_inner()
.unwrap_or_else(|_| panic!("Array was not completely filled"));
// use `.expect` instead if your type implements `Debug`
}
Pulling the array out of the ArrayVec returns a Result to deal with the case where there weren't enough items to fill it; the case that was discussed in the other answers.
For your specific problem, Rust 1.55.0 allows you to directly map an array:
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos = bar.map(Foo::Value);
}
In this case you can use Vec<Foo>:
#[derive(Debug)]
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let foos = bar.iter().map(|&x| Foo::Value(x)).collect::<Vec<Foo>>();
println!("{:?}", foos);
}
.collect() builds data structures that can have arbitrary length, because the iterator's item number is not limited in general. (Shepmaster's answer already provides plenty details there).
One possibility to get data into an array from a mapped chain without allocating a Vec or similar is to bring mutable references to the array into the chain. In your example, that'd look like this:
#[derive(Debug, Clone, Copy)]
enum Foo {
Value(i32),
Nothing,
}
fn main() {
let bar = [1, 2, 3];
let mut foos = [Foo::Nothing; 3];
bar.iter().map(|x| Foo::Value(*x))
.zip(foos.iter_mut()).for_each(|(b, df)| *df = b);
}
The .zip() makes the iteration run over both bar and foos in lockstep -- if foos were under-allocated, the higher bars would not be mapped at all, and if it were over-allocated, it'd keep its original initialization values. (Thus also the Clone and Copy, they are needed for the [Nothing; 3] initialization).
You can actually define a Iterator trait extension to do this!
use std::convert::AsMut;
use std::default::Default;
trait CastExt<T, U: Default + AsMut<[T]>>: Sized + Iterator<Item = T> {
fn cast(mut self) -> U {
let mut out: U = U::default();
let arr: &mut [T] = out.as_mut();
for i in 0..arr.len() {
match self.next() {
None => panic!("Array was not filled"),
Some(v) => arr[i] = v,
}
}
assert!(self.next().is_none(), "Array was overfilled");
out
}
}
impl<T, U: Iterator<Item = T>, V: Default + AsMut<[T]>> CastExt<T, V> for U { }
fn main () {
let a: [i32; 8] = (0..8).map(|i| i * 2).cast();
println!("{:?}", a); // -> [0, 2, 4, 6, 8, 10, 12, 14]
}
Here's a playground link.
This isn't possible because arrays do not implement any traits. You can only collect into types which implement the FromIterator trait (see the list at the bottom of its docs).
This is a language limitation, since it's currently impossible to be generic over the length of an array and the length is part of its type. But, even if it were possible, it's very unlikely that FromIterator would be implemented on arrays because it'd have to panic if the number of items yielded wasn't exactly the length of the array.
You may combine arrays map method with Iterator::next.
Example:
fn iter_to_array<Element, const N: usize>(mut iter: impl Iterator<Item = Element>) -> [Element; N] {
// Here I use `()` to make array zero-sized -> no real use in runtime.
// `map` creates new array, which we fill by values of iterator.
let res = [(); N].map(|_| iter.next().unwrap());
// Ensure that iterator finished
assert!(matches!(iter.next(), None));
res
}
I ran into this problem myself — here's a workaround.
You can't use FromIterator, but you can iterate over the contents of a fixed-size object, or, if things are more complicated, indices that slice anything that can be accessed. Either way, mutation is viable.
For example, the problem I had was with an array of type [[usize; 2]; 4]:
fn main() {
// Some input that could come from another function and thus not be mutable
let pairs: [[usize; 2]; 4] = [[0, 0], [0, 1], [1, 1], [1, 0]];
// Copy mutable
let mut foo_pairs = pairs.clone();
for pair in foo_pairs.iter_mut() {
// Do some operation or other on the fixed-size contents of each
pair[0] += 1;
pair[1] -= 1;
}
// Go forth and foo the foo_pairs
}
If this is happening inside a small function, it's okay in my book. Either way, you were going to end up with a transformed value of identical type as the same one, so copying the whole thing first and then mutating is about the same amount of effort as referencing a value in a closure and returning some function of it.
Note that this only works if you plan to compute something that is going to be the same type, up to and including size/length. But that's implied by your use of Rust arrays. (Specifically, you could Value() your Foos or Nothing them as you like, and still be within type parameters for your array.)

Flatten vector of enums in Rust

I am trying to flatten a vector of Enum in Rust, but I am having some issues:
enum Foo {
A(i32),
B(i32, i32),
}
fn main() {
let vf = vec![Foo::A(1), Foo::A(2), Foo::B(3, 4)];
let vi: Vec<i32> = vf
.iter()
.map(|f| match f {
Foo::A(i) => [i].into_iter(),
Foo::B(i, j) => [i, j].into_iter(),
})
.collect(); // this does not compile
// I want vi = [1, 2, 3, 4]. vf must still be valid
}
I could just use a regular for loop and insert elements into an existing vector, but that would be no fun. I'd like to know if there is a more idiomatic Rust way of doing it.
Here's a way to do it that produces an iterator (rather than necessarily a vector, as the fold() based solution does).
use std::iter::once;
enum Foo {
A(i32),
B(i32, i32),
}
fn main() {
let vf = vec![Foo::A(1), Foo::A(2), Foo::B(3, 4)];
let vi: Vec<i32> = vf
.iter()
.flat_map(|f| {
match f {
&Foo::A(i) => once(i).chain(None),
&Foo::B(i, j) => once(i).chain(Some(j)),
}
})
.collect();
dbg!(vi);
}
This does essentially the same thing that you were attempting, but in a way which will succeed. Here are the parts I changed, in the order they appear in the code:
I used .flat_map() instead of .map(). flat_map accepts a function which returns an iterator and produces the elements of that iterator ("flattening") whereas .map() would have just given the iterator.
I used & in the match patterns. This is because, since you are using .iter() on the vector (which is appropriate for your requirement “vf must still be valid”), you have references to enums, and pattern matching on a reference to an enum will normally give you references to its elements, but we almost certainly want to handle the i32s by value instead. There are several other things I could have done, such as using the * dereference operator on the values instead, but this is concise and tidy.
You tried to .into_iter() an array. Unfortunately, in current Rust this does not do what you want and you can't actually return that iterator, for somewhat awkward reasons (which will be fixed in an upcoming Rust version). And then, if it did mean what you wanted, then you'd get an error because the two match arms have unequal types — one is an iterator over [i32; 1] and the other is an iterator over [i32; 2].
Instead, you need to build two possible iterators which are clearly of the same type. There are lots of ways to do this, and the way I picked was to use Iterator::chain to combine once(i), an iterator that returns the single element i, with an Option<i32> (which implements IntoIterator) that contains the second element j if it exists.
Notice that in the first match arm I wrote the seemingly useless expression .chain(None); this is so that the two arms have the same type. Another way to write the same thing, which is arguably clearer since it doesn't duplicate code that has to be identical, is:
let (i, opt_j) = match f {
&Foo::A(i) => (i, None),
&Foo::B(i, j) => (i, Some(j)),
};
once(i).chain(opt_j)
In either case, the iterator's type is std::iter::Chain<std::iter::Once<i32>, std::option::IntoIter<i32>> — you don't need to know this exactly, just notice that there must be a type which handles both the A(i) and the B(i, j) cases.
First of all, you need to change the i32 references to owned values by e.g. dereferencing them. Then you can circumvent proxying through inlined arrays by using fold():
enum Foo {
A(i32),
B(i32, i32),
}
fn main() {
let vf = vec![Foo::A(1), Foo::A(2), Foo::B(3, 4)];
let vi: Vec<i32> = vf
.iter()
.fold(Vec::new(), |mut acc, f| {
match f {
Foo::A(i) => acc.push(*i),
Foo::B(i, j) => {
acc.push(*i);
acc.push(*j);
}
}
acc
});
}

How to call a function that returns a generic slice type on Rust

I'm reading the following code from here:
#[inline]
pub fn plane<T: Component>(&self, index: usize) -> &[T] {
if index >= self.planes() {
panic!("out of bounds");
}
if !<T as Component>::is_valid(self.format()) {
As you see, the plane function returns a slice of a generic type. Does that mean I need to always call this function like this: plane::<SomeType>::(my_index)?
The problem is that I don't know which type to use, it's not a type for the entire struct, just for this function and others.
For example, I saw
unsafe impl Component for [u8; 3] {
#[inline(always)]
fn is_valid(format: format::Pixel) -> bool {
format == format::Pixel::RGB24 || format == format::Pixel::BGR24
}
}
Does that mean T can be [u8; 3] and thus plane can return &[&[u8; 3]]?
So should I call self.plane::<u8>(index)? I tried that but I get wrong number of type arguments: expected 0, found 1 on u8. Also I don't think &[&[u8; 3]] is right.
Does that mean I need to always call this function like this: plane::<SomeType>(my_index)?
No, if Rust can infer SomeType, you don't have to provide it explicitly. If you're e.g. assigning the result of plane to a variable that you've given a type, you don't have to provide it in the call.
Does that mean T can be [u8; 3] and thus plane can return &[&[u8; 3]]?
If T is [u8; 3], plane returns &[[u8; 3]].

How do I cope with lazy iterators?

I'm trying to sort an array with a map() over an iterator.
struct A {
b: Vec<B>,
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct B {
c: Vec<i32>,
}
fn main() {
let mut a = A { b: Vec::new() };
let b = B { c: vec![5, 2, 3] };
a.b.push(b);
a.b.iter_mut().map(|b| b.c.sort());
}
Gives the warning:
warning: unused `std::iter::Map` that must be used
--> src/main.rs:16:5
|
16 | a.b.iter_mut().map(|b| b.c.sort());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
= note: iterators are lazy and do nothing unless consumed
Which is true, sort() isn't actually called here. This warning is described in the book, but I don't understand why this variation with iter_mut() works fine:
a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
As the book you linked to says:
If you are trying to execute a closure on an iterator for its side effects, use for instead.
That way it works, and it's much clearer to anyone reading the code. You should use map when you want to transform a vector to a different one.
I don't understand why this variation with iter_mut() works fine:
a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());
It works because find is not lazy; it's an iterator consumer. It returns an Option not an Iterator. This might be why it is confusing you, because Option also has a map method, which is what you are using here.
As others have said, map is intended for transforming data, without modifying it and without any other side-effects. If you really want to use map, you can map over the collection and assign it back:
fn main() {
let mut a = A { b: Vec::new() };
let mut b = B { c: vec![5, 2, 3] };
a.b.push(b);
a.b =
a.b.into_iter()
.map(|mut b| {
b.c.sort();
b
})
.collect();
}
Note that vector's sort method returns (), so you have to explicitly return the sorted vector from the mapping function.
I use for_each.
According to the doc:
It is equivalent to using a for loop on the iterator, although break and continue are not possible from a closure. It's generally more idiomatic to use a for loop, but for_each may be more legible when processing items at the end of longer iterator chains. In some cases for_each may also be faster than a loop, because it will use internal iteration on adaptors like Chain.

What are Some and None?

I came across some output I don't understand using Vec::get. Here's the code:
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i));
}
}
the output is
0 Some(('G', 'H'))
1 Some(('H', '5'))
2 None
I've dabbled in Haskell before, and by that I mean looked at a tutorial site for 10 minutes and ran back to C++, but I remember reading something about Some and None for Haskell. I was surprised to see this here in Rust. Could someone explain why .get() returns Some or None?
The signature of get (for slices, not Vec, since you're using an array/slice) is
fn get(&self, index: usize) -> Option<&T>
That is, it returns an Option, which is an enum defined like
pub enum Option<T> {
None,
Some(T),
}
None and Some are the variants of the enum, that is, a value with type Option<T> can either be a None, or it can be a Some containing a value of type T. You can create the Option enum using the variants as well:
let foo = Some(42);
let bar = None;
This is the same as the core data Maybe a = Nothing | Just a type in Haskell; both represent an optional value, it's either there (Some/Just), or it's not (None/Nothing).
These types are often used to represent failure when there's only one possibility for why something failed, for example, .get uses Option to give type-safe bounds-checked array access: it returns None (i.e. no data) when the index is out of bounds, otherwise it returns a Some containing the requested pointer.
See also:
Why don't Option's Some and None variants need to be qualified?
What is the difference between Some and Option in Rust?
Think of Some and None as the canonical "safe" way of working around the fact that the Rust language does not support "safe" use of NULL pointers. Since the length of your Vec is 3, and you have only specified two pairs, the third pair is effectively NULL; instead of returning NULL, it returns None.
Rust provides safety guarantees by forcing us at compile-time, via Some / None, to always deal with the possibility of None being returned.
command is not a vector (type Vec<T>), it is a fixed-size array (type [(char, char); 2] in your case), and arrays are automatically borrowed into slices (views into arrays), hence you can use all methods defined on slices, including get:
Returns the element of a slice at the given index, or None if the index is out of bounds.
The behavior is pretty obvious: when given index is valid, it returns Some with the element under that index, otherwise it returns None.
There is another way to access elements in a slice - the indexing operator, which should be familiar to you:
let nums = [1, 2, 3];
let x = nums[1];
It returns the element of the slice directly, but it will fail the current task if the index is out of bounds:
fn main() {
let x = [1, 2];
for i in 0..3 {
println!("{}", x[i]);
}
}
This program fails:
% ./main2
1
2
task '<main>' failed at 'index out of bounds: the len is 2 but the index is 2', main2.rs:4
The get() method is needed for convenience; it saves you from checking in advance if the given index is valid.
If you don't know what Some and None really are and why they are needed in general, you should read the official tutorial, it explains it because it is very basic concept.
Option enum has 2 variants.
1- None is used to indicate failure or no value
2- Some which is tuple-struct that wraps the value
If you need to write this structure in OOB, for example in typescript, you would write like this. This would make it easier to visualize the situation
Define Option interface as derived class
interface Option<T = any> {
// pass all the methods here
// unwrap is used to access the wrapped value
unwrap(): T;
}
write Some class which inherits from Option
Some class returns a value
class Some<T> implements Option<T> {
private value: T;
constructor(v: T) {
this.value = v;
}
unwrap(): T {
return this.value
}}
Write None class which also inherits from Option
None class returns null
class None<T> implements Option<T> {
// you do not need constructor here
unwrap(): T {
return null as T;
}
}
The other answers discussing the return type for get() being option enum are accurate, but I think what is helpful is how to remove the some from the prints. To do that a quick way is to just call the unwrap on the option, although this is not production recommended. For a discussion on option take a look at the rust book here.
Updated with unwrap code in playground (below)
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i).unwrap());
}
}

Resources