Reputation: 2460
I'd appreciate some help with this, it's the first thing I'm trying to do with Elixir and it's throwing me off.
So my intent is to capture from STDIN over and over, parsing the user input as numbers. When the user finally hits enter without entering a number, they get a sum of all numbers entered so far. Simple.
So here's how I plan it:
defmodule Solution do
def main, do: scan(IO.read :line)
def scan(line), do: scan(IO.read :line, Integer.parse line)
def scan("\n", total), do: IO.puts(total)
def scan(line, {total, _}) do
final_total = Integer.parse(line) + Integer.parse(total)
next_line = IO.read :line
scan(next_line, final_total)
end
end
Solution.main
Going line by line:
def main, do: scan(IO.read :line)
To start with, call scan
passing in one line from stdin.
def scan(line), do: scan(IO.read :line, Integer.parse line)
If we get a scan
call with a single argument, parse that argument as an integer, and pass it plus the next stdin line to scan/2
.
def scan("\n", total), do: IO.puts(total)
If we get a scan/2
call where the stdin line was blank, just output the second argument, the integer total
.
and then finally
def scan(line, {total, _}) do
final_total = Integer.parse(line) + Integer.parse(total)
next_line = IO.read :line
scan(next_line, final_total)
end
We get a line from stdin, and a tuple of an integer total and some garbage. The current total is that line (parsed as int) plus the previous total. We call scan/2
again with a new line from stdin and our latest total.
All the logic seems to hold to me. But I get (FunctionClauseError) no function clause matching in IO.read/2
. Elixir's error messages aren't super descriptive, so I'm having trouble working this out. What exactly am I doing wrong?
Upvotes: 2
Views: 85
Reputation: 222398
The biggest hint here is the 2
in (FunctionClauseError) no function clause matching in IO.read/2
. You're calling the 2 arity version of IO.read
instead of 1 (with the arguments :line
and Integer.parse line
), which you most likely intended. This is because you're missing a pair of parenthesis around the arguments for IO.read
in the 3rd line:
def scan(line), do: scan(IO.read :line, Integer.parse line)
That should be:
def scan(line), do: scan(IO.read(:line), Integer.parse line)
It's also considered more idiomatic to have parenthesis around all function calls (at least those with arguments) when you're nesting them:
def scan(line), do: scan(IO.read(:line), Integer.parse(line))
The error here is a bit less obvious than it could have been (like failing to compile) since both Solution.scan
and IO.read
have 1 and 2 arity versions.
Upvotes: 3