Andriy Drozdyuk
Andriy Drozdyuk

Reputation: 61091

Records vs Tagged tuples in public api

Is it common practice to return records from query functions? If not, what are the downsides?

Let's say I have a query service, that can return some cars and whether they are currently rented or not.

My record for car looks something like this:

-type rent_state:: rented | available.
-record(car, {make::string(), year::integer(), color::string(), state::rent_state()}).

If I then had a query for cars, is it a reasonable thing to do to return this record?

-type car::#car{}.
-spec cars() -> [car()].

or should I create a tagged tuple type instead?

-type car()::{ {make, string()}, {year,integer()}, {color,string()}, {state,rent_state()}}).

I want to make an API that is pleasant to use for others. Any advice appreciated.

Upvotes: 3

Views: 227

Answers (1)

Nathaniel Waisbrot
Nathaniel Waisbrot

Reputation: 24493

I like using records locally to a module, but I find that sharing them between applications runs into a few warts:

  • It's a little painful to get them loaded into the REPL
  • Record definitions are global, so you'd probably want to name your record drozzy_vehicles_car or something else long and then using it would be ugly
  • Users of your library have to include your header file that defines the record or it won't work

The tagged tuple you describe seems like a big pain to work with -- there's no easy way to grab something out of the middle.

I would use maps if you're lazy and accessors if you aren't.

Maps:

Car = #{ make => "foo", year => 2016, color => "red", state => rented}.

Accessors:

1> Car = rentals:get_car().
{car,"foo",2016,"red",rented}  %% it's actually a record, but we don't expose that!
2> rentals_car:year(Car).
2016
3> rentals_car:state(Car).
rented
4> % etc

Upvotes: 3

Related Questions