Amnesia: reverse enumerate test does not work

Hi ,

I am playing with the Amnesia tests to learn the user database functions.
First I tested the Enumerate database function. It works fine.
Next I tried the Reverse enumerate database function:

  assert( Amnesia.transaction! do 
   assert Enum.map(Koersen.stream |> Stream.reverse, fn(koers) -> koers.dag
   end) ==  [9,8,7,6,5,4,3,2,1]
  end == true) 

I got this compile error:

 ** (UndefinedFunctionError) function Stream.reverse/1 is undefined or private
     code: assert( Amnesia.transaction! do
     stacktrace:
       (elixir) Stream.reverse(%Amnesia.Table.Stream{dirty: false, lock: :read, reverse: false, table: Dat.Database.Koersen, type: :ordered_set})
       lib/TInstall.ex:148: anonymous fn/0 in Dat.TestDB."test Test cases for an Amnesia database"/1
       (mnesia) mnesia_tm.erl:836: :mnesia_tm.apply_fun/3
       (mnesia) mnesia_tm.erl:811: :mnesia_tm.execute_transaction/5
       lib/TInstall.ex:147: (test)

Does anyone knows what went wrong?

Many thanks in advance,

Thiel Chang

What probably went wrong, is that Stream does not have a reverse/1 function.

And this makes sense: Streams are lazily defined enumerables, which might contain an infinite amount of elements.

To reverse an enumerable, its last element needs to be known.

So in this case, your could use Enum.reverse/1 instead, which will not compute the result lazily, but it’s not possible to compute a reversion operation lazily so that’s the best there is.

Where does Stream come from? There is no Stream.reverse function.

Hi mr Karlsson,

Find enclosed the original Reverse enumerate test from Meh’ Amnesia Database test.

test "reverse enumerator works" do
    IO.write"\nDatabase_test -  Reverse enumerator works "
    Amnesia.transaction! do
      %User{id: 1, name: "John"} |> User.write
      %User{id: 2, name: "Lucas"} |> User.write
      %User{id: 3, name: "David"} |> User.write
    end

    assert(Amnesia.transaction! do
      assert Enum.map(User.stream |> Stream.reverse, fn(user) ->
        user.id
      end) == [3, 2, 1]

      refute Enum.member?(User.stream, 4)
      assert Enum.member?(User.stream, %User{id: 1, name: "John"})
    end == true)
  end

And it uses the Stream reverse function!

I am surprised it does work.

Thiel Chang

1 Like

Hi, just looked at the code. Amnesia provides a Stream with a reverse function.

Your initial code likely use elixir Stream module where this function does not exists.

If you try with Amnesia.Table.Stream.reverse instead it may work. The test code aliases Stream (alias Amnesia.Table.Stream)

2 Likes

Hi, Many thanks for your quick response!

Your solution to this problem works:

assert( Amnesia.transaction! do 
   assert Enum.map(Koersen.stream |> Amnesia.Table.Stream.reverse, fn(koers) -> koers.dag end) 
          ==  [9,8,7,6,5,4,3,2,1]
  end == true)

Thiel

2 Likes