Elixir의 for 문장을 복습해 보세요.

28752 단어 Elixirtech
이 글은 fukuoka.ex Elixir/Phoenix Advent Calendar 2020 9일째다.
전날, @the_haigo씨의 "Phoenix LiveView로 제작된 웹/mobile 채팅 앱 실시간 처리편"!

메시지


Elixir에서 Enum 모듈을 사용한 목록 처리는 철판이었으나 OSS의 코드를 읽은 결과 의외로 for문(내장 표기)으로 목록 처리를 쓰는 패턴이 흔하다는 것을 발견했다.
예를 들면 이쪽.플러그인 목록의 Reduce 처리를 for 글로 원활하게 작성합니다.
여담: 이것은zen의 스크랩 기능으로 대략적으로 볼 때Dashbit의 OSS의 일지입니다.배울 코드가 많기 때문에 꼭 배워야 합니다.
https://zenn.dev/koga1020/scraps/823045b9494296#comment-a8e102bd4ca19c
이렇게 하면 사용하는 곳에 따라 for문도 있다.그래서 오늘 보도에서 나는 공식 문서에 따라 for문의 기술을 다시 정리하고 싶다.
https://hexdocs.pm/elixir/Kernel.SpecialForms.html#for/1

릴리즈


$ elixir -v
Erlang/OTP 21 [erts-10.3.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Elixir 1.11.2 (compiled with Erlang/OTP 21)

개시하다


Elixir의 for 반환 값입니다.만약등도 마찬가지다.따라서 for에서push부터 목록에 이르기까지 이러한 쓰기 방법은 기본적으로 없다. 주로 목록의 각 요소를 처리하거나 목록에서 지도에 모인다.
for와 if 반환값은 Elixir에 처음 들어간 곳입니다. 신중하게 보기 위해서 기록해 주십시오.
iex> arr = for n <- [1, 2, 3, 4], do: n * 2
[2, 4, 6, 8]
# arr に値が入っている
iex> arr
[2, 4, 6, 8]

재생 목록 요소 반복


가장 간단한 예네요.n <- [1, 2, 3, 4]의 부분을generator라고 부른다.
iex> for n <- [1, 2, 3, 4], do: n * 2
[2, 4, 6, 8]
네스트도 가능합니다.
iex> for x <- [1, 2], y <- [2, 3], do: x * y
[2, 3, 4, 6]

조건부 필터

rem/2는 여수를 구하는 함수다.다음 예에서는 충족rem(n, 2) == 0의 짝수만 처리됩니다.
iex> for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n
[2, 4, 6]
엔음으로 쓰면 이런 느낌이죠.for가 더 깔끔합니다.
# Enumで書くとこんな感じ
iex> [1, 2, 3, 4, 5, 6] |> Enum.filter(fn n -> rem(n, 2) == 0 end) |> Enum.map(fn n -> n end)

# &で書いてもこれぐらい
iex> [1, 2, 3, 4, 5, 6] |> Enum.filter(&(rem(&1, 2) == 0)) |> Enum.map(&(&1))
두 언어의 문법과 함께generator를 기술해도 Filter를 나타낼 수 있다.
iex> users = [user: "john", admin: "meg", guest: "barbara"]
iex> for {type, name} when type != :guest <- users do
...>   String.upcase(name)
...> end
["JOHN", "MEG"]
간단한 예가 바로 이런 느낌이다.
iex> for x when is_atom(x) <- [1, "hoge", :hoge], do: x
[:hoge]

bitstring 처리


generator에서bitstring을 사용할 수도 있습니다.
iex> pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
<<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>
iex> for <<r::8, g::8, b::8 <- pixels>>, do: {r, g, b}
[{213, 45, 132}, {64, 76, 32}, {76, 0, 0}, {234, 32, 15}]

옵션


몇 가지 편리한 옵션이 있는데 제가 소개해 드릴게요.

:into

Enum.into/2 옵션을 사용하여 적절한 처리를 지정할 수 있습니다.
iex> for n <- ["1", "2", "3"], into: "", do: n
"123"
iex> Enum.into(["1", "2", "3"], "")
"123"
iex> for {key, value} <- [key1: :value1, key2: :value2], into: %{}, do: {key, value}
%{key1: :value1, key2: :value2}
iex> Enum.into([key1: :value1, key2: :value2], %{})
%{key1: :value1, key2: :value2}

:uniq

:into 옵션을 사용하여 중복을 제거할 수 있습니다.
iex> for x <- [1, 1, 2, 3], uniq: true, do: x * 2
[2, 4, 6]

:reduce

:uniq 옵션을 사용하여 목록 처리 결과를 요약할 수 있습니다.
iex> for n <- [1, 2, 3, 4], reduce: 0 do
...>   acc -> acc + n
...> end
10
물론 Filter도 함께 사용할 수 있습니다.
iex> for n <- [1, 2, 3, 4], rem(n, 2) == 0, reduce: 0 do
...>   acc -> acc + n
...> end
6
hexdocs의 예는 매우 재미있다.좀 귀찮아서 썼어요.
# charlistとしてloop
iex> for <<x <- "AbCabCABc">>, do: x
'AbCabCABc'
# in句で小文字のa~zのみ抽出(filtering)
iex> for <<x <- "AbCabCABc">>, x in ?a..?z, do: x
'babc'
# reduceを追加して頻度をカウントする処理を記述
iex> for <<x <- "AbCabCABc">>, x in ?a..?z, reduce: %{} do
...>   acc -> Map.update(acc, <<x>>, 1, & &1 + 1)
...> end
%{"a" => 1, "b" => 2, "c" => 1}

총결산


공식 문서에 따라 :reduce의 사용 방법을 정리했다.잘 사용하면 기술을 줄일 수 있는 시기가 있을 것 같아요.특히 이중 언어 중 Filterfor가 사용하는 장면이 많다.
내일 열흘째는 @tuchiro입니다!기대해주세요!

좋은 웹페이지 즐겨찾기