[erlang-questions] Record typing for dialyzer

3 views
Skip to first unread message

Bernard Duggan

unread,
Nov 24, 2009, 6:37:28 PM11/24/09
to Erlang Questions List
Hi list,
We have a lot of auto-generated record types that we use to allow
our (newer, awesomer) erlang/mnesia code to interact with our (older,
less awesome, but we're stuck with it for now) C++/mysql code. It
recently occurred to me that it would be a simple matter to add type
specifiers to the records to give dialyzer (which we love to death) some
extra info to work with. And for the most part it was. So we now have
nice auto-generated records of the form:

-record( person{
id :: integer(),
name :: string(),
is_awesome :: boolean()
}).

which is great (and already helped us find several bugs - have I
mentioned we love dialyzer?). We struck a problem, however, when we
used one of our records in a select statement thus:

Match = #person{name="Bernie", id='$1', _='_'},
mnesia:select(person, [{Match, [], [{{'$1'}}]}]),

At this point, dialyzer quite correctly points out that '$1' isn't an
integer and '_' isn't a boolean and so we've got no business assigning
them to fields typed as such.

My solution, then was to add an extra type definition:

-type search_spec() :: '_' | '$1' | '$2' | '$3' | '$4' | '$5' | '$6' |
'$7' | '$8' | '$9'.

and change all the record definitions to something like:

-record( person{
id :: integer() | search_spec(),
name :: string() | search_spec(),
is_awesome :: boolean() | search_spec()
}).

Now this solves the problem, but it really looks ugly and seems like
kind of a hack and I can't help but feel like there must be some more
elegant solution. But I don't know what it is :) Any input (even if
it's only "nope, there's no better way to do it") would be greatly
appreciated.

Cheers,

Bernard

________________________________________________________________
erlang-questions mailing list. See http://www.erlang.org/faq.html
erlang-questions (at) erlang.org

Paul Mineiro

unread,
Nov 24, 2009, 7:21:56 PM11/24/09
to Erlang Questions List
I had the same problem.

I ended up keeping the type signature in the declaration strict, and using
setelement/3 to construct the type-violating version of the record that I
pass to mnesia:select/2.

-- p

Bernard Duggan

unread,
Nov 24, 2009, 7:51:41 PM11/24/09
to Erlang Questions List
That was another other option I toyed with - I ended up coming down on
the side of keeping the "code" as un-hacked as possible and just messing
with the headers and auto-generated stuff. My reasoning being that I
didn't want others in the team to have to re-solve the problem every
time they wanted to use a select() statement. Not that I'm saying it's
not a perfectly valid solution, just explaining why I didn't choose it :)

Cheers,

B

Kostis Sagonas

unread,
Nov 25, 2009, 2:44:06 AM11/25/09
to Erlang Questions List, Bernard Duggan

I am not aware of any cleaner way of doing what you want to do, so what
you've done is how I would personally also do it. The only thing I
would recommend is to try to add these declarations as sparsely as
possible, meaning try to add them only to the record fields that are
used in match specifications in your program, not everywhere.

The problem is that you (and dialyzer) are up against a really bad
design decision in the language here, namely the use of "special" atoms
to represent variables in match specifications. I sincerely hope that
this is fixed by Erlang providing an alternative way of writing match
specifications that does not lie about types.

Thanks for your thumbs up for dialyzer!

Kostis

Reply all
Reply to author
Forward
0 new messages