Как сопоставить ets:match с записью в Erlang?

Я слышал, что указание записей через кортежи в коде — плохая практика: я всегда должен использовать поля записи (#record_name{record_field = something}) вместо простых кортежей {record_name, value1, value2, something}.

Но как сопоставить запись с таблицей ETS? Если у меня есть таблица с записями, я могу сопоставить только следующее:

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

Очевидно, что как только я добавлю несколько новых полей в определение записи, это сопоставление с шаблоном перестанет работать.

Вместо этого я хотел бы использовать что-то вроде этого:

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

К сожалению, он возвращает пустой список.


person skanatek    schedule 29.09.2011    source источник


Ответы (3)


Причина вашей проблемы заключается в том, что устанавливаются неуказанные поля, когда вы выполняете #record_name{record_field=something}. Это синтаксис для создания записи, здесь вы создаете запись/кортеж, который ETS интерпретирует как шаблон. Когда вы создаете запись, все неуказанные поля получают свои значения по умолчанию, либо определенные в определении записи, либо значение по умолчанию по умолчанию undefined.

Поэтому, если вы хотите присвоить полям определенные значения, вы должны сделать это явно в записи, например #record_name{f1='$1',f2='$2',record_field=something}. Часто при использовании записей и ets вы хотите установить для всех неуказанных полей значение '_', "независимую переменную" для сопоставления ets. Для этого существует специальный синтаксис с использованием специального и недопустимого имени поля _. Например #record_name{record_field=something,_='_'}.

Обратите внимание, что в вашем примере вы установили для элемент имени записи в кортеже значение '$1'. Кортеж, представляющий запись, всегда имеет имя записи в качестве первого элемента. Это означает, что когда вы создаете таблицу ets, вы должны установить ключевую позицию с {keypos,Pos} на что-то отличное от значения по умолчанию 1, иначе не будет никакой индексации и, что еще хуже, если у вас есть таблица типа «set» или «ordered_set», вы будете получить только 1 элемент в таблице. Чтобы получить индекс поля записи, вы можете использовать синтаксис #Record.Field, в вашем примере #record_name.record_field.

person rvirding    schedule 29.09.2011
comment
После этого примера: #record_name{f1='$1',f2='$2',record_field=something} вы привели пример: #record_name{record_field=something,_='_'}. Создается впечатление, что однократное написание _='_' будет соответствовать всем остальным полям, но в моих попытках вы должны написать _='_' для каждого дополнительного поля. Это означает, что если вы измените определение записи, чтобы иметь больше или меньше полей, вам также придется изменить спецификацию соответствия, что, очевидно, не идеально. Одна приятная вещь: вам не нужно указывать поле, которое вы сопоставляете, например. record_field=something , в правильном месте в кортеже... - person 7stud; 14.07.2019
comment
... Вы можете сначала указать поле, которое вы ищете, а затем указать правильный номер _='_'. Например, с этим определением записи -record(user, {id, name, city}) вы можете использовать подобный шаблон #user{city="London", _='_', _='_'}. - person 7stud; 14.07.2019

Попробуйте использовать

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

См. это для объяснения.

person gleber    schedule 29.09.2011

Искомый формат: #record_name{record_field=что-то, _ = '_'}

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

http://www.erlang.org/doc/programming_examples/records.html (см. 1.3 Создание записи)

person Paul Peregud    schedule 29.09.2011