1
votes

I am trying to do a sentiment analysis on a fiction novel by passing each sentence to the analyze function in the external library Sentient. I am repeatedly getting the following error:

(Enum.EmptyError) empty error
(elixir) lib/enum.ex:1590: Enum.reduce/2
(elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
(sentiment) lib/sentiment.ex:23: Sentiment.analyze/1
(sentiment) lib/sentiment.ex:6: Sentiment.run/1
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:168: Code.eval_string/3

To the best of my knowledge, I am not passing an empty string to my function. I have been using a test file that contains the following:

This is a test. This sentence is sad. This sentence is happy. The end.

This is my code:

defmodule Sentiment do

  def run(file) do
    file
    |> fileread
    |> analyze
    |>IO.inspect
  end

  def fileread(file) do
    file
    |> File.stream!
    |> Stream.map(&String.trim_trailing(&1))
    |> Enum.map(&String.replace(&1, ~r/[-@#$%^&*()=_+|;':",<>']/, ""))
    |> Stream.map(&String.split(&1,~r/[\p{P}\p{S}]+/, trim: true))
    |> Enum.to_list
    |> List.flatten
    |> IO.inspect
  end

  def analyze(list) do
    list
    |> Enum.map(&Sentient.analyze(&1))
    |> IO.inspect
  end

end

I put an IO.inspect at the end of my fileread function in order to check if there was an empty entry in the list. There is not, this is the result of my fileread function:

mix run -e 'Sentiment.run("test.txt")'
["This is a test", " This sentence is sad", " This sentence is happy",
 " The end"]

So, I'm really not sure why I'm getting this error. Anyone have any suggestions?

1
Judging by your stack trace it looks like the Enum.EmptyError is raised by Enum.map/2 and not by &Sentient.analyze(&1). Are you 100% positive that list in analyze/1 is the list of arrays you show in your question? - Daniel Zendejas
I would assume so, since I'm just calling the run function, which just pipes a file into the fileread/1 function, then pipes the result of that into analyze/1. - K. Swan
Which version of Elixir are you using? (I'm trying to understand the stacktrace.) - Dogbert
I'm running 1.3.4, thanks! - K. Swan
Can you try calling Sentient.analyze() on each of those 4 sentences manually in iex -S mix? Does any of them raise any error? - Dogbert

1 Answers

2
votes

This is a bug in sentient:

$ mix run -e 'Sentient.analyze("This is a test")'
** (Enum.EmptyError) empty error
    (elixir) lib/enum.ex:1722: Enum.reduce/2
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/code.ex:170: Code.eval_string/3
    (elixir) lib/enum.ex:645: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:645: Enum.each/2
    (mix) lib/mix/tasks/run.ex:78: Mix.Tasks.Run.run/1

It looks like the author fixed this in the Git repo but never released it on hex.pm. With the current git version the above statement does not throw any error.

The bug was that the old version was calling Enum.reduce/2 with an empty list, which is documented to throw that error if the list is empty. They changed that to Enum.reduce/3 with a default accumulator value in the commit linked earlier which handles empty lists just fine.