erlang mnesia-非法记录信息

erlang mnesia-非法记录信息,erlang,record,mnesia,Erlang,Record,Mnesia,我正在尝试使用一个函数来确保我所需要的表已经创建,如果不创建它的话。以下是示例: ensure_table_exists(Table, MnesiaTables, Nodes) -> case lists:member(Table, MnesiaTables) of true -> throw({error, db_might_have_already_been_created}); false -> mnesia:create_

我正在尝试使用一个函数来确保我所需要的表已经创建,如果不创建它的话。以下是示例:

ensure_table_exists(Table, MnesiaTables, Nodes) ->
case lists:member(Table, MnesiaTables) of
    true ->
        throw({error, db_might_have_already_been_created});
    false ->
        mnesia:create_table(Table, [{disc_copies, Nodes},
                {attributes, record_info(fields, Table)}]), 
        ok  
end.
问题是编译时出现错误:
非法记录信息

可能需要这样做:record\u info在编译时解析,或者record info的第二个参数实际上应该是一个可以从源代码中检索的记录?

您可能需要查看一下

阅读描述:

该模块是一个解析转换 允许您导出记录。这个 transform为添加访问器函数 实例化、检查和测试 修改记录,而无需 引入编译时依赖关系 在模块之间

尽管如此,我还是觉得你的功能有点保守。下页解释了为什么在Erlang中进行防御编程是一个坏习惯:

是的,所有与记录相关的事情,包括
record\u info/2
都在编译时解决。这意味着记录和字段名必须在编译时已知。这就是编译器错误的原因

我不认为你的函数真的太过保守,因为你所做的只是发出一个更具体的错误信号。如果您返回
{error,…}
,那将是另一回事

最后一点是,如果要引发异常,则不应使用
throw/1
,而应使用
erlang:error/1
throw
用于非本地返回(使用
catch
捕获),而
erlang:error
用于引发异常。在许多情况下,结果可能相同,但实际错误值可能会产生误导(
nocatch
)。你越清楚地表明你的意图越好,在这种情况下,这是一个错误的信号


是的,我知道,
catch
也会捕获错误/退出。这是故意的。在一个完美的世界中,可能
catch
只应捕获抛出的内容,而
try
只应捕获错误/退出。

不幸的是,record\u info实际上不是一个函数,即使它看起来像一个函数

您可以通过测试以下各项来验证这一点。创建一个文件:

 -module(something).
 -record(a, {}).
启动Erlang shell:

 > rr(something).
 [a]
 > record_info(fields, a).
 []
 > A = a.
 > record_info(fields, A).
 * 2: illegal record info
因此,我的建议是对记录信息部分使用宏或专用函数

回答你原来的问题。使用类似于:

 tables() ->
   [?TABLE_MACRO(tablename),
    ?TABLE_MACRO(tablename2),
    ...].
 -define(TABLE_MACRO(Table), fun() ->
      mnesia:create_table(Table, [{disc_copies, Nodes},
               {attributes, record_info(fields, Table)}])
      end).
其中,TABLE_宏类似于:

 tables() ->
   [?TABLE_MACRO(tablename),
    ?TABLE_MACRO(tablename2),
    ...].
 -define(TABLE_MACRO(Table), fun() ->
      mnesia:create_table(Table, [{disc_copies, Nodes},
               {attributes, record_info(fields, Table)}])
      end).
然后使用下面的函数

 [case CreateTable of
   {aborted, {already_exists, _}} -> ok;
   {atomic, ok} -> ok
  end || CreateTable <- tables()].
[case CreateTable of
{中止,{已经存在,{}}->确定;
{原子,ok}->ok

end | | CreateTable我知道在Erlang中进行防御性编程的坏习惯,但我不明白这与我的函数有什么关系?我只是想确保我没有创建模式。