Compilation 编译错误:Erlang中宏的记录替换

Compilation 编译错误:Erlang中宏的记录替换,compilation,macros,erlang,record,Compilation,Macros,Erlang,Record,这是目录结构 src/ 动物。hrl people.hrl 数据_animal.erl 个人数据。erl test.erl test_macro.erl -module(test_macro). %% API -export([get_animal_list/1,get_people_list/1]). -include("animal.hrl"). -include("people.hrl"). -define(get_list(DataMod,Record,Age),( Fun=f

这是目录结构

src/
动物。hrl
people.hrl
数据_animal.erl
个人数据。erl
test.erl
test_macro.erl

-module(test_macro).

%% API
-export([get_animal_list/1,get_people_list/1]).

-include("animal.hrl").
-include("people.hrl").

-define(get_list(DataMod,Record,Age),(
  Fun=fun(Id,Acc)->
    case DataMod:get(Id) of
      #Record{age=Age}=Conf->
        [Conf|Acc];
      _->
        Acc
    end
  end,
  lists:foldl(Fun,[],DataMod:get_ids())
)).

get_animal_list(Age)->
  ?get_list(data_animal,animal,Age).

get_people_list(Age)->
  ?get_list(data_people,people,Age).
动物激素

%% The record definition of animal.

-ifndef(ANIMAL).
-define(ANIMAL,true).

-record(animal,{
  id,
  animal_name,
  age
}).

-endif.
人民网

%% The record definition of people.

-ifndef(PEOPLE).
-define(PEOPLE,true).

-record(people,{
  id,
  people_name,
  age
}).

-endif.
数据_animal.erl

%% The data file of animal.

-module(data_animal).
-include("animal.hrl").

%% API
-export([get/1,get_ids/0]).

get(1)->
  #animal{
    id=1,
    animal_name="cat",
    age=23
  };
get(2)->
  #animal{
    id=2,
    animal_name="dog",
    age=19
  };
get(3)->
  #animal{
    id=3,
    animal_name="tiger",
    age=23
  };
get(4)->
  #animal{
    id=4,
    animal_name="pig",
    age=19
  };
get(_)->
  undefined.

get_ids()->
  [1,2,3,4].
数据_people.erl

%% The data file of people.

-module(data_people).
-include("people.hrl").

%% API
-export([get/1,get_ids/0]).

get(1)->
  #people{
    id=1,
    people_name="John",
    age=23
  };
get(2)->
  #people{
    id=2,
    people_name="Ken",
    age=19
  };
get(3)->
  #people{
    id=3,
    people_name="Tom",
    age=23
  };
get(4)->
  #people{
    id=4,
    people_name="Healthy",
    age=19
  };
get(_)->
  undefined.

get_ids()->
  [1,2,3,4].
注意,对于
data\u animal.erl
data\u people.erl
get/1
的参数是返回值的记录id,
get\u id/0
的返回值是
get/1
的参数列表

test.erl

-module(test).

%% API
-export([get_animal_list/1,get_people_list/1]).

-include("animal.hrl").
-include("people.hrl").

get_animal_list(Age)->
  Fun=fun(Id,Acc)->
    case data_animal:get(Id) of
      #animal{age=Age}=Conf->
        [Conf|Acc];
      _->
        Acc
    end
      end,
  lists:foldl(Fun,[],data_animal:get_ids()).

get_people_list(Age)->
  Fun=fun(Id,Acc)->
    case data_people:get(Id) of
      #people{age=Age}=Conf->
        [Conf|Acc];
      _->
        Acc
    end
      end,
  lists:foldl(Fun,[],data_people:get_ids()).
我想得到23岁的动物和人的数据,所以我写了两个函数,
get\u animal\u list/1,get\u people\u list/1

我跑

突然,我发现这两个函数具有相同的模式。然后我尝试编写一个宏
get_list
,并进行两次调用

test_macro.erl

-module(test_macro).

%% API
-export([get_animal_list/1,get_people_list/1]).

-include("animal.hrl").
-include("people.hrl").

-define(get_list(DataMod,Record,Age),(
  Fun=fun(Id,Acc)->
    case DataMod:get(Id) of
      #Record{age=Age}=Conf->
        [Conf|Acc];
      _->
        Acc
    end
  end,
  lists:foldl(Fun,[],DataMod:get_ids())
)).

get_animal_list(Age)->
  ?get_list(data_animal,animal,Age).

get_people_list(Age)->
  ?get_list(data_people,people,Age).
但我得到了编译错误:

4> c(test_macro).
test_macro.erl:22: syntax error before: ','
test_macro.erl:25: syntax error before: ','
test_macro.erl:4: function get_animal_list/1 undefined
test_macro.erl:4: function get_people_list/1 undefined
error
告诉我为什么~y~y~

