Нет функционального предложения, хотя кажется, что оно определенно есть?

Я был бы признателен за помощь в этом, это первое, что я пытаюсь сделать с Эликсиром, и это сбивает меня с толку.

Итак, я намерен снова и снова считывать из STDIN, анализируя пользовательский ввод как числа. Когда пользователь, наконец, нажимает Enter, не вводя число, он получает сумму всех введенных чисел. Простой.

Итак, вот как я это планирую:

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

Идем построчно:

def main, do: scan(IO.read :line)

Для начала вызовите scan, передав одну строку из стандартного ввода.

def scan(line), do: scan(IO.read :line, Integer.parse line)

Если мы получаем вызов scan с одним аргументом, анализируем этот аргумент как целое число и передаем его плюс следующую строку стандартного ввода в scan/2.

def scan("\n", total), do: IO.puts(total)

Если мы получим вызов scan/2, в котором строка стандартного ввода была пустой, просто выведите второй аргумент, целое число 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

Получаем строку из stdin, и кортеж целой суммы и какой-то мусор. Текущая сумма — это эта строка (обработанная как int) плюс предыдущая сумма. Мы снова вызываем scan/2 с новой строкой из стандартного ввода и нашей последней суммой.

Вся логика кажется мне верной. Но я получаю (FunctionClauseError) no function clause matching in IO.read/2. Сообщения об ошибках Эликсира не очень информативны, поэтому у меня возникли проблемы с этим. Что именно я делаю неправильно?


person GreenTriangle    schedule 20.11.2016    source источник


Ответы (1)


Самая большая подсказка здесь — 2 в (FunctionClauseError) no function clause matching in IO.read/2. Вы вызываете версию IO.read с арностью 2 вместо 1 (с аргументами :line и Integer.parse line), что вы, скорее всего, и предполагали. Это потому, что вам не хватает пары скобок вокруг аргументов для IO.read в 3-й строке:

def scan(line), do: scan(IO.read :line, Integer.parse line)

Которые должны быть:

def scan(line), do: scan(IO.read(:line), Integer.parse line)

Также считается более идиоматичным заключать в скобки все вызовы функций (по крайней мере, с аргументами), когда вы их вкладываете:

def scan(line), do: scan(IO.read(:line), Integer.parse(line))

Ошибка здесь немного менее очевидна, чем могла бы быть (например, сбой при компиляции), поскольку и Solution.scan, и IO.read имеют версии с арностью 1 и 2.

person Dogbert    schedule 20.11.2016
comment
О, черт, я полностью пропустил это, и это имеет смысл. Спасибо за это @Dogbert, ценю это. - person GreenTriangle; 20.11.2016