Эликсир: предупреждение о компиляции "результат выражения игнорируется" - PullRequest
0 голосов
/ 27 мая 2018

Я реализую crash функцию в GenServer, чтобы проверить поведение супервизора и реестра, которые будут управлять этим процессом.Работа выполняется в Elixir, но я полагаю, что это также может касаться Эрланга.

Я мог бы назвать raise(), но сначала я применил 1/0 в качестве причины сбоя.Компилятор, будучи умным парнем, для следующего кода:

def handle_cast(:crash, state) do
  a = 1 / 0
  {:noreply, state}    
end

Я получил предупреждение:

warning: this expression will fail with ArithmeticError
  lib/xyz/worker.ex:47

Справедливо.В конце концов, даже старые компиляторы C или C ++ могли обнаруживать подобные вещи.Я попробовал библиотечный вызов, заменив a = 1 / 0 на a = 1 / :math.sin(0).То же предупреждение.Мое любопытство проснулось, и я попробовал разные вещи с одинаковым результатом.На самом деле, похоже, что это не так легко обмануть компилятор!В конце концов, я добавил:

a = 1 / Enum.reduce([0, 1, -1], 0, fn(n, acc) -> n+acc end)

и получил другое предупреждение:

warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable)
  lib/xyz/worker.ex:50

строка 50: a = 1 / Enum.reduce(...).

Я потратил пару часов, пытаясь по-другомувещи с всегда получать либо предупреждение.

Я полагаю, что первое поднято, потому что компилятор может предварительно вычислить результат из константных аргументов, типа функции и встроенной в конечном итоге операции 1 / 0.

Все же я не понимаю второе предупреждение.В одном из тестов я написал:

def handle_cast(:crash, state) do
  a = 1 / Enum.reduce([0, 1, -1], 0, fn(n, acc) -> n+acc end)
  # {:noreply, state}    
end

, который фактически подавляет предупреждение, но я действительно не понимаю, почему.

NB.1 : версии:

maurice@mickey> elixir -v
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.6.1 (compiled with OTP 19)

NB.2 : Мне известен этот вопрос , но я не думаю, что ответ здесь применим.

Пока я буду звонить raise(...) ...

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Короткая версия

Предупреждение фактически говорит вам, что делать: замените a = ... на _ = ....

Длинная версия

В ваших примерах выприсвойте результат операции переменной a.Компиляция замечает, что вы никогда больше не используете эту переменную, поэтому жалуется на это.

Elixir знает «специальную» переменную для этого случая, которая называется _.При выполнении _ = ... или def my_function(_, second_paramter) вы в основном указываете компилятору:

Я не хочу использовать это значение, поэтому, пожалуйста, не жалуйтесь

Дляпредоставляя больше информации о игнорируемом значении, вы также можете поставить префикс переменной с подчеркиванием (_), которая служит той же цели.В вашем случае это может быть _a = ....

Это в основном полезно при игнорировании аргументов в функции, не позволяя читателю угадать, о чем этот аргумент.Так что def get(:thing, _) может стать def get(:thing, _opts).


Затем вы спросили, почему закомментированная версия не выдает такую ​​ошибку.Ответ заключается в том, что возвращаемое значение функции равно последнему утверждению этой функции.

Таким образом, эта функция

def my_function do
  1
  2
  3
end

возвращает 3, а эта функция

def my_function do
  :a
  :b
end

возвращает :b.Таким образом, в вашем примере

def handle_cast(:crash, state) do
  a = 1 / Enum.reduce([0, 1, -1], 0, fn(n, acc) -> n+acc end)
  # {:noreply, state}    
end

Вы закомментировали кортеж # {:noreply, state}, и оператор a = ... станет последним в функции.Поскольку теперь вы создаете переменную a и оцениваете ее как часть "return", компилятор перестает жаловаться.

С другой стороны, вполне может быть справедливо, что присвоение переменной в последней строкефункции бесполезны.Так что это может на самом деле оправдать проблему с низким приоритетом на GitHub .

0 голосов
/ 27 мая 2018

Обмани компилятор до конца, переназначьте state переменную:

def handle_cast(:crash, state) do
  state = Enum.reduce([0, 1, -1], 0, fn(n, acc) ->
    n + acc
  end)
  {:noreply, state}    
end

Таким образом, компилятор будет думать, что state присваивание необходимо (так как он используется в качестве возвращаемого значения.)

...