JavaScriptを有効にしてください

【Elixir】ループの癖が強かった

 ·  ☕ 2 分で読めます

【Elixir】ループの癖が強いかった

Elixir 初心者の僕がループを使用してハマったことをメモしておきます

ハマったこと

Elixer で勉強用にコードを書いていて「渡された数値の回数 1~X までループして 1~X までの合計を出す」という単純な問題をやっていたのですが、これがハマった。

PHPでやろうとするとこんな感じのコードになるものですね

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php

function sum_number($num) {
    $sum = 0;
    for($i = 1; $i <= $num; $i++){
        $sum += $i;
    }
    return $sum;
}

# 1+2+3 = 6
echo sum_number(3);

Elixirで以下のようなコードを最初に書きました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
defmodule MyModule do
  def sum_number(n) do
    sum = 0

    for i <- 1..n do
      sum = sum + i
    end

    sum
  end
end

IO.puts MyModule.sum_number(3)

そしてこんなエラーが出ました。

warning: variable "sum" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
  Main.exs:6: MyModule.sum_number/1

sum 使ってない→使ってる!

warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable)
  Main.exs:6

sum 使ってないから _ 付けてね→使ってる!

エラー原因

エラーがの原因についてですがElixirはループ内の副作用をループ外に対して行わないようにしているようです。
そのためループ内でいくら変数を変えてもループ外に出たら反映されません。
Elixir - loop

対応

この場合は再帰を使って対応します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
defmodule MyModule do
 # 値 0 の場合 0を返す
  def sum_number(0), do: 0
  def sum_number(x) do
    x + sum_number(x-1)
  end
end

# 1+2+3 = 6
IO.puts MyModule.sum_number(3)

他言語とのループの差で最初つまづきそうな気がします。

補足

一応再帰やループを使わずにこんなふうにもできる模様です。

1
2
3
4
5
6
7
8
defmodule MyModule do
  def sum_number(x) do
    Enum.sum(1..x)
  end
end

# 1+2+3 = 6
IO.puts MyModule.sum_number(3)

参考

共有

こぴぺたん
著者
こぴぺたん
Copy & Paste Engineer