As you might have noticed, closures do not require us to annotate the types being used because closures
are typically short and have a narrow context.
The compiler is able to reliably infer the types of parameters being used as well as the return type,
but we can still annotate the types if we wanted to.
So to see an example of this, we'll create an add closure which is going to accept a parameter of type
IE 32 and then it's going to return an I 32 and then we're just going to have it add one to the value
we get.
But as we already saw, we also don't have to have annotation.
So I'll create the same closure and I'll just call it add v two for version two and we'll accept in
our X argument and then we'll just add one to it.
But as you can see, this X is underlined and it says a type annotation is needed.
Well, in order for the compiler to infer what.
It will require we actually have to use it.
So in this case, as soon as we call it and then pass into one, it's able to infer, hey, we are using
type I 32.
But once we let the compiler infer the type, then that is the type that must continue to be used.
Otherwise it will create an error and we can very easily see an example of this and we'll create a closure
that accepts one argument and then it's just going to immediately return it.
So we'll say.
Let's string equals example.
So we're calling our closure and then we're going to pass in a string called string.
And the closure, as you can see, is completely happy with that.
But what if we try to pass in a number now, to example, will we see the two is underlined in red because
it is expecting a string which was the first type that was inferred.
So we can see that by hovering over it and it says expected string found an integer and that's really
all there is to it for closure type annotations.
So now I want to take a quick minute to discuss closures performance.
Russ is closures are designed to be fast closures are not allocated on the heap unless you put them
in some kind of a container such as a vector.
And since each closure has a known type, whenever Rust compiles the code, it can inline that code
for that particular closure.
And lining is a technique where the compiler will add the closure inside the calling functions block.
And this prevents another separate function call from happening, which is going to give us a performance
optimization.
So if you are creating a program that is extremely performance dependent, closures are still very acceptable
to use in the right situation.