Benjamin Halsted // [bgh] todo, add something clever here.

17Mar/100

Erlang Programming Exercise: 3-4

In this exercise you are to make a database using this interface:

db:new() ⇒ Db.
db:destroy(Db) ⇒ ok.
db:write(Key, Element, Db) ⇒ NewDb.
db:delete(Key, Db) ⇒ NewDb.
db:read(Key, Db) ⇒{ok, Element} | {error, instance}.
db:match(Element, Db) ⇒ [Key1, ..., KeyN].

This one took a while to get right. In other languages I can look at some code and quickly figure out what it does. When I look at erlang recursive list code, it takes a while to parse it and figure out what it does.

In the read/2 and match/2 functions below, I end up discarding the head item from the list if it doesn't match what I'm looking for. It took a while for me to get used to throwing away data like this. In other languages I would iterated over the list until I found what I was looking for, saving allocation and deallocation cycles. Getting access to the head item in Erlang is very fast so this is a common pattern. This makes me wonder what sort of optimizations the Erlang VM (beam) guys have done to minimize the data copy costs. Anyhow, here is my solution:

-module(threefour_db).
-export([new/0, destroy/1, write/3, delete/2, read/2, match/2]).

new() ->
	[].

destroy(_Db) ->
	ok.

delete(_Key, NewDb, []) ->
	NewDb;
delete(Key, NewDb, [{Key, _Element}|T]) ->
	delete(Key, NewDb, T);
delete(Key, NewDb, [H|T]) ->
	delete(Key, [H|NewDb], T).

delete(Key, Db) ->
	delete(Key, [], Db).

write(Key, Element, Db) ->
	NewDb = delete(Key, Db),
	[{Key, Element}|NewDb].

read(_Key, []) ->
	{error, instance};
read(Key, [{Key,Element}|_T]) ->
	{ok, Element};
read(Key, [_H|T]) ->
	read(Key, T).

match(_Element, [], Keys) ->
	Keys;
match(Element, [{Key,Element}|Db], Keys) ->
	match(Element, Db, [Key|Keys]);
match(Element, [_H|Db], Keys) ->
	match(Element, Db, Keys).

match(Element, Db) ->
	match(Element, Db, []).

Cheers,
-Halzy

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Reddit
  • Twitter