处理记录列表时出现Erlang非法模式

处理记录列表时出现Erlang非法模式,erlang,Erlang,我正在尝试用Erlang编写简单的地址簿。我从以下几点开始: -record(entry, {name, surname, phone, email}). createAdressBook() -> []. addContact(Name, Surname, AdressBook) -> case isAlready(Name, Surname, AdressBook) of false -> [#entry{name = Name, surname = Sur

我正在尝试用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).
然而,过了一会儿,我决定把名字和姓氏保留在一起。将代码更改为以下代码后,将引发编译错误(new 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
是列表的标题吗?

您试图在函数标题中执行一个操作,而不仅仅是在使用
++
时进行匹配。因此,这不会起作用。相反,使用调用函数中的opportunity创建
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\u ready
。在Erlang中,大写单词有一个特殊的含义,为了避免混淆,我们只需对函数名使用所有的\u小写字母和\u下划线,对变量使用大写字母。

您正在尝试在函数中执行一个操作首先,不要只在使用
++
时进行匹配。这样做不起作用。相反,使用调用函数中的opportunity只创建一次您的
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\u ready
。在Erlang中,大写单词有一个特殊的含义,为了避免混淆,我们只需将所有的_lower\u和_下划线用作函数名,将AllUpperCamelCase用作变量。

就在zxq9发布他的答案之前我发现另一个解决方案是在记录的person字段中保留name和姓氏作为元组

-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).
就在zxq9发布他的答案之前,我发现另一个解决方案是将姓名作为元组保存在记录的person字段中

-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).

当模式匹配wiht++时,编译时必须知道heading元素。 比如说,

TitledName = "Mr. Black",
"Mr. "++LastName= TitledName
就像:

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

当模式匹配wiht++时,编译时必须知道heading元素。 比如说,

TitledName = "Mr. Black",
"Mr. "++LastName= TitledName
就像:

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

我决定使用我的解决方案,因为它避免使用连接,但我将您的标记为已接受,因为您解决了++为什么不能在模式匹配中工作的问题。谢谢:)我决定使用我的解决方案,因为它避免使用连接,但我将您的标记为已接受,因为您解决了++为什么不能在模式匹配中工作的问题。谢谢你:)真的!无论如何,这可能是一个更好的全面解决方案,因为您可以避免在内部篡改数据。当然,这是一个体系结构的问题,而不是本例中的匹配技术,但我唯一想将它们连接到一个字符串中的地方是当您向用户或另一个需要格式化数据的系统呈现输出时。的确!无论如何,这可能是一个更好的全面解决方案,因为您可以避免在内部篡改数据。这是一个体系结构的问题,当然不是本例中的匹配技术,但我唯一想将它们连接到一个字符串中的地方是当您向用户或另一个需要格式化数据的系统呈现输出时。