Sunday, March 27, 2016

dets:select_delete: exception error: bad argument

When first learning about how to delete records from an Erlang dets table, I kept getting this error from the dets:select_delete() function:

Erlang/OTP 18 [erts-7.2.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Eshell V7.2.1  (abort with ^G)
1> c(dets_select_delete).  
{ok,dets_select_delete}
2> dets_select_delete:test().
** exception error: bad argument
     in function  dets:select_delete/2
        called as dets:select_delete(test,[{{'_','_','$1'},[{'<','$1',3}],[]}])
3>

Here is the code:

-module(dets_select_delete).
-export([test/0]).

% Test syntax of match clause.
test() ->
    %delete_dets(),
    {ok, test} = dets:open_file(test, [{type, set}, {file, "test.dets"}]),
    % Add some data
    ok = dets:insert(test, {a, 1}),
    ok = dets:insert(test, {b, 2}),
    ok = dets:insert(test, {c, 3}),
    Match = [{{'_','_','$1'},[{'<','$1',3}],[]}],
    DeletedN = dets:select_delete(test, Match),
    DeletedN.

The issue was with the return value clause:

    Match = [{{'_','_','$1'},[{'<','$1',3}],[]}],
                                           ^^^^
                                             |
                                             +-- wrong return value clause.

This is the correct match specification:

    Match = [{{'_','_','$1'},[{'<','$1',3}],[true]}],
                                           ^^^^^^^
                                             |
                                             +-- right return value clause.

I was confused by the examples "Match specifications in Erlang" [http://erlang.org/doc/apps/erts/match_spec.html], the simplest of which always have an empty return clause. Since the match spec is kind of complex, I thought it was a problem in my match spec.

I sorted this out by using the shell, and verifying my match spec was correct with the dets:select/2. Once I knew it was correct, I went back and read the docs to select_delete again, and there it is, clear as day:

Deletes each object from the table Name such that applying the match specification MatchSpec to the object returns the value true.

select_delete(Name, MatchSpec) -> N | {error, Reason}, Retrieved March 27, 2016.