[英]compilation error: record replacement of macro in Erlang
这是目录结构。
SRC /
animal.hrl
people.hrl
data_animal.erl
data_people.erl
test.erl
test_macro.erl
animal.hrl
%% The record definition of animal.
-ifndef(ANIMAL).
-define(ANIMAL,true).
-record(animal,{
id,
animal_name,
age
}).
-endif.
people.hrl
%% The record definition of people.
-ifndef(PEOPLE).
-define(PEOPLE,true).
-record(people,{
id,
people_name,
age
}).
-endif.
data_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].
data_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_animal.erl
和data_people.erl
, get/1
的参数是返回值的记录ID,而get_ids/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岁的动物和人的数据,因此我编写了2个函数get_animal_list/1, get_people_list/1
。
我跑
1> c(data_animal),c(data_people),c(test).
{ok,test}
2> test:get_people_list(23).
[{people,3,"Tom",23},{people,1,"John",23}]
3> test:get_animal_list(23).
[{animal,3,"tiger",23},{animal,1,"cat",23}]
突然,我发现这两个函数共享相同的模式。 然后,我尝试编写宏get_list
,并进行2次调用。
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〜
谢谢你们! 我现在有3个问题。
#Record{age=Age}
扫描程序,所以无法识别#Record{age=Age}
? 根据@mlambrichs的建议,我尝试更改宏
-define(get_list(DataMod,Record,Age),[P || P <-list:map(fun(Id)-> DataMod:get(Id)end,DataMod:get_ids()),P#Record.age = := Age])。
转化为功能
get_list(DataMod, Record, Age)->
[P || P <- lists:map(fun(Id) -> DataMod:get(Id) end,
DataMod:get_ids()),
P#Record.age =:= Age].
然后我得到编译错误: syntax error before: Record
错误的原因是放错了'(',应将其删除:
-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_list(DataMod, Age) ->
[ P || P = {_,_,_,A} <- lists:map(fun(Id) -> DataMod:get(Id) end,
DataMod:get_ids()),
A =:= Age].
编辑
进行重写。 您想要的是功能测试中两个列表的串联(您的test / 0,我的test / 1)。 使用逗号不会为您做到这一点。 ;-)
test(X)->
?get_list(data_animal,X) ++
?get_list(data_people,X).
让我们也修复该get_list宏。 您的宏定义get_list有3个参数,只需要2个参数。为什么已经在get_people_list / 1和get_animal_list / 1中使用Record作为参数,为什么要使用Record作为参数? 例如,尝试以下操作:
-define(get_list(DataMod, Y),
case DataMod of
data_animal -> get_animal_list(Y);
data_people -> get_people_list(Y);
_Else -> []
end
)
总体而言,您的测试模块中有很多代码复制。 作为@yjcdll的建议的后续措施,请将接口功能(动物和人)移至其自己的模块。
让我们来看看您的数据模块及其获取功能。
我建议将所有人员记录放在一个数组中,在您的情况下,放在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 )].
is_age / 2函数将是:
is_age( Person, Age ) ->
Person#people.age =:= Age.
因此,在模块测试中,您的get_people_list / 1将变得更加简单。
get_people_list(Age) ->
data_people:get(Age).
等等。 始终在寻找与您在某处已经使用过的代码看起来几乎一样的代码。 只是尝试表现一个理智,懒惰的程序员。 懒惰=好。 ;-)
编辑:OP必须坚持给定的模块。 因此,宏的重写为:
-define(get_list(DataMod, Record, Age),
[P || P <- lists:map(fun(Id) -> DataMod:get(Id) end,
DataMod:get_ids()),
P#Record.age =:= Age]
).
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.