使用记录列表时Erlang非法模式

时间:2015-12-05 15:41:47

标签: erlang

我正在尝试在Erlang中编写简单的地址簿。我已经开始:

-record(entry, {name, surname, phone, email}).

createAdressBook() -> [].

addContact(Name, Surname, AdressBook) ->
  case isAlready(Name, Surname, AdressBook) of
    false -> [#entry{name = Name, surname = Surname}|AdressBook];
    _ -> {error, "This entry already exists"}
  end.

isAlready(_, _, []) -> false;
isAlready(Name, Surname, [#entry{name = Name, surname = Surname}|_]) -> true;
isAlready(Name, Surname, [_|T]) -> isAlready(Name, Surname, T).

然而,过了一会儿,我决定将名字和姓氏放在一起。将代码更改为以下后,会引发编译错误(新的isAlready / 3的第二行中的非法模式。

-record(entry, {person, phone, email}).

createAdressBook() -> [].

addContact(Name, Surname, AdressBook) ->
  case isAlready(Name, Surname, AdressBook) of
    false -> [#entry{person = Name ++ " " ++ Surname}|AdressBook];
    _ -> {error, "This entry already exists"}
  end.

isAlready(_, _, []) -> false;
isAlready(Name, Surname, [#entry{person = Name ++ " " ++ Surname}|_]) -> true;
isAlready(Name, Surname, [_|T]) -> isAlready(Name, Surname, T).

我做错了什么以及检查string1 + " " + string2是否是列表首长的正确原因是什么?

3 个答案:

答案 0 :(得分:3)

您正尝试在功能头中执行操作,而不是仅在使用++时进行匹配。所以这不会起作用。相反,使用调用函数中的机会只创建一次Person值,并从那里始终如一地使用它:

-record(entry, {person, phone, email}).

createAdressBook() -> [].

add_contact(Name, Surname, AdressBook) ->
  Person = Name ++ " " ++ Surname,
  case is_already(Person, AdressBook) of
    false -> [#entry{person = Person}|AdressBook];
    _ -> {error, "This entry already exists"}
  end.

is_already(_, []) -> false;
is_already(Person, [#entry{person = Person}|_]) -> true;
is_already(Person, [_|T]) -> is_already(Person, T).

或者,您可以使用记录和元组索引的属性来使用搜索功能而不是编写自己的搜索功能:

is_already(Person, AddressBook) ->
    case lists:keyfind(Person, #entry.person, AddressBook) of
        #entry{} -> true;
        false    -> false
    end.

作为样式注释 - 您注意到我将函数名称从isAlready更改为is_already。在Erlang中,大写单词具有特殊含义,为防止混淆,我们只使用all_lower_and_underscores作为函数名称,使用AllUpperCamelCase作为变量。

答案 1 :(得分:2)

zxq9 发布他的回答之前,我发现另一个解决办法是将名字和姓氏保留为记录人员字段中的元组。

-record(entry, {person, phone, email}).

createAdressBook() -> [].

addContact(Name, Surname, AdressBook) ->
  case isAlready(Name, Surname, AdressBook) of
    false -> [#entry{person = {Name, Surname}}|AdressBook];
    _ -> {error, "This entry already exists"}
  end.

isAlready(_, _, []) -> false;
isAlready(Name, Surname, [#entry{person = {Name, Surname}}|_]) -> true;
isAlready(Name, Surname, [_|T]) -> isAlready(Name, Surname, T).

答案 2 :(得分:2)

当使用++进行模式匹配时,必须在编译时知道标题元素。 例如,

TitledName = "Mr. Black",
"Mr. "++LastName= TitledName

就像:

[$M, $r, $., $\s|LastName]= TitledName.