2
votes

So I'm trying to learn Elixir (I have a background o F# and Haskell) and I'm having difficulties understanging what is going on in my code:

fizz_buzz = fn
  (0, 0, _) -> "FizzBuzz"
  (0, _, _) -> "Fizz"
  (_, 0, _) -> "Buzz"
  (_, _, c) -> c
end

fizz_buzz_rem = fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end


# This works
IO.puts(fizz_buzz_rem.(10))
IO.puts(fizz_buzz_rem.(11))
IO.puts(fizz_buzz_rem.(12))
IO.puts(fizz_buzz_rem.(13))
IO.puts(fizz_buzz_rem.(14))
IO.puts(fizz_buzz_rem.(15))
IO.puts(fizz_buzz_rem.(16))
IO.puts(fizz_buzz_rem.(17))

IO.puts("----------------")

inputs =
  10..17
  |> Enum.to_list

# Doesn't work
inputs
|> Enum.map(fizz_buzz_rem)
|> IO.puts

IO.puts("----------------")

# Doesn't work
inputs
|> Enum.map(fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end)
|> IO.puts

IO.puts("----------------")

manual_inputs = [10, 11, 12, 13, 14, 15, 16, 17]

# Doesn't work
manual_inputs
|> Enum.map(fizz_buzz_rem)
|> IO.puts

IO.puts("----------------")

# Doesn't work
manual_inputs
|> Enum.map(fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end)
|> IO.puts


IO.puts("----------------")

# The idiotic way (that doesn't work)

result = [
  fizz_buzz_rem.(10),
  fizz_buzz_rem.(11),
  fizz_buzz_rem.(12),
  fizz_buzz_rem.(13),
  fizz_buzz_rem.(14),
  fizz_buzz_rem.(15),
  fizz_buzz_rem.(16),
  fizz_buzz_rem.(17),
]

IO.puts result

# ???????????

When I run elixir ex_02.exs the output is:

Buzz
FizzBuzz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz

So as you can see when I apply the anonymous function to each value individually I get the right answer bu when I try to use ranges, maps and even apply the function to each element of a list manually I end up with the wrong result.

What am I getting wrong about aplying a anonymous function to a list in elixir?

1
try inputs |> Enum.map(fizz_buzz_rem) |> Enum.map(&IO.puts/1)Guru Stron

1 Answers

7
votes

If you use IO.inspect instead of IO.puts, you can see what's going on:

["Buzz", 11, "Fizz", 13, 14, "FizzBuzz", 16, 17]

Your fizzbuzz function returns either a string or an integer, depending on the input. IO.puts treats integers differently depending on whether they're in a list:

iex(1)> IO.puts(65)
65
:ok
iex(2)> IO.puts([65])
A
:ok

So in your code, IO.puts actually prints the control codes corresponding to the integers 11, 13, 14, 16 and 17. In my terminal it shows up as:

Buzz^KFizz^M^NFizzBuzz^P^Q

You can fix this by making your function always return strings:

fizz_buzz = fn
  (0, 0, _) -> "FizzBuzz"
  (0, _, _) -> "Fizz"
  (_, 0, _) -> "Buzz"
  (_, _, c) -> "#{c}"
end