[erlang-questions] useful trick for finding record instantiations

Richard Carlsson carlsson.richard@REDACTED
Fri Apr 27 15:06:05 CEST 2012


It's not unusual when working with some legacy code that you want to 
find all the locations that instantiate a certain record using the 
#foo{...} syntax, so that you can replace those with calls to a function 
that controls the instantiation for better encapsulation:

   init_foo(...) -> #foo{...}.

However, you can't easily grep for '#foo{' because of all the patterns 
that have the same syntax, '= #foo{' misses cases where a record is 
instantiated as the argument of a function call, and so on. It's hard to 
know that you've found all the occurrences.

This little trick works pretty well, though: you add a dummy field to 
the record definition (usually in a header file):

   -record(foo, {'$hidden' = 1/0,
                 ...}).

This will not cause errors or warnings at the point of the record 
declaration, so modules that include the header file and just use the 
record for pattern matching and field accesses will compile cleanly. But 
instantiations of the record, such as 'X=#foo{...}', will cause the 
compiler to warn that "this expression will fail with a 'badarith' 
exception". Only instantiations that override this locally will not 
trigger the warning. Since you just added that field, there should not 
be any cases like that in the code, apart from the one you write in your 
new instantiator function:

   init_foo(...) -> #foo{'$hidden'=[], ...}.

The exception is that if you have a record instantiation on the form 
'#foo{..., _=Default}', which overrides the default setting for all 
fields not explicitly mentioned (usually only used in match specs). You 
can use this to suppress the warning in places like unit tests where you 
might want to allow direct instantiation.

Of course, once you're done refactoring and have all instantiations 
under control, you remove the dummy field again (in particular if it's 
used for a mnesia table).

Have a nice weekend,

     /Richard



More information about the erlang-questions mailing list