what does the '->' token mean in Rust? [duplicate] - rust

This question already has an answer here:
What's the origin of -> in Rust function definition return types?
(1 answer)
Closed last month.
I'm digging into Rust for the first time, with a primarily ObjC and Javascript (sigh) background, and working with a few of the playgrounds.
I'm trying to understand the -> (aka "thin arrow??") symbol in Rust and how I am supposed to interpret this when reading Rust statements

In Rust -> specifies the return type of the function. In Rust, functions need to specify their return type (if it isn't (), the empty return type).
So when you declare a function that adds one to an i32, you have to specify the return type i32 of the function like this:
fn add_one(x: i32) -> i32
{
x+1
}
You have to declare x+1 to add one and return the value. Note that when you return the value you do not use a semicolon after x+1;. A semicolon means it is a statement and not a return expression. In Rust, expressions without semicolons are return value expressions.

Related

How do I return different iterators from a function? [duplicate]

This question already has answers here:
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Closed 5 months ago.
I'm trying to change the minigrep application that I've implemented in the rust book to also take stdin input like the real grep does.
I've created a small helper function that takes the configuration and decides (currently according to an environment variable) whether to return the buffered reader iterator or the stdin iterator:
fn stdinOrFile(cfg: &Cfg) -> impl Iterator<Item = String> + '_ {
if cfg.stdin {
return io::stdin().lines();
}
let file = File::open(cfg.path.clone()).unwrap();
let reader = BufReader::new(file);
return reader.lines();
}
Realizing that I'm poking with a stick in the dark, it appears that the syntax of returning a trait object is legal, it's a dead-end for now thought. The compiler appears to still try to infer the concrete type of the returned value and complains that the other type is not of the same type, however to the best of my knowledge both implement the iterator trait.
Some ideas I have to get around this:
Box the value before returning it
Create a generic wrapper that would wrap both underlying types, then, since the minigrep matcher only uses the filter functionality of the iterators, I could have separate filter implementations on the wrapper according to which underlying type it holds, which would then call the relevant method on the underlying type.
Any ideas?
Why is the trait object syntax allowed in the return type if a concrete implementation is inferred?
You're right to think you should box it. impl Iterator is not a trait object. It can mean a couple of different things, but in return position it's a special impl return syntax. Effectively, the function still returns a concrete, ordinary iterator of known type, it's just that the compiler infers that type for you. It's most commonly used with iterators, since writing impl Iterator<Item=u32> is far nicer than the actual return type which can be some shenanigans like Map<Vec::Iter<String>, fn(String) -> i32> (and can even be non-denotable in cases where the function argument is a closure).
However, with impl return, there must still exist a concrete type. You can't return two different types in two different branches. So in this case, you do need a trait object. That's dyn Iterator, but dyn Iterator is not sized, so you need to wrap it in a Box to deal with that.
Box<dyn Iterator<Item = String> + '_>
and, of course, you'll need to wrap your return values in Box::new, since Rust won't do that for you.

What enables a closure type to be used where a function pointer type is expected in Rust? [duplicate]

This question already has answers here:
Why does passing a closure to function which accepts a function pointer not work?
(2 answers)
Closed last year.
What enables a closure type to be used where a function pointer type to be used?
fn takes_ptr(_f: fn(u32) -> u32) {}
fn main() {
let closure = |n| n;
takes_ptr(closure)
}
related: there's another question that asks what enables pointer types to be used where closure types are expected: What enables a function trait type to be used where an fn type is expected?
Closures can be coerced to function pointers if they do not capture any local variables.
Closures that don't capture any variables are effectively the same as normal functions, making this sound. This behaviour was defined in RFC 1558, which says:
A closure that does not move, borrow, or otherwise access (capture) local variables should be coercable to a function pointer (fn).
So |n| n can be coerced since it doesn't capture any local variables, but |n| n + a cannot be coerced since it captures a variable, a, from the outer environment.

What does “&*” do in Rust? [duplicate]

This question already has answers here:
What does &* combined together do in Rust?
(2 answers)
Closed 5 months ago.
I encountered this block of code while reading documentation from a Rust library:
for (ent, pos, vel) in (&*entities, &mut pos_storage, &vel_storage).join() {
println!("Processing entity: {:?}", ent);
*pos += *vel;
}
What does &*entities do here? From what I can tell it’s dereferencing entities and then referencing it again. But why?
This is an explicit reborrow and it's a common idiom that pops up in Rust from time to time.
& in an expression only has one meaning: it takes an expression (which must be a place expression) of type T and borrows a reference to it of type &T.
For references, * does the opposite of & -- it takes a reference (&T) and makes a place expression of type T. But * can mean different things with different kinds of pointers, since you can override it by implementing Deref. Because * ties in some compiler magic that automatically dereferences the return value of Deref::deref, you can borrow the result of *, turning it back into a plain reference, by using the & operator.
So &*foo is a way of explicitly reborrowing "any kind of pointer to T" as a &T, and is the equivalent of manually calling Deref::deref(&foo).
(The above explanation also works for &mut borrows -- just replace & with &mut and Deref with DerefMut.)
It's not clear in the example you link what entities is, but it's probably some kind of smart pointer, where the join() method requires a plain reference. For another example where this is required, consider using [&str]::concat to concatenate a String with some &strs:
// I want to concatenate this with some other strings
let s = String::from("Amelia");
// The following won't compile: you can't make an array of &str and String
assert_eq!(["Hello", ", ", s].concat(), "Hello, Amelia"); // WRONG
// However, &*s takes a reference to the str pointed to by s.
assert_eq!(["Hello", ", ", &*s].concat(), "Hello, Amelia"); // OK
See also
Is there a difference between slicing and an explicit reborrow when converting Strings to &strs?
Box<T> to &T in Rust

About trait Index implement of Vector in Rust [duplicate]

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?

What is the use of `!` as return type in Rust? [duplicate]

This question already has answers here:
Why would I use divergent functions?
(3 answers)
Closed 5 years ago.
I have recently seen a code like this:
fn read() -> ! {
unimplemented!()
}
fn read2() {
}
fn main() {
read2();
read();
}
I could not find any information about the ! as return type of fn read() anywhere so I don't have any idea what is this and what for.
The only thing I have found seems useless for me:
Using ! as a return type indicates to the Rust compiler that this function never returns
I don't understand what it does since omitting the type also says that the function returns nothing (the unit type actually).
Unit () is not nothing, it is a type, with one possible value also written ().
Furthermore, when a function returns unit (or "nothing" as you say), it actually returns. The Never type ! specifies that the function never returns, i.e. quits the program.
This is typically the return type of a panic macro:
let s = match i {
1 => "one",
2 => "two",
_ => panic!("Error"),
}
In this example, note that ! can "take the role" of all the types. The compiler does not complain that one branch has type &str and another has type !.
For your information, here is a little history of the Never type.

Resources