1
votes

As an exercise in learning Erlang, I'm trying to write a simple database (from O'Reilly's Programming Erlang).

Basically I have a list of Tuples like this:

Db1 = [{person1,charleston},{person2,charleston},{person3,chicago}].

I need to create function such that

db:match(charleston,Db1).

returns

[person1,person2]

Here's the method that I wrote:

match(Element, Db) -> match(Element, Db, []).
match(_Element,[], Results) -> Results;
match(Element, [{Key,Value}|T], Results) ->
    case Value == Element of
        true -> match(Element, T, [Results,Key]);
        false -> match(Element,T,Results)
    end.

The result I'm getting back is this:

[[[],person1],person2]

I know there are ways of combining lists with the lists.erl module, but I'm trying to bypass it in an effort to learn more about the language. Any ideas what I'm doing wrong?

3
your case Value == Element can be folded into the clause: match(Value, [{Key, Value}|T], ...) -> and so on. - I GIVE CRAP ANSWERS
And your case is so simple I wouldn't use a tail recursive accumulator here, but rather use [Key|match(Element, T)] as a recurser. - I GIVE CRAP ANSWERS

3 Answers

7
votes

You're re-inventing the wheel. Just use list comprehension:

match(X, Db) -> [P || {P, E} <- Db, E == X].
5
votes

the problem is how you are building up your list, try this instead:

case Value == Element of
    true -> match(Element, T, [Key|Results]);
    false -> match(Element,T,Results)
end.
  • [A,B] builds a new list with elements A and B.
  • [A|B] prepends A to the list B.
1
votes

An alternate way to write the code directly is

match(_Value, []) -> [];
match(Value, [{Key,Value}|T]) ->
    [Key|match(Value, T)];
match(Value, [_|T]) ->
    match(Value, T).

The list comprehension in @Little Bobby Tables solution is equivalent to this.