Read File, Flow, Stream, Write gives Protocol.UndefinedError

Hi Experts,

Using online examples and some modifications, I am trying to run the following code:

File.stream!("data-source.json")
    |> Flow.from_enumerable()
    |> Flow.flat_map(&String.split(&1, " "))
    |> Flow.partition()
    |> Flow.reduce(fn -> %{} end, fn word, acc ->
      Map.update(acc, word, 1, & &1 + 1)
    end)
    |> Stream.into(File.stream!("output.txt", [:write, :utf8]))
    |> Stream.run

and it gives me the wollowing error:

** (Protocol.UndefinedError) protocol String.Chars not implemented for {"\"http://site.co/track?c=2597&csurl=http://site.co/profile/name\",\n", 1}. This protocol is implemented for: Atom, BitString, Date, DateTime, Float, Integer, List, NaiveDateTime, Time, URI, Version, Version.Requirement
    (elixir) lib/string/chars.ex:3: String.Chars.impl_for!/1
    (elixir) lib/string/chars.ex:22: String.Chars.to_string/1
    (elixir) lib/io.ex:553: IO.write/2
    (elixir) lib/stream.ex:511: anonymous fn/5 in Stream.do_into/5
    (elixir) lib/enum.ex:3251: Enumerable.List.reduce/3
    (elixir) lib/stream.ex:1391: Stream.do_list_resource/6
    (elixir) lib/stream.ex:521: Stream.do_into/4
    (elixir) lib/stream.ex:624: Stream.run/1 

Can someone advise where to dig to sort it out ?

After the

Flow.reduce(fn -> %{} end, fn word, acc ->
  Map.update(acc, word, 1, & &1 + 1)
end)

step you will return a map which, when enumerated with Stream.into/2, will operate on a tuple {key, value}. Your exception message shows that tuple to be {"\"http://site.co/track?c=2597&csurl=http://site.co/profile/name\",\n", 1}.

The tuple cannot be converted to a string with the String.Chars protocol which would be required in order to stream it to the output file.

So a solution would be to decide how to transform the tuple to a string. Since the tuple looks a little weird (embedded double quotes in a string) I suspect you’re trying to invent a streaming json sort of parsing thing and its not quite returning what you want yet.

4 Likes

Hi kip,

Yes, you are right, thank you for the direction !