erl_pp(3)
π NAME π
erl_pp β literally just the Erlang pretty printer, no cap π
β¨ DESCRIPTION β¨
okay so bestie, the functions in this module are the whole reason your abstract forms can look aesthetically attractive and actually be suitable for printing. They take abstract forms and give you back glow-ups. π¦
Every single function in here returns a (possibly deep) list of characters, and every single one of them generates an error if the form is wrong. No silent fails, she does not play like that π
Every function can also take an optional argument, which specifies a hook that gets called if something tries to print an unknown form.
β οΈ real talk: if you're using these functions to convert abstract code back to Erlang source code, you should first run the enclosing function through legalize_vars/1 so the output is actually semantically equivalent to the abstract code. Do not skip this step, bestie, I am begging π
πΈ Known Limitations
It is not possible to have hook functions for unknown forms anywhere other than in expressions. That's it, that's the limitation, periodt.
π See Also
erl_eval, erl_parse, io
π§ DATA TYPES π§
hook_function()
hook_function() ::
none |
fun((Expr :: erl_parse:abstract_expr(),
CurrentIndentation :: integer(),
CurrentPrecedence :: non_neg_integer(),
Options :: options()) ->
io_lib:chars()).
The optional argument HookFunction (you'll see it showing up in all the functions below) defines a function that gets called whenever an unknown form shows up somewhere there needs to be a valid expression. If HookFunction is equal to none, then congrats, there is no hook function. π
The hook function you call is supposed to return a (possibly deep) list of characters. And psst β the function expr/4 is super useful inside a hook, iykyk.
If CurrentIndentation is negative, there are no line breaks and only a space is used as a separator. Little detail, big energy. β¨
option()
option() ::
{hook, hook_function()} |
{encoding, latin1 | unicode | utf8} |
{quote_singleton_atom_types, boolean()} |
{linewidth, pos_integer()} |
{indent, pos_integer()}.
- The
quote_singleton_atom_typesoption is used to add quotes to all singleton atom types. yes, all of them. π - The
linewidthoption controls the maximum line width for formatted lines (defaults to 72 characters). - The
indentoption controls the indention for formatted lines (defaults to 4 spaces).
options()
options() :: hook_function() | [option()].
π₯ FUNCTIONS π₯
attribute(Attribute, Options) -> io_lib:chars()
when
Attribute :: erl_parse:abstract_form(),
Options :: options().
Same as form/1,2, but only for the attribute Attribute. It's giving specialized, we love a focused queen π
expr(Expression, Indent, Precedence, Options) -> io_lib:chars()
when
Expression :: erl_parse:abstract_expr(),
Indent :: integer(),
Precedence :: non_neg_integer(),
Options :: options().
Prints one expression. Just one. Single. Main character energy only. π
It's useful for implementing hooks (see the section Known Limitations up above, bestie).
exprs(Expressions, Indent, Options) -> io_lib:chars()
when
Expressions :: [erl_parse:abstract_expr()],
Indent :: integer(),
Options :: options().
Same as form/1,2, but only for the sequence of expressions in Expressions. Plural era. π₯
form(Form, Options) -> io_lib:chars()
when
Form ::
erl_parse:abstract_form() | erl_parse:form_info(),
Options :: options().
Pretty prints a Form, which is an abstract form of a type that's returned by erl_parse:parse_form/1. This is the blueprint, the moment, the whole vibe check. β¨
function(Function, Options) -> io_lib:chars()
when
Function :: erl_parse:abstract_form(),
Options :: options().
Same as form/1,2, but only for the function Function. One function, fully served π
guard(Guard, Options) -> io_lib:chars()
when
Guard :: [erl_parse:abstract_expr()],
Options :: options().
Same as form/1,2, but only for the guard test Guard. Protection spell activated π‘οΈ
legalize_vars(Function) -> erl_parse:abstract_form()
when Function :: erl_parse:abstract_form().
okay so this one is important, listen up π’
When the Erlang compiler expands records into tuples, it introduces new variables in the abstract representation. And because that expansion happens on the abstract representation itself, the compiler can safely name those new variables with names that are not syntactically valid in Erlang source code β specifically, the name starts with a lowercase letter β which guarantees the new names are unique. Clever, lowkey iconic. π§ β¨
But bestieβ¦ that strategy causes problems if a user wants to convert the abstract representation back to Erlang source code using the functions in this module. Typically, pattern variables get output as atoms, which changes the semantics of the program. π Not the vibe.
So to solve this, legalize_vars/1 β when you run it on the abstract representation of a function β returns an equivalent function where all variables will have syntactically valid names. Problem solved, glow restored, we ate. π
π and that's the whole page! erl_pp really said "I will make your abstract forms pretty and I will not elaborate further," and honestly? respect. π
mwah π this was erl_pp(3), from Ericsson AB, riding with stdlib 8.0.4. stan a pretty printer, xoxo π«Ά
π¦ where this page comes from
- ubuntu stonking: erlang-doc 1:29.0.6+dfsg-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms