Erlang mnesia - illegal recording

I am trying to create a function that ensures that the table I need is already created, and if not created. Here's a sample:

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. 

The problem is that when compiling I get an error: illegal record info . Perhaps this should be done so that record_info is allowed at compile time, or that the second argument to write information should actually be a record that can be extracted from the source code?

+4
source share
3 answers

Yes, all things related to recording, including record_info/2 , are allowed at compile time. This means that the names of the records and fields must be known at compile time. This is the cause of the compiler error.

I don’t think your function is really too defensive, because what you are doing is signaling a more specific error. Another thing is if you must return {error, ...} .

The final question is that if you want to raise an exception, you should not use throw/1 , but instead use erlang:error/1 . throw is for non-local return (caught with catch ), and erlang:error is for erlang:error an exception. In many cases, the result may be the same, but the actual value of the error can be misleading ( nocatch ). It is always better than the clearer you can show your intention, which in this case signals an error.

PS Yes, I know that catch also catches errors / exits. It was intentional. In an ideal world, perhaps catch should catch throws and try only errors / exits.

+3
source

Unfortunately, record_info is not really a function, even if it looks like one.

You can verify this by testing the following. Create a file:

  -module(something). -record(a, {}). 

Launch the Erlang shell:

  > rr(something). [a] > record_info(fields, a). [] > A = a. > record_info(fields, A). * 2: illegal record info 

So my recommendation would be to use a macro or a specialized function for the record_info part.

To answer your initial question. Use something like:

  tables() -> [?TABLE_MACRO(tablename), ?TABLE_MACRO(tablename2), ...]. 

where TABLE_MACRO looks something like this:

  -define(TABLE_MACRO(Table), fun() -> mnesia:create_table(Table, [{disc_copies, Nodes}, {attributes, record_info(fields, Table)}]) end). 

and then a function using something like below.

  [case CreateTable of {aborted, {already_exists, _}} -> ok; {atomic, ok} -> ok end || CreateTable <- tables()]. 

Ugh! You can clean it up a bit, but I hope you understand the general idea.

  • Macro instead of using a variable.
  • Matches both {atomic, ok} and {aborted, {already_exists, _TableName}}
+2
source

You might want to take a look at Ulf Wieger betrays .

Reading from the description:

The module is a parsing allowing you to export records. the conversion adds access functions for creating, checking, and modifying records, without the need to introduce compile-time dependencies between modules.

Said your function sounds a little defensive to me. The following page explains why it is a bad habit to program in Erlang:

http://www.erlang.se/doc/programming_rules.shtml#HDR11

0
source

All Articles