简体   繁体   中英

What is this Elixir message means

I am writing Elixir to get record from remote nodes, I have write a module,

   defmodule Connect do
      def connect do
      node_ap_dev_ejd = :'abc@abc.com'
      :net_adm.ping(node_ap)

      fbUsersFun = fn(x) -> :binary.part(x,{0,3}) == <<"*ab">> end
      f = fn()-> :mnesia.dirty_select(:'cz_map',[{{:cz_map, :'$1', :'_',:'_',:'_'},[],[:'$1']}]) end

      fbUserList = :rpc.call(node_ap_dev_ejd,:mnesia,:activity,[:async_dirty,f])
      list = Enum.filter(fbUserList ,fbUsersFun)
      length(list)
      end
   end    

I can run the code if I put it in iex shell line by line, however if I compile the code and run Connect.connect , this error appear, I have no idea of it, please suggest

** (Protocol.UndefinedError) protocol Enumerable not implemented for 
{:badrpc, {:EXIT, {:undef, [{#Function<1.96315226/0 in Connect.connect/0>, [], []}, {:mnesia_tm, :non_transaction, 5, [file: 'mnesia_tm.erl', line: 738]}]}}}
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:112: Enumerable.reduce/3
(elixir) lib/enum.ex:666: Enum.filter/2
         second_function.ex:10: Connect.connect/0

It means that the Enumerable protocol is not implemented for the data {:badrpc, ...} .

Most likely, that error comes from this line:

list = Enum.filter(fbUserList ,fbUsersFun)

In that line, you're trying to filter fbUserList which I guess is {:badrpc, ...} instead of an enumerable. Tuples are not enumerables; lists and maps (and other things) are.

The solution probably lies in a case expression which checks the result returned by :rpc.call/4 in order to defend from errors:

case :rpc.call(node_ap_dev_ejd, :mnesia, :activity, [:async_dirty, f]) do
  {:badrpc, _} -> raise "bad rpc error"
  fbUserList   -> Enum.filter(fbUserList, ...) # and so on
end

I'm having the same issue working mnesia with erlang, the error is because of the anonymous function "f", the thing is that the remote node does not recognize that function because it was created in another node.

EDIT:

I managed to solve the problem in erlang, I will show you how I did it in erlang, I don't know much about elixir but I´m sure if it can be done in erlang it will in elixir.

So this segment

 f = fn()-> :mnesia.dirty_select(:'cz_map',[{{:cz_map, :'$1', :'_',:'_',:'_'},[],[:'$1']}]) end

  fbUserList = :rpc.call(node_ap_dev_ejd,:mnesia,:activity,[:async_dirty,f])

In erlang is like this

f = fun()-> mnesia:dirty_select(cz_map,[{{cz_map, '$1', '_', '_', '_'},[],['$1']}]) end,
fbUserList = rpc:call(node_ap_dev_ejd, mnesia, activity, [async_dirty, f])

Instead declaring an anonymous fun you have to do something like this

fbUserList = rpc:call(node_ap_dev_ejd, mnesia, activity, [async_dirty, mnesia:dirty_select/2, [cz_map, [{{cz_map, '$1', '_', '_', '_'},[],['$1']}]]])

You can find a clear explanation here what kind of types can be sent on an erlang message?

I hope this information helps you.

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