Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ch. 20: show both impl Fn and Box<dyn Fn> #4152

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
fn returns_closure() -> dyn Fn(i32) -> i32 {
fn returns_closure() -> impl Fn(i32) -> i32 {
|x| x + 1
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let handlers = vec![returns_closure(), returns_initialized_closure(123)];
for handler in handlers {
let output = handler(5);
println!("{output}");
}
}

fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
Box::new(|x| x + 1)
}

fn returns_initialized_closure(init: i32) -> Box<dyn Fn(i32) -> i32> {
Box::new(move |x| x + init)
}
30 changes: 15 additions & 15 deletions src/ch20-05-advanced-functions-and-closures.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,33 +95,33 @@ function. However, you can’t do that with closures because they don’t have a
concrete type that is returnable; you’re not allowed to use the function
pointer `fn` as a return type, for example.

The following code tries to return a closure directly, but it won’t compile:
Instead, you will normally use the `impl Trait` syntax we learned about in
Chapter 10. You can return any function type, using `Fn`, `FnOnce` and `FnMut`.
For example, this code will work just fine:

```rust,ignore,does_not_compile
{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-18-returns-closure/src/lib.rs}}
```

The compiler error is as follows:

```console
{{#include ../listings/ch20-advanced-features/no-listing-18-returns-closure/output.txt}}
```

The error references the `Sized` trait again! Rust doesn’t know how much space
it will need to store the closure. We saw a solution to this problem earlier.
We can use a trait object:
However, as we noted in the [“Closure Type Inference and
Annotation”][closure-types]<!-- ignore --> section in Chapter 13, each closure
is also its own distinct type. If you need to work with multiple functions that
have the same signature but different implementations, you will need to use a
trait object for them:

```rust,noplayground
{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/lib.rs}}
{{#rustdoc_include ../listings/ch20-advanced-features/no-listing-19-returns-closure-trait-object/src/main.rs}}
```

This code will compile just fine. For more about trait objects, refer to the
section [“Using Trait Objects That Allow for Values of Different
Types”][using-trait-objects-that-allow-for-values-of-different-types]<!--
ignore --> in Chapter 19.
This code will compile just fine—but it wouldn’t if we had tried to stick with
`impl Fn(i32) -> i32`. For more about trait objects, refer to the section
[“Using Trait Objects That Allow for Values of Different
Types”][using-trait-objects-that-allow-for-values-of-different-types]<!-- ignore
--> in Chapter 19.

Next, let’s look at macros!

[advanced-traits]: ch20-03-advanced-traits.html#advanced-traits
[enum-values]: ch06-01-defining-an-enum.html#enum-values
[closure-types]: ch13-01-closures.html#closure-type-inference-and-annotation
[using-trait-objects-that-allow-for-values-of-different-types]: ch18-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
Loading