%}{{!"matching-code"}< Destructing AST nodes}{%html:
%}{{!"good-practices"}Good practices >}{%html:
%}
{0 AST Traversals}
The {{!Ppxlib.Parsetree}[Parsetree]} is a very complex type. Other {!Ppxlib} modules such as
{{!Ppxlib_metaquot}[Metaquot]}, {{!Ppxlib.Ast_builder}[Ast_builder]} and {{!Ppxlib.Ast_pattern}[Ast_pattern]} help in generating and matching values,
but only when the overall structure of the code is known in advance.
For other use cases, such as extracting all identifiers, checking that a
property is verified, or replacing all integer constants by something else,
those modules cannot really help. All these examples relate with another kind
of {{!Ppxlib.Parsetree}[Parsetree]} manipulations known as traversals.
A traversal is a recursive function that will be called on a value, and recursively on all
of its subvalues, combining the result in a certain way. For instance, {{!Stdlib.List.map}[List.map]} is a traversal of the
[list] type. In the case of a [list], a map is very simple to write, but in the
case of the long {{!Ppxlib.Parsetree}[Parsetree]} type, it is a lot of boilerplate code! Fortunately,
{{!Ppxlib}[ppxlib]} provides a way to ease this.
In [ppxlib], traversals are implemented using the "visitor" object-oriented pattern.
{1 Writing Traverses}
For each kind of traversal (described below), [ppxlib] provides a "default" traversal,
in the form of a class following the visitors pattern. For instance, in the case of the map traversal, the
default map is the identity AST map, and any object of class {{!Ppxlib.Ast_traverse.map}[Ast_traverse.map]}
will be this identity map. To apply a map to a node of a given type, one needs
to call the appropriate method:
{[
# let f payload =
let map = new Ppxlib.Ast_traverse.map in
map#payload ;;
val f : payload -> payload =