Hi,
I am learning Elixir through self-study. At the moment I am working through Elixir in Action chapter 3 stream exercises. I have a couple of questions I hope someone can answer:
I am trying to iterate through each line of a file and produce a list of numbers each representing a number of chars in that line. Easy enough.
I wrote the following function:
def lines_lengths!(path) do
path
|> File.stream!()
|> Stream.map(&String.replace(&1, “\n”, “”))
|> Enum.map(&String.length/1)
end
This fails my doctest with the following message:
- doctest Exercises.lines_lengths!/1 (1) (ExercisesTest)
test/exercises_test.exs:3
Doctest failed
doctest:
iex> Exercises.lines_lengths!("/Users/nixlim/Sync/PROJECTS/elixir_learning/elixir_in_action/exercises/sample_text.txt")
[125, 108, 104, 110]
code: Exercises.lines_lengths!(
“/Users/nixlim/Sync/PROJECTS/elixir_learning/elixir_in_action/exercises/sample_text.txt”
) === [125, 108, 104, 110]
left: ‘|lgn’
right: ‘}lhn’
stacktrace:
lib/exercises.ex:77: Exercises (module)
…
This is the function from the author’s solution:
defp filtered_lines!(path) do
path
|> File.stream!()
|> Stream.map(&String.replace(&1, “\n”, “”))
end
def lines_lengths!(path) do
path
|> filtered_lines!()
|> Enum.map(&String.length/1)
end
This works as intended.
So, my questions are:
-
Why does the original function produce this weird output:
left: ‘|lgn’
right: ‘}lhn’ -
What am I misunderstanding here - ie why is the
filtered_lines
function required? My thinking is that all that does (apart from the logic of removing line breaks) is output a stream which is then passed to the Enum.map function. So, why does that not work if I put it into single function?