谢谢大家!! 我现在有三个问题

  • 我的代码真的不像Erlang吗?这是从我公司的项目中提取的。我还在用OOP思考吗?或者我公司的编程人员也是这样
  • 感谢@mlambrichs的建议。它可以工作,但我仍然想知道为什么我的代码会出现编译错误?是不是因为Erlang预处理器是一个单程扫描程序,所以它无法识别
    #Record{age=age}
  • 根据@mlambrichs的建议,我尝试更改宏

    -定义(获取列表(数据模型、记录、年龄), [P | | P DataMod:get(Id)end, DataMod:get_id()), P#Record.age=:=年龄] )

  • 转化为函数

    get_list(DataMod, Record, Age)->
      [P || P <- lists:map(fun(Id) -> DataMod:get(Id) end,
        DataMod:get_ids()),
        P#Record.age =:= Age].
    
    get_列表(DataMod、记录、年龄)->
    [P | | P DataMod:get(Id)end,
    DataMod:get_id()),
    P#Record.age=:=age]。
    
    然后我得到编译错误:
    之前的语法错误:记录

    错误的原因是一个放错了位置的“(”应该删除:

    -define(get_list(DataMod,Record,Age), (
                                         ^^^
       Fun=fun(Id,Acc)->              
         case DataMod:get(Id) of
            #Record{age=Age}=Conf->
               [Conf|Acc];
            _->
               Acc
         end
       end,
       lists:foldl(Fun,[],DataMod:get_ids())
    ).
    
    编辑 你添加了一些问题,我想现在开始回答

    • 我的代码真的不像Erlang吗?
      • 宏的使用。在你的情况下没有必要使用宏
      • 一般来说:你想隐藏在人和动物身上使用的是什么样的记录。这是实现,应该被你的界面屏蔽。你可以在正确的模块中定义一个getter函数来处理这个问题。请阅读我的重写建议
    • 它可以工作,但我仍然想知道为什么我的代码会出现编译错误?请参阅答案的顶部
    • ..我试图更改宏…你是对的,该函数无法编译。显然需要重写
    像这样:

    get_list(DataMod, Age) ->
        [ P || P = {_,_,_,A} <- lists:map(fun(Id) -> DataMod:get(Id) end,
               DataMod:get_ids()),
               A =:= Age].
    
    让我们也修复get_list宏。您的宏定义get_list有3个参数,其中只需要2个参数。为什么要在get_people_list/1和get_animal_list/1中使用Record作为参数?例如,请尝试以下操作:

    -define(get_list(DataMod, Y),
       case DataMod of
          data_animal -> get_animal_list(Y);
          data_people -> get_people_list(Y);
          _Else -> []
       end
    )
    
    总的来说,您的测试模块中存在大量代码复制。按照@yjcdll的建议,将接口函数移到动物和人的模块中

    让我们看看您的数据模块及其get函数

    我建议将所有人员记录放在一个数组中,以您的情况为例,放在data_people模块中

    people() -> [
       #people{ id=1, people_name="John", age=23 },
       #people{ id=2, people_name="Ken", age=19 },
       #people{ id=3, people_name="Tom", age=23 },
       #people{ id=4, people_name="Healthy", age=19 } ].
    
    接下来,您需要一个getter函数来仅获取具有特定年龄的人:

    get(Age) ->
       [X || X <- people(), is_age( X, Age )].
    
    因此,在模块测试中,get_people_list/1将变得简单得多

    get_people_list(Age) ->
       data_people:get(Age).
    
    诸如此类。始终注意那些看起来与您在某个地方已经使用过的代码几乎相同的代码。试着表现得像一个理智、懒惰的程序员。lazy=good.;-)

    编辑:OP必须坚持给定的模块。因此,宏的重写是:

    -define(get_list(DataMod, Record, Age),
       [P || P <- lists:map(fun(Id) -> DataMod:get(Id) end, 
                                       DataMod:get_ids()), 
             P#Record.age =:= Age]
    ).
    
    -定义(获取列表(数据模式、记录、年龄),
    [P | | P DataMod:get(Id)end,
    DataMod:get_id()),
    P#Record.age=:=年龄]
    ).
    
    有关样式的说明(这可能会理所当然地解决您的问题)直接在.erl文件中定义记录。只有一个
    animal.erl
    和一个
    people.erl
    并将接口函数写入数据,以便它们作为自己的抽象数据类型。为了在Erlangdom中进一步实现这一点(并按照Alan Kay的意图使其成为OOP),可以使
    人.erl
    动物.erl
    模块定义过程,以便每个实例都是动物或人。将接口函数作为访问器写入这些进程。通过这种方式,像游戏服务器这样的东西在Erlang中得到了简化?更重要的是,如果有人能在不使用列表的情况下优化我的代码,我将不胜感激:foldl/3。宏定义末尾缺少“结尾”)“否,有一个开头”(“就在应该删除的有趣定义之前。如果添加额外的”)”这是行不通的,所以你需要有人为工作或学校校对你的语法,而不是从更一般的意义上指导你走向更好的Erlang。非常:-/也许你误解了。我无法更改代码结构,即数据的分布。我想做的是抽象get__列表函数的公共部分并生成一个宏。为什么记录名不能被预处理器替换。Aha。也许这会有帮助:-定义(get_list(DataMod,Record,Age),[P | P DataMod:get(Id)end,DataMod:get_Id()),P#Record.Age=:=Age])。
    get_people_list(Age) ->
       data_people:get(Age).
    
    -define(get_list(DataMod, Record, Age),
       [P || P <- lists:map(fun(Id) -> DataMod:get(Id) end, 
                                       DataMod:get_ids()), 
             P#Record.age =:= Age]
    ).