简体   繁体   中英

How to match ets:match against a record in Erlang?

I have heard that specifying records through tuples in the code is a bad practice: I should always use record fields ( #record_name{record_field = something} ) instead of plain tuples {record_name, value1, value2, something} .

But how do I match the record against an ETS table? If I have a table with records, I can only match with the following:

ets:match(Table, {$1,$2,$3,something}

It is obvious that once I add some new fields to the record definition this pattern match will stop working.

Instead, I would like to use something like this:

ets:match(Table, #record_name{record_field=something})

Unfortunately, it returns an empty list.

The cause of your problem is what the unspecified fields are set to when you do a #record_name{record_field=something} . This is the syntax for creating a record, here you are creating a record/tuple which ETS will interpret as a pattern. When you create a record then all the unspecified fields will get their default values, either ones defined in the record definition or the default default value undefined .

So if you want to give fields specific values then you must explicitly do this in the record, for example #record_name{f1='$1',f2='$2',record_field=something} . Often when using records and ets you want to set all the unspecified fields to '_' , the "don't care variable" for ets matching. There is a special syntax for this using the special, and otherwise illegal, field name _ . For example #record_name{record_field=something,_='_'} .

Note that in your example you have set the the record name element in the tuple to '$1'. The tuple representing a record always has the record name as the first element. This means that when you create the ets table you should set the key position with {keypos,Pos} to something other than the default 1 otherwise there won't be any indexing and worse if you have a table of type 'set' or 'ordered_set' you will only get 1 element in the table. To get the index of a record field you can use the syntax #Record.Field , in your example #record_name.record_field .

Try using

ets:match(Table, #record_name{record_field=something, _='_'})

See this for explanation.

Format you are looking for is #record_name{record_field=something, _ = '_'}

http://www.erlang.org/doc/man/ets.html#match-2

http://www.erlang.org/doc/programming_examples/records.html (see 1.3 Creating a record)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM