[erlang-questions] Pretty printing records from a program

Mats Cronqvist <>
Fri Sep 29 11:25:49 CEST 2006


Joe Armstrong wrote:
> I have a record X in a program and all the .hrl files etc.
> How do I pretty print this from a program


   the real problem is of course that record_info/2 is a macro, and not a real 
function. IMO record_info should be generated by the compiler (just like 
module_info/0).

   now, if your module is debug compiled, you can use the fabled rec module 
(that i just wrote :> ). then this snippet;

-define(PURTY(X),rec:pretty(?MODULE,X)).
-record(sucky,{t=aT,u,v=aV,w=aDubU,x=anX,y=aY,z}).
g() -> ?PURTY(#sucky{z=hello}).

   will produce this output;

[{t,aT},{u,undefined},{v,aV},{w,aDubU},{x,anX},{y,aY},{z,hello}]

   which is probably what you want.

   mats

%-------------------------------------------------------------------
%%% File : rec.erl
%%% Author : Mats Cronqvist
%%% Description :
%%% pretty(Mod,Rec) -> list({FieldName,Value})
%%% Mod = atom() - module name
%%% Rec = record()
%%%
%%% Rec must declared in Mod.
%%% works by getting debug_info from the beam file. caches the record
%%% info in the process registry. checks compile times to see if cache
%%% is out-of-date.
%%%
%%% Created : 29 Sep 2006 by Mats Cronqvist <>
%%%-------------------------------------------------------------------
-module(rec).

-export([pretty/2]).

pretty(Mod,Rec) when is_tuple(Rec) -> pretty(Mod,tuple_to_list(Rec));
pretty(Mod,[RecName|Vals]) -> lists:zip(get_recinfo(Mod,RecName),Vals).

get_recinfo(Mod,RecName) ->
     Key = {rec_info,Mod,RecName},
     case get(Key) of
         undefined ->
             try put_recinfo(Mod,RecName),get_recinfo(Mod,RecName)
             catch _:R -> exit({no_record_info,RecName,Mod,R})
             end;
         {Ctime,Fields} ->
             case Ctime < ctime(Mod:module_info(compile)) of
                 true -> erase(Key),get_recinfo(Mod,RecName);
                 false -> Fields
             end
     end.
put_recinfo(Mod,RecName) ->
     {_,C} = get_chunk(Mod,"Abst"),
     Fs = try [_Fs] = [X||{attribute,_,record,{R,X}} <- C, R=:=RecName], _Fs
          catch _:_ -> throw(no_such_record)
          end,
     F = fun({record_field,_,{atom,_,V},_})->V;
            ({record_field,_,{atom,_,V}})->V end,
     put({rec_info,Mod,RecName},
         {ctime(get_chunk(Mod,"CInf")), lists:map(F,Fs)}).

ctime(C) -> [X || X <- C, element(1,X)==time].

get_chunk(Mod,Chnk) ->
     F = try hd(_F = code:which(Mod)), _F
         catch _:_ -> throw(no_file)
         end,
     B = try {ok,{Mod,[{Chnk,_B}]}} = beam_lib:chunks(F,[Chnk]),_B
         catch _:_ -> throw(not_debug_compiled)
         end,
     binary_to_term(B).



More information about the erlang-questions mailing list