less than 1 minute read

build_list 라는 함수를 짜고 있다. 요소(element)를 원하는 개수만큼 생성하게 하고 싶다.

def build_list(count, elem_func) do
  for _ <- 1..count do
    elem_func.()
  end
end

Range를 사용해서 [1, 2, ... count] 를 만들고 elem_func 함수를 호출해서 리스트를 만들 수 있다. 하지만 0개를 만들려면 문제가 된다.

1..0 |> Enum.to_list()
[1, 0]

count 가 0이면 Range에서 인자로 넘기지 않으면 자동으로 계산해 주는 step이 -1 이 되면서 1과 0에 대해 만들 게 된다. 결과 리스트 사이즈가 0이 되길 원했는데, 2가 된다.

그렇다면 count 에 대해 분기를 타볼까?

def build_list(count, elem_func) do
  if count > 0 do
    for _ <- 1..count do
      elem_func.()
    end
  else
    []
  end
end

원하는 대로 동작하지만 뭔가 더 나은 방법이 반드시 있을 것 같은 구현이다.

그렇다. Stream.repeatedly를 사용하면 된다.

def build_list(count, elem_func) do
  Stream.repeatedly(fn -> elem_func.() end)
  |> Enum.take(count)
end

무한히 생성하는 Stream을 만들고 count만큼 가져온다. Enum.take/2 함수는 두 번째 인자로 0을 넘기면 빈 문자열을 리턴한다. 원하던 함수 구현이다. ExMachina.build_list/4 소스 코드에서 배웠다.