In many languages (Fortran, Matlab/Octave, Julia, etc) an expression like sum(array,n) will sum the values of an array along the n:th dimension and outputting an array of one lower dimensionality. Is there something equivalent in Rust?
I tried:
fn main() {
let arr1: [f64; 5] = [1.1, 1.2, 2.3, 3.4, 4.5555];
println!("this {}", arr1.iter().sum())
}
with this error:
error[E0282]: unable to infer enough type information about `_`
--> src/main.rs:3:37
|
3 | println!("this {}", arr1.iter().sum())
| ^^^ cannot infer type for `_`
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:3:5: 3:43 note: in this expansion of println! (defined in <std macros>)
|
= note: type annotations or generic parameter binding required
In this case you have to explicitly specify type of the elements:
println!("this {}", arr1.iter().sum::<f64>())
You were very close :)
Another option that were suggested by #E_net4 is to use separate binding:
let res: f64 = arr1.iter().sum();
println!("this {}", res)
The "unable to infer enough type information about _" error message is explained in a few other questions. See Error: unable to infer enough type information about `_`; type annotations or generic parameter binding required and Unable to infer enough type information about _; type annotations or generic parameter binding required. Basically, it means that the compiler doesn't have enough information to specify all type parameters in a function or a data type.
Nevertheless, this particular case may arouse some confusion: why can't Iterator.sum() just infer the resulting sum's type to the iterator's Item? By supposedly adding up f64s, we'd be expecting f64 as an outcome, right? Well, the method sum is actually defined like this:
fn sum<S>(self) -> S
where S: Sum<Self::Item>
Where S implements another kind of sum function (see trait Sum) that takes an iterator:
pub trait Sum<A = Self> {
fn sum<I>(iter: I) -> Self where I: Iterator<Item=A>;
}
This trait gives us the freedom to sum numbers and references to numbers alike:
static MAGIC_CODE: u32 = 0xDEADBEEF;
static BLAND_CODE: u32 = 0x1234ABCD;
fn main() {
let sum1: u32 = vec![MAGIC_CODE, BLAND_CODE] // vec! infers to Vec<u32>
.into_iter().sum();
let sum2 = vec![&MAGIC_CODE, &BLAND_CODE] // vec! infers to Vec<&u32>
.into_iter().sum::<u32>();
assert_eq!(sum1, sum2);
}
On the other hand, this also means that the definition of a sum becomes more loose: any other data type implementing Sum<u32> (or Sum<&u32>) could take its place in the code above, which leads to the aforementioned ambiguity. For the purpose of demonstration, this code also compiles:
use std::iter::Sum;
struct Accumulator(bool);
impl Sum<u32> for Accumulator {
fn sum<I: Iterator<Item = u32>>(mut iter: I) -> Self {
Accumulator(iter.any(|v| v != 0))
}
}
fn main() {
let sum3: Accumulator = {
let data = vec![MAGIC_CODE, BLAND_CODE];
data.into_iter().sum()
};
assert!(sum3.0);
}
Full code on Playground.
Related
I have a custom struct using a type parameter, as such:
struct Foo<'a, T: ?Sized> {
parser: &'a dyn Fn(&str) -> Box<T>,
value: Option<Box<T>>
}
As the T: ?Sized indicates, the size of an element of type Foo does not change depending on the size of T (thanks to the Boxes).
I want to put multiple Foo elements in an array, with the elements being able to have a different T, and pass it on to a function.
To do it, I tried something along those lines:
fn parse_all<'a, T>(args: &mut [&mut Foo<'a, T>]) where T: Any;
fn main() {
let a: Foo<i32> = Foo{parser = ..., value = None};
let b: Foo<String> = Foo{parser = ..., value = None};
parse_all(&mut[&mut a, &mut b]);
}
Of course it fails, as a and b have a different T type.
The idea is that I don't need to know the exact type of the elements of the arrays, as the Foo::parser function pointer will handle them. Additionally, all of them are of a constant size so I shouldn't have size issues.
Can I bypass the fact that each element of an array have exactly the same and have a and b of different actual types by using Foo? (as in C for instance where we can cast a void* to any pointer type)
By the way, the array can be of any size, so I can't use tuples as far as I am aware.
The issue with creating an array is not that each Foo<T> will have a different size - as you pointed our they will be the same. However, each one will potentially have a different type which is extra information that would somehow need to be stored, and Rust doesn't support this for arrays.
Since you don't seem to care what the resulting type is during parsing, instead of a generic parameter in Foo, you can use Box<dyn Any> and then only downcast when you extract the result:
struct Foo<'a> {
parser: &'a dyn Fn(&str) -> Box<dyn Any>,
value: Option<Box<dyn Any>>,
}
impl Foo<'_> {
fn try_extract<T: 'static>(&mut self) -> Option<Box<T>> {
if let Some(val) = self.value.take() {
match val.downcast::<T>() {
Ok(x) => Some(x),
Err(x) => {
self.value = Some(x);
None
}
}
} else {
None
}
}
}
In your code you don't pass any strings to parse_all, but I don't see what that could accomplish, so I've modified it slightly for the working example: playground
Note that this won't work if T is unsized since Box::downcast requires T: Sized.
You will also need to somehow store the types that you want to decode to independently of the array of parsers, but it's difficult to suggest a good approach to do this without seeing more of your code.
All elements of an array must be of the same type. However, that type can be a trait object, such as Box<dyn FooTrait> or &mut dyn FooTrait for a custom trait FooTrait.
You can define the trait and implement it for all your Foo types, with some common interface that you can call without knowing the specific type T:
trait FooTrait {
fn do_something(&mut self);
}
impl<'a, T> FooTrait for Foo<'a, T> {
fn do_something(&mut self) {
unimplemented!()
}
}
Because &mut T is automatically cast into &mut dyn FooTrait if T: FooTrait, you can use that instead in your function signature:
fn parse_all(args: &mut [&mut dyn FooTrait]) {
// ^^^^^^^^^^^^
for arg in args {
arg.do_something();
}
}
fn main() {
let mut a: Foo<i32> = Foo{parser = ..., value = None};
let mut b: Foo<String> = Foo{parser = ..., value = None};
parse_all(&mut[&mut a, &mut b]);
}
And it doesn't really matter if all of the Foo<T> are the same size, since only the references (which are always the same size) are stored in the array. So you can remove the usage of Box as well in your Foo struct if you want to avoid that heap allocation:
struct Foo<'a, T> {
parser: &'a dyn Fn(&str) -> T,
value: Option<T>
}
I'd like to achieve the following but can't fix the error: "Non-nominal type 'Element' does not support explicit initialization"
Original attempt:
public extension Array where Element: FloatingPointMathType {
func mean<Element>() -> Element {
let sum: Element = reduce (0.0, +) as! Element
return sum / Element(count) // ==> Non-nominal type 'Element' does not support explicit initialization
}
}
Also, I wonder why it requires the as! Element cast
As a comparaison, a local function as follows compiles with no issue:
func mean<Element: FloatingPointMathType>(_ e: [Element]) -> Element {
let sum: Element = e.reduce (0.0, +)
return sum / Element(e.count)
}
It's impossible to say what the problem is exactly, because we don't know how your FloatingPointMathType protocol is defined. There are a few issues in your implementation (chiefly, you don't want to define a generic function mean<Element>; the extension is already parametrized over the Element type, and the generic parameter is introducing a new type name that shadows it (and that new type is unbound, so you can't do anything with it).
The following works with the standard library's FloatingPoint protocol:
public extension Collection where Element: FloatingPoint {
func mean() -> Element {
reduce(into: 0, +=) / Element(count)
}
}
It is legal to say this (arr is an Array):
let arrenum = Array(arr.enumerated())
So why isn't it legal to say this?
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
EDIT It seems this is a workaround:
extension Array {
func f() {
typealias Tup = (offset:Index, element:Element)
let arrenum = Array<Tup>(self.enumerated())
}
}
But why is that needed? (And is it right?)
This is a known bug (SR-1789). Swift currently has a feature where you can refer to a generic type within its own body without having to repeat its placeholder type(s) – the compiler will infer them for you to be the same as the type of self.
For example:
struct S<T> {
func foo(_ other: S) { // parameter inferred to be `S<T>`.
let x = S() // `x` inferred to be `S<T>`.
}
}
extension S {
func bar(_ other: S) {} // same in extensions too.
}
This is pretty convenient, but the bug you're running into is the fact that Swift will always make this inference, even if it's incorrect.
So, in your example:
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
Swift interprets the code as let arrenum = Array<Element>(self.enumerated()), as you're in the body of Array<Element>. This is incorrect, because enumerated() yields a sequence of offset-element tuple pairs – Swift should have inferred Array to be Array<(offset: Int, element: Element)> instead.
One workaround, which you've already discovered, is to explicitly specify the placeholder type in order to prevent the compiler from making this incorrect inference.
extension Array {
func f() {
let arrenum = Array<(offset: Int, element: Element)>(self.enumerated())
}
}
Another possible workaround appears to be using the fully-qualified type, for example:
extension Array {
func f() {
let arrenum = Swift.Array(self.enumerated())
}
}
as it appears Swift doesn't do the same inference for fully-qualified types (I'm not sure if you should rely on this fact though).
Finally it's worth noting that instead of doing a call to Array's initialiser, you could use map(_:) instead to avoid the issue entirely:
extension Array {
func f() {
let arrenum = self.enumerated().map { $0 }
}
}
which, like the initialiser call, will give you back an array of offset-element pairs.
I wanted to extend an array of UInt8 values so I wrote this code in Swift 3:
extension Array where Element: UInt8 {
}
But I got this error:
Type 'Self.Generator.Element' constrained to non-protocol type 'UInt8'
So how do I fix it?
The syntax Element: X means you want to inpose a type constraint on Element that is defined by X, where X must be a protocol or a class from which Element is derived. As a workaround if you'd like to construct an extension to Array which is only available to arrays with (value type) element UInt8, you could define a protocol to which only UInt8 conforms, and use this protocol as a type constraint in the extension. E.g.
protocol MyType {}
extension UInt8: MyType {}
extension Array where Element: MyType {
// ...
}
At its current implementation, any code within the extension knows nothing more about the Element type than what is blueprinted in the MyType protocol (i.e., currently, nothing). Depending on what you want to achieve with your extension, you could add blueprints to MyType that you know are already fulfilled by implementations available to UInt8, e.g. some initializer. But a more sensible approach is to make use of the fact that UInt8 conforms to the useful protocols UnsignedInteger, Equatable and Comparable. By using protocol composition, all methods blueprinted by these protocols can be readily available to Element:s in the extension, however restricting these elements to type conforming to your own protocol MyType (i.e., only UInt8):
protocol MyType {}
extension UInt8: MyType {}
extension Array where Element: MyType & UnsignedInteger {
mutating func superfluouslyReplaceAllElements(with value: Element) {
self = self.map { $0.advanced(by: $0.distance(to: value)) }
} /* using 'advanced(by:)' and 'distance(to:)' methods of
'Element', blueprinted in 'UnsignedInteger', to which
'Element' conforms */
mutating func elementsSquaredWithOverflow() -> Bool {
var overflow = false
self = self.map {
let result = Element.multiplyWithOverflow($0, $0)
overflow = overflow || result.overflow
return result.0
}
return overflow // did at least one element cause an arithmetic overflow?
}
}
var foo: [UInt8] = [14, 87, 13, 240]
print(foo.elementsSquaredWithOverflow()) // true (at least one arithmetic overflow)
print(foo) // [196, 145, 169, 0]
foo.superfluouslyReplaceAllElements(with: 42)
print(foo) // 42, 42, 42, 42
var bar: [UInt16] = [14, 87, 13, 240]
bar.superfluouslyReplaceAllElements(with: 42)
/* error: type 'UInt16' does not conform to protocol 'MyType'
OK, as expected! */
This is just a short lesson in protocols and type constraints, however; if you intend to work with UInt8 sequences in the context of bytes, follow #vadian:s advice in his comment to your question.
I'm very new to Rust, coming from C# / Java / similar.
In C# we have IEnumerable<T> that can be used to iterate almost any kind of array or list. C# also has a yield keyword that you can use to return a lazy list. Here's an example...
// Lazily returns the even numbers out of an enumerable
IEnumerable<int> Evens(IEnumerable<int> input)
{
foreach (var x in input)
{
if (x % 2 == 0)
{
yield return x;
}
}
}
This is a silly example of course. I know I could do this with Rust's map function, but I would like to know how to create my own methods that accept and return generic iterators.
From what I can gather, Rust has generic iterators that can be use similarly, but they are above my understanding. I see Iter, IntoIterator, Iterator types, and probably more in documentation, but no good way to understand them.
Can anyone provide clear examples of how to create something like above? Thank you!
P.S. The lazy aspect is optional. I am more concerned with abstraction away from specific list and array types.
First, forget about IntoIterator and other traits or types. The core iteration trait in Rust is Iterator. Its trimmed down definition is as follows:
trait Iterator {
type Item; // type of elements returned by the iterator
fn next(&mut self) -> Option<Self::Item>;
}
As you probably know, you can think of an iterator as a cursor inside of some structure. next() method advances this cursor forward, returning an element it pointed at previously. Naturally, if the collection is exhausted, there is nothing to return, and so next() returns Option<Self::Item>, not just Self::Item.
Iterator is a trait, and so it can be implemented by specific types. Note that Iterator itself is not a proper type which you can use as a return value or a function argument - you have to use concrete types which implement this trait.
The above statement may sound too restrictive - how to use arbitrary iterator types then? - but because of generics this is not so. If you want a function to accept arbitrary iterators, just make it generic in the corresponding argument, adding an Iterator bound over the corresponding type parameter:
fn iterate_bytes<I>(iter: I) where I: Iterator<Item=u8> { ... }
Returning iterators from functions may be difficult, but see below.
For example, there is a method on &[T], called iter(), which returns an iterator which yields references into the slice. This iterator is an instance of this structure. You can see on that page how Iterator is implemented for Iter:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> { ... }
...
}
This structure holds a reference to the original slice and some iteration state inside it. Its next() method updates this state and returns the next value, if there is any.
Any value whose type implements Iterator can be used in a for loop (for loop in fact works with IntoIterator, but see below):
let s: &[u8] = b"hello";
for b in s.iter() {
println!("{}", b); // prints numerical value of each byte
}
Now, Iterator trait is actually more complex than the above one. It also defines a lot of transformation methods which consume the iterator they are called on and return a new iterator which somehow transforms or filters values from the original iterator. For example, enumerate() method returns an iterator which yields values from the original iterator together with the positional number of the element:
let s: &[u8] = b"hello";
for (i, b) in s.iter().enumerate() {
println!("{} at {}", b, i); // prints "x at 0", "y at 1", etc.
}
enumerate() is defined like this:
trait Iterator {
type Item;
...
fn enumerate(self) -> Enumerate<Self> {
Enumerate {
iter: self,
count: 0
}
}
...
}
Enumerate is just a struct which contains an iterator and a counter inside it and which implements Iterator<Item=(usize, I::Item)>:
struct Enumerate<I> {
iter: I,
count: usize
}
impl<I> Iterator for Enumerate<I> where I: Iterator {
type Item = (usize, I::Item);
#[inline]
fn next(&mut self) -> Option<(usize, I::Item)> {
self.iter.next().map(|a| {
let ret = (self.count, a);
self.count += 1;
ret
})
}
}
And this is how most iterator transformations are implemented: each transformation is a wrapping struct which wraps the original iterator and implements Iterator trait by delegating to the original iterator and transforming the resulting value somehow. For example, s.iter().enumerate() from the example above returns a value of type Enumerate<Iter<'static, u8>>.
Note that while enumerate() is defined in Iterator trait directly, it can be a standalone function as well:
fn enumerate<I>(iter: I) -> Enumerate<I> where I: Iterator {
Enumerate {
iter: iter,
count: 0
}
}
The method works very similarly - it just uses implicit Self type parameter instead of an explicitly named one.
You may wonder what IntoIterator trait is. Well, it is just a convenience conversion trait which can be implemented by any type which can be converted to an iterator:
pub trait IntoIterator where Self::IntoIter::Item == Self::Item {
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
For example, &'a [T] can be converted into Iter<'a, T>, and so it has the following implementation:
impl<'a, T> IntoIterator for &'a [T] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter() // just delegate to the existing method
}
}
This trait is implemented for most container types and references to these types. It is in fact used by for loops - a value of any type which implements IntoIterator can be used in in clause:
let s: &[u8] = b"hello";
for b in s { ... }
This is very nice from learning and reading perspective because it has less noise (in form of iter()-like methods). It even allows things like these:
let v: Vec<u8> = ...;
for i in &v { /* i is &u8 here, v is borrowed immutably */ }
for i in &mut v { /* i is &mut u8 here, v is borrowed mutably */ }
for i in v { /* i is just u8 here, v is consumed */ }
This is possible because IntoIterator is implemented differently for &Vec<T>, &mut Vec<T> and just Vec<T>.
Every Iterator implements IntoIterator which performs an identity conversion (into_iter() just returns the iterator it is called on), so you can use Iterator instances in for loops as well.
Consequently, it makes sense to use IntoIterator in generic functions because it will make the API more convenient for the user. For example, enumerate() function from above could be rewritten as such:
fn enumerate<I>(source: I) -> Enumerate<I::IntoIter> where I: IntoIterator {
Enumerate {
iter: source.into_iter(),
count: 0
}
}
Now you can see how generics can be used to implement transformations with static typing easily. Rust does not have anything like C#/Python yield (but it is one of the most desired features, so one day it may appear in the language!), thus you need to wrap source iterators explicitly. For example, you can write something analogous to the above Enumerate structure which does the task you want.
However, the most idiomatic way would be to use existing combinators to do the work for you. For example, your code may be written as follows:
let iter = ...; // iter implements Iterator<Item=i32>
let r = iter.filter(|&x| x % 2 == 0); // r implements Iterator<Item=i32>
for i in r {
println!("{}", i); // prints only even items from the iterator
}
However, using combinators may turn ugly when you want to write custom combinator functions because a lot of existing combinator functions accept closures (e.g. the filter() one above), but closures in Rust are implemented as values of anonymous types, so there is just no way to write the signature of the function returning the iterator out:
fn filter_even<I>(source: I) -> ??? where I: IntoIter<Item=i32> {
source.into_iter().filter(|&x| x % 2 == 0)
}
There are several ways around this, one of them is using trait objects:
fn filter_even<'a, I>(source: I) -> Box<Iterator<Item=i32>+'a>
where I: IntoIterator<Item=i32>, I::IntoIter: 'a
{
Box::new(source.into_iter().filter(|&x| x % 2 == 0))
}
Here we hide the actual iterator type returned by filter() behind a trait object. Note that in order to make the function fully generic I had to add a lifetime parameter and a corresponding bound to Box trait object and I::IntoIter associated type. This is necessary because I::IntoIter may contain arbitrary lifetimes inside it (just like Iter<'a, T> type above), and we have to specify them in the trait object type (otherwise the lifetime information would be lost).
Trait objects created from Iterator trait implement Iterator themselves, so you can continue using these iterators as usual:
let source = vec![1_i32, 2, 3, 4];
for i in filter_even(source) {
println!("{}", i); // prints 2 and 4
}
Here is the full version of Map, and here is the function that builds it.
A minimal implementation would look something like
fn map<I, E, B, F>(i: I, f: F) -> Map<I, F> where
F: FnMut(E) -> B,
I: Iterator<Item=E>
{
Map {iter: i, f: f}
}
pub struct Map<I, F> {
iter: I,
f: F,
}
impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
type Item = B;
fn next(&mut self) -> Option<B> {
self.iter.next().map(|a| (self.f)(a))
}
}
Playpen link. Note that the map used inside the iterator is the method on Option; this isn't recursively defined!
It's not too convenient to write, but boy is it fast!
Now, to write this for an arbitrary "enumerable" type one would change map to
fn map<I, E, B, F>(i: I, f: F) -> Map<I::IntoIter, F> where
F: FnMut(E) -> B,
I: IntoIterator<Item=E>
{
Map {iter: i.into_iter(), f: f}
}
IntoIterator is basically IEnumerable, only instead of GetEnumerator there's into_iter.
Implement the Iterator trait for the struct that should serve as iterator. You only need to implement the next method. The other methods have default implementations.
It is not possible to create an iterator that works with any container. The type system machinery needed for this doesn't exist yet.
I am too learning Rust coming from a C# background. Here is how I would implement it:
fn evens<'a>(input: impl Iterator<Item = &'a i32>) -> impl Iterator<Item = &'a i32> {
input.filter(|x| (*x % 2) == 0)
}
and here is the test
#[test]
fn test_evens() {
let input = vec![1, 2, 3];
let mut iter = evens(input.iter());
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), None);
}