liveBook · Manning

Function-like macro

As explained in Write Powerful Rust Macros

A function-like macro is a Rust procedural macro invoked with the ! operator that accepts arbitrary token input and replaces that input with generated output.

A function-like macro is a Rust procedural macro called with `!` that accepts token input and replaces it with generated tokens. Unlike derive and attribute macros, it is not confined to decorating particular Rust items, so it can be invoked almost anywhere code can appear. That freedom makes it useful for transformations that do not begin with a struct, enum, trait, or function. section 1.3.1 section 5.7

Figure 1.2 The types of macros in Rust
figure

Compare function-like macros with derive and attribute procedural macros before choosing how much input freedom and transformation power a task needs. section 1.3.1

Define one with `#[proc_macro]` and a function taking one `TokenStream` and returning one. Parse the incoming tokens into a `syn` type, inspect the resulting syntax tree, then use `quote!` to emit replacement code. Because arbitrary input may not be valid Rust, a general-purpose parser such as `DeriveInput` is often insufficient; define a custom parser when the macro accepts its own notation. section 5.1.1 section 5.3

Generate an information-hiding struct API

A call such as `private!(struct Example { string_value: String, number_value: i32, });` can receive the complete struct definition. Its expansion recreates the struct and its implementation, allowing generated accessor methods while controlling which details remain exposed. The original invocation disappears, so the output must include every item needed by the caller. section 5.1.1

Accept a mini-language for composition

`compose!(add_one . add_one . stringify)` accepts dot-separated identifiers that are not an ordinary Rust composition expression. A custom `ComposeInput` parser reads identifiers punctuated by `.`, while token generation emits a block containing a helper function and the composed closure. The block is necessary so the expansion evaluates as one value for a `let` binding. section 5.3

Choose a macro form by the transformation required:

  • Use a derive macro when adding functionality to a struct or enum without changing it. section 5.4
  • Use an attribute macro when altering an annotated struct, enum, trait, or function. section 5.4
  • Use a function-like macro when input may be broader than annotated items or when it must change functionality in other contexts. section 5.4

Treat generated code as code that must compile on its own. When expansion errors are confusing, write the intended generated Rust manually first and let the compiler or IDE identify problems. Prefer the simplest macro that meets the requirements: broad input makes function-like macros flexible, but also increases parsing work and makes their effects less predictable than narrower procedural macros. section 5.7 section 5.4

Generate configuration storage

A `config` macro can turn YAML-style plain string key-value properties into a generated `Config` struct holding `HashMap<String, String>` data and a method that fills it. Restricting the accepted configuration to non-nested values keeps the input format and generated API deliberately simple. section 10.1

How Write Powerful Rust Macros covers it

How deep it goes
Works through macro signatures, token parsing, custom parsers, quoted output, block scoping, and compiler-guided debugging.
Examples
Uses a struct-accessor macro, dot-separated function composition, YAML configuration generation, and implementation exercises.
What it assumes
Assumes Rust macro familiarity and builds from procedural-macro setup through custom parsing for nonstandard input.
What you can do after
Build it from scratch by parsing token input, generating replacement code, and selecting a narrower macro when possible.
How it connects
Connects procedural macros with declarative macros, derive macros, attribute macros, TokenStream, syn, quote, and function composition.

Also explained in

Compare how 3 books explain function-like macro →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Write Powerful Rust Macros. The section links point to the parts of the book it draws on.