This question already has answers here:
What's an idiomatic way to print an iterator separated by spaces in Rust?
(4 answers)
Closed 5 years ago.
Currently the SliceConcatExt seems to be very specifically crafted for slices or vectors of Strings, even though it arbitrarily constrains its use. That particular use-case is reflected in the trait name as well, after all, it is called SliceConcatExt for a reason.
Is there a more general connect() implementation which would take any Iterator over items supporting the Str trait ?.
If not, are there any plans to remedy this ?
Example
use std::iter::IntoIterator;
fn connected<S, I>(s: I) -> String
where S: Str,
I: IntoIterator<Item=S> {
// have
s.into_iter().collect::<Vec<S>>().connect(", ")
// want
// s.into_iter().connect(", ")
// error: type `<I as core::iter::IntoIterator>::IntoIter` does not implement any method in scope named `connect`
// tests/lang.rs:790 s.into_iter().connect(", ")
}
connected(&["foo", "bar"]);
One could possibly implement SliceConcatExt for any iterator with item type Str, but I have the suspicion that connect() currently is just unnecessarily specialized, which might be fixable until Rust beta.
Using rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
The closest solution I know of would be to use Itertools::intersperse:
#![feature(core)]
extern crate itertools;
use std::iter::IntoIterator;
use itertools::Itertools;
fn connected<'a, S, I>(s: I) -> String //'
where S: Str,
I: IntoIterator<Item=&'a S> //'
{
s.into_iter().map(|s| s.as_slice()).intersperse(", ").collect()
}
fn main() {
println!("{}", connected(&["foo", "bar"]));
}
Related
This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Confusion over auto-dereferencing rules when using function
(1 answer)
Closed 4 years ago.
The following program works fine:
pub fn foo(_v: &str) -> bool {
false
}
fn main() {
let f = "hello world";
println!("{}", foo(&&&&f)); // note the number of & here
}
In fact it works on passing any number of &. How should I interpret what is going on ?
My rust version:
$ rustc --version
rustc 1.32.0-nightly (13dab66a6 2018-11-05)
From the Rust book:
Deref coercion is a convenience that Rust performs on arguments to
functions and methods. Deref coercion converts a reference to a type
that implements Deref into a reference to a type that Deref can
convert the original type into. Deref coercion happens automatically
when we pass a reference to a particular type’s value as an argument
to a function or method that doesn’t match the parameter type in the
function or method definition. A sequence of calls to the deref method
converts the type we provided into the type the parameter needs.
So basically, in function arguments the compiler will automatically remove any & written or implied until it gets to a type that can be passed to the function.
Because the compiler automatically dereferences the chain of references, you can imagine that it inserts as many * as necessary to get the right type:
foo(&&&f)
is converted to:
foo(&****(&&&f))
that leads to the right invocation:
foo(f)
The insertions of as many * as needed is actually performed by this blanket implementation of Deref trait:
impl<'a, T: ?Sized> Deref for &'a T {
type Target = T;
fn deref(&self) -> &T { *self }
}
Note: I've update my answer because in the original I used the term autoderef in the wrong way, see this post for details.
This question already has answers here:
How to call function from certain trait explicitly?
(2 answers)
How do I disambiguate traits in Rust?
(2 answers)
Closed 1 year ago.
The use of use in Rust so far seems pretty simple - everything is already "imported" (in the sense that other languages use the word), use just brings them into scope.
However, for traits, this seemingly falls apart. To use a trait's methods on a struct, the said trait must be in scope.
So I thought, if the behavior of use be consistent, then there must be another, more verbose way of calling trait methods.
So I tried:
fn main() {
some_obj.TraitName::trait_method();
}
However this doesn't seem to compile. So is there a way to do this or is use inconsistent in this sense?
EDIT: TraitName is the full path of the trait, i.e some_obj.module_1::TraitName::trait_method().
You could use fully qualified syntax:
<Type as crate::mod::TraitName>::trait_method(object);
as example:
mod m {
pub trait Foo {
fn foo(&self) {}
}
impl<T> Foo for T {}
}
fn main() {
let x = 10u32;
<u32 as m::Foo>::foo(&x);
}
Playground
Or just let the compiler elide the types:
m::Foo::foo(&x);
This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Confusion over auto-dereferencing rules when using function
(1 answer)
Closed 4 years ago.
The following program works fine:
pub fn foo(_v: &str) -> bool {
false
}
fn main() {
let f = "hello world";
println!("{}", foo(&&&&f)); // note the number of & here
}
In fact it works on passing any number of &. How should I interpret what is going on ?
My rust version:
$ rustc --version
rustc 1.32.0-nightly (13dab66a6 2018-11-05)
From the Rust book:
Deref coercion is a convenience that Rust performs on arguments to
functions and methods. Deref coercion converts a reference to a type
that implements Deref into a reference to a type that Deref can
convert the original type into. Deref coercion happens automatically
when we pass a reference to a particular type’s value as an argument
to a function or method that doesn’t match the parameter type in the
function or method definition. A sequence of calls to the deref method
converts the type we provided into the type the parameter needs.
So basically, in function arguments the compiler will automatically remove any & written or implied until it gets to a type that can be passed to the function.
Because the compiler automatically dereferences the chain of references, you can imagine that it inserts as many * as necessary to get the right type:
foo(&&&f)
is converted to:
foo(&****(&&&f))
that leads to the right invocation:
foo(f)
The insertions of as many * as needed is actually performed by this blanket implementation of Deref trait:
impl<'a, T: ?Sized> Deref for &'a T {
type Target = T;
fn deref(&self) -> &T { *self }
}
Note: I've update my answer because in the original I used the term autoderef in the wrong way, see this post for details.
This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
Closed 4 years ago.
I check Index trait in doc and find return type of index() is &T.
Then I write this function to get value from vector:
fn get_value_test(a: usize, v: &Vec<i32>) -> i32 {
v[a]
}
My question is: why v[a] is i32 but &i32? Because i32 ...have a known size at compile time are stored entirely on the stack, so copies of the actual values are quick to make? (from here)
It looks like Rust have hidden rule to convert type in this situation?
There was a small misguidance here. Although the method prototype for Index<Idx> is fn index(&self, index: Idx) -> &T, the syntactical operator x[i] does dereference the output from that &T:
container[index] is actually syntactic sugar for *container.index(index) [...]. This allows nice things such as let value = v[index] if the type of value implements Copy.
So there you go. Your function is indeed returning a copy of the value from the vector, but not from an implicit conversion. If the original intent was to really retrieve a reference to that value, you would do &x[i].
See also:
Meaning of the ampersand '&' and star '*' symbols in Rust
Does Rust automatically dereference primitive type references?
This question already has answers here:
How to write a Rust function that takes an iterator?
(3 answers)
Closed 5 years ago.
Say I have a string, from which I make an iterator (cycle-able, peek-able) over its chars:
let hello = "hello";
let mut iterator = hello.chars().cycle().peekable;
I wanted to figure out what the type of iterator is, so I purposefully introduced an error:
let mut iterator: usize = hello.chars().cycle().peekable;
The compiler then informed me that the type of the right hand side is:
std::iter::Peekable<std::iter::Cycle<std::str::Chars<'_>>>
Wow, that's a mouthful. If I define a function like so:
fn foobar(x: std::iter::Peekable<std::iter::Cycle<std::str::Chars<'_>>>){
// snip
}
I get an error like this:
error: underscore lifetimes are unstable (see issue #44524)
So, if I want to pass an iterator to a function, how should I do so? Or, is this something I should avoid?
Ok so there are multiple aspects to this questions:
First of, you can avoid the compiler error by giving it an explicit lifetime:
fn foobar<'a>(mut x: std::iter::Peekable<std::iter::Cycle<std::str::Chars<'a>>>){
To the he second question, whether this is idiomatic or not, i'd say no, avoid this specific approach.
You can only pass in this specific Iterator chain - something else is not possible. But most of the times, your algorithm isn't interested in the specific combination, rather than the functionality to "produce" chars. Use generics orimpl Trait instead (if you have access to nightly rust).
Impl Trait is a feature, which allows hiding the specific type used. This specific feature, accepting impl traits in argument position landed as of a few days ago, at the time of writing. I made this quick sketch for demonstration purposes, playground link
#![feature(universal_impl_trait)]
fn main() {
foo("hello".chars());
foo("hello".chars().rev());
}
fn foo(x: impl Iterator<Item=char>) {
let text: String = x.collect();
println!("{}", &text)
}
Edit: You can use generics as well, see comments from nullqube and stefan