Function composition combines small functions into a larger function: each output becomes the next input. In Rust, this supports applications built from simple, understandable, testable pieces rather than object interactions. section 2.2.5
Compose a typed pipeline
Start with `add_one: i32 -> i32`, then `stringify: i32 -> String`, then a partially applied `prefix_with("Result: ")`. Calling the resulting function with `5` runs those stages in order and produces a prefixed string. Every stage must accept the preceding stage’s output; additional compatible stages can be added. section 2.2.5
Listing 2.16 A function to compose two functions
fn compose_two<FIRST, SECOND, THIRD, F, G>(f: F, g: G)
-> impl Fn(FIRST) -> THIRD #1
where F: Fn(FIRST) -> SECOND, #2
G: Fn(SECOND) -> THIRD #3
{
move |x| g(f(x)) #4
}
fn main() {
let two_composed_function = compose_two(
compose_two(add_one, stringify),
prefix_with("Result: ")
);
} #5
`compose_two` makes the core operation explicit: its bounds connect `Fn(FIRST) -> SECOND` to `Fn(SECOND) -> THIRD`, and its returned closure evaluates `g(f(x))`. Larger pipelines can be built by nesting this two-function form. section 2.2.5
A declarative `compose!` macro removes the nesting. Its base case returns one function unchanged; its recursive case combines the first expression with the composition of the remaining expressions. Comma-separated input can also be written with arrows when that reads more clearly. section 2.2.5
Listing 5.7 Our compose macro entry point
#[proc_macro]
pub fn compose(item: TokenStream) -> TokenStream {
let ci: ComposeInput = parse_macro_input!(item); #1
quote!(
{
fn compose_two<FIRST, SECOND, THIRD, F, G>(first: F, second: G)
-> impl Fn(FIRST) -> THIRD
where
F: Fn(FIRST) -> SECOND,
G: Fn(SECOND) -> THIRD,
{
move |x| second(first(x))
} #2
#ci
}
).into()
}
A function-like procedural macro can provide dot-separated composition syntax such as `compose!(add_one . add_one . stringify)`. It parses custom input, emits a local `compose_two`, and wraps the generated declarations and expression in a block so the invocation remains one value for a `let` binding. section 5.3
Composition is also a macro use case when fluent syntax is difficult or impossible in ordinary Rust. A function-like macro is suitable for this custom expression input, whereas derive and attribute macros expect valid Rust items such as structs, enums, or functions. section 5.3 section 2.2










