The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

439748 (2) [Avatar] Offline
#1
Hi,

This is my solution for the practice exercise 3.4.5

def large_lines!(path) do
File.stream!(path)
|> Stream.map(&String.replace(&1,"\n",""))
|> Enum.map(&String.length(&1))
end

And the result is: 'n\nn'

I checked the solution and it has the same result.

if I added a couple of lines to the text file and I get the expected result with my code and the solution code: [110, 10, 110, 1, 2, 3].

Is this the default behavior or do I need to do something else to get always a list?

Thanks,
sjuric (109) [Avatar] Offline
#2
I assume you expect the result [110, 10, 110]. The thing is that you in fact do get that result. However, a list of integers will be displayed as the character string (aka Erlang string) if all of its elements are ASCII codes representing printable characters. This is briefly mentioned in the book at the end of page 46 (PDF page 71).

You can easily verify this in iex:

iex(1)> [110, 10, 110]
'n\nn'


And you can also check that both values are the same thing:

iex(2)> [110, 10, 110] == 'n\nn'
true


If there is a non-printable character in the list, then a list of integer is displayed. This is the reason why you see integers if you add a couple of short lines, since 1, 2, and 3 don't correspond to printable characters.

If you're using inspect or IO.inspect to display your results, you can explicitly disable this conversion:

iex(1)> IO.inspect([110, 10, 110], charlists: :as_lists)
[110, 10, 110]
'n\nn'


In the snippet above, [110, 10, 110] is the output printed by IO.inspect, while 'n\nn' is the result of the function, which is still converted by the shell into a charlist.

You can also prevent iex from converting expression results into a charlist using IEx.configure:

iex(1)> IEx.configure(inspect: [charlists: :as_lists])
:ok

iex(2)> [110, 10, 110]
[110, 10, 110]


However, in this case Erlang strings are also going to be printed as list of integers:

iex(3)> 'a character list'
[97, 32, 99, 104, 97, 114, 97, 99, 116, 101, 114, 32, 108, 105, 115, 116]

439748 (2) [Avatar] Offline
#3
Thanks for the answer, it was really helpful.

100% recommended book.

I thought that I could have issues looping through it, but no, it is just the representation as you mentioned on your answer.

Streams.large_lines!("test1.txt") |> Enum.each(&IO.puts(&1) )
110
10
110
:ok

Thanks again.