Elixir 간단명료 노트 (15) - 제어 구조의 패턴 일치
Elixir
이러한 구조의 키 워드 를 직접 제공 하지 않 고 모델 매 칭, 매 거 진 교체, 재 귀 를 통 해 절차 통 제 를 실현 하 는 것 이다.패턴 매 칭
앞에서 간단 한 패턴 매 칭 을 소개 했다. 특히 서로 다른 데이터 구 조 를 소개 할 때 도 이 모듈 에 대해 패턴 매 칭 방식 을 제공한다.이 편 은 패턴 매 칭 에 관 한 토론 으로 패턴 매 칭 의 총화 와 같다.
기본 정의
패턴 일치 란 일치 문자
=
를 사용 하여 왼쪽 과 오른쪽 변 수 를 연결 하 는 것 입 니 다.왼쪽 표현 식 이나 변 수 는 패턴 (pattern) 이 라 고 부 르 고 오른쪽 표현 식 은 값 을 구 합 니 다.그 다음 에 오른쪽 에서 값 을 구 하 는 결 과 를 왼쪽 모드 와 일치 시 키 고 일치 하면 해당 하 는 변 수 를 연결 합 니 다.패턴 이 일치 하 는 표현 식 은 오른쪽 표현 식 의 값 을 구 하 는 결 과 를 되 돌려 줍 니 다.Tuple 매 칭
모드 는 변수 일 수도 있 고 원 그룹 일 수도 있 습 니 다.elixir 의 모든 표현 식 은 값 을 되 돌려 줍 니 다. 패턴 이 일치 하면 일치 하 는 오른쪽 값 을 되 돌려 줍 니 다.
iex(1)> person = {"Bob", 25} # , ,
{"Bob", 25}
iex(2)> {name, age} = {"Bob", 25}
{"Bob", 25}
iex(3)> name # name
"Bob"
iex(4)> age # age
25
Elixir 에 서 는 함수 가 되 돌아 오 는 여러 값 을 tuple 에 넣 고 tuple 의 pattern match 를 자주 사용 합 니 다.또한 끼 워 넣 을 수 있 습 니 다:
iex(1)> {date, time} = :calendar.local_time
{{2016, 4, 7}, {20, 49, 11}}
iex(2)> {year, month, day} = date
{2016, 4, 7}
iex(3)> year
2016
iex(4)> {{year, month, day}, {hour, minutes, second}} = :calendar.local_time
{{2016, 4, 7}, {20, 58, 3}}
iex(5)> year
2016
iex(6)> hour
20
iex(7)> {{year, month, day}, {hour, minutes, second}} = {date, time} = :calendar.local_time
{{2016, 4, 7}, {20, 59, 7}}
iex(8)> month
4
iex(9)> date
{2016, 4, 7}
마지막 표현 식 은 끼 워 넣 기 일치 입 니 다. 즉, 맨 오른쪽 에서 패턴 을 일치 시 킨 다음 에 맨 오른쪽 표현 식 의 값 을 패턴 과 일치 시 키 는 성공 적 인 결과 (: calendar. local time) 를 되 돌려 준 다음 에 이 결 과 는 왼쪽 {year, month, day}, {hour, minutes, second} 과 계속 패턴 을 일치 시 킵 니 다.
고정 정합
비록 elixir 의 데 이 터 는 변 하지 않 지만 변 수 는 다시 연결 할 수 있 습 니 다.변 수 를 다시 연결 할 필요 가 없 을 때 도 있 습 니 다. 이 때 는 pin 연산 자 (^) 를 사용 하여 고정 적 으로 일치 할 수 있 습 니 다.
iex(10)> expected_name = "Bob"
"Bob"
iex(11)> {^expected_name, _} = {"Bob", 25} # expected_name
{"Bob", 25}
iex(12)> {^expected_name, _} = {"Alice", 30}
** (MatchError) no match of right hand side value: {"Alice", 30}
목록 일치
일치 하 는 목록 과 일치 하 는 원 그룹의 차 이 는 그리 크 지 않 습 니 다.목록 작업 head 와 tail 의 특수성 으로 인해
|
을 사용 하여 목록 과 일치 할 수 있 습 니 다. 바 인 딩 되 지 않 으 려 는 변 수 를 만나면 _
를 사용 하여 모든 모드 와 일치 할 수 있 고 바 인 딩 되 지 않 음 을 표시 합 니 다.iex(15)> [1, second, third] = [1, 2, 3]
[1, 2, 3]
iex(16)> second
2
iex(17)> [head|tail] = [1, 2, 3]
[1, 2, 3]
iex(18)> head
1
iex(19)> [1|tail] = [1, 2, 3]
[1, 2, 3]
iex(20)> tail
[2, 3]
일치 하 는 것 은 매우 유연 합 니 다. 같은 변 수 는 여러 번 일치 할 수 있 지만 여러 변수 와 일치 할 수 없습니다.
iex(21)> [first, first, first] = [1, 1, 1]
[1, 1, 1]
iex(22)> first
1
iex(23)> [^first, second, _] = [1, 2, 3]
[1, 2, 3]
iex(24)> first
1
iex(25)> second
2
iex(26)> [first|first] = [1, 1]
** (MatchError) no match of right hand side value: [1, 1]
iex(26)> [first, first] = [1, 2]
** (MatchError) no match of right hand side value: [1, 2]
맵 매 칭
맵 의 일치 와 목록 은 원본 그룹 과 다 릅 니 다. list 와 tuple 은 일치 하 는 요 소 를 모두 써 야 합 니 다. list 의
|
도 마찬가지 입 니 다.맵 은 일부 모드 만 일치 할 수 있 으 며, 일치 하지 않 으 면 오류 가 발생 합 니 다:iex(26)> %{age: age} = %{name: "Bob", age: 25}
%{age: 25, name: "Bob"}
iex(27)> age
25
iex(28)> name
** (RuntimeError) undefined function: name/0
iex(28)> %{age: age, work_at: work_at} = %{name: "Bob", age: 25}
** (MatchError) no match of right hand side value: %{age: 25, name: "Bob"}
함수 매 칭
함수 의 매개 변 수 는 패턴 매 칭 을 할 수 있 습 니 다.같은 함수 이름, 서로 다른 매개 변수 모드 는 서로 다른 매개 변수 와 일치 할 수 있 습 니 다. 다 중 함수 논 리 를 실행 하고 일치 하지 않 으 면 이상 을 던 집 니 다.
iex(1)> defmodule Geometry do
...(1)> def area({:rectangle, a, b}) do
...(1)> a * b
...(1)> end
...(1)>
...(1)> def area({:square, a}) do
...(1)> a * a
...(1)> end
...(1)>
...(1)> def area({:circle, r}) do
...(1)> r * r * 3.14
...(1)> end
...(1)> end
{:module, Geometry,
<<70, 79, 82, 49, 0, 0, 5, 124, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 117, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
{:area, 1}}
iex(2)> Geometry.area({:rectangle, 4, 5})
20
iex(3)> Geometry.area({:square, 5})
25
iex(4)> Geometry.area({:circle, 4})
50.24
iex(5)> Geometry.area({:triangle, 1, 2, 3})
** (FunctionClauseError) no function clause matching in Geometry.area/1
iex:2: Geometry.area({:triangle, 1, 2, 3})
오류 가 발생 하지 않도록 오 류 를 처리 하 는 일치 함 수 를 쓸 수 있 습 니 다. 만능 으로 handler 오 류 를 일치 시 킬 수 있 습 니 다.모듈 에 넣 을 수 없 는 첫 번 째 함 수 를 정의 합 니 다. 함 수 는 순서대로 위 에서 아래로 순서대로 일치 하기 때문에 첫 번 째 에 쓰 면 뒤의 논리 함수 와 일치 하지 않 습 니 다.
iex(1)> defmodule Geometry do
...(1)> def area({:rectangle, a, b}) do
...(1)> a * b
...(1)> end
...(1)>
...(1)> def area({:square, a}) do
...(1)> a * a
...(1)> end
...(1)>
...(1)> def area({:circle, r}) do
...(1)> r * r * 3.14
...(1)> end
...(1)> def area(unknow) do
...(1)> {:error, {:unknow_shape, unknow}}
...(1)> end
...(1)> end
...(2)>Geometry.area({:triangle, 1, 2, 3})
{:error, {:unknown_shape, {:triangle, 1, 2, 3}}}
익명 함수 에서 우 리 는
&
를 사용 하여 함 수 를 인용 합 니 다. 함수 도 이러한 문법 사탕 을 써 서 일치 할 수 있 습 니 다.iex(5)> fun = &Geometry.area/1
&Geometry.area/1
iex(6)> fun.({:circle, 4})
50.24
iex(7)> fun.({:square, 5})
25
Guards 위 자구
매개 변수 가 패턴 매 칭 을 하 는 것 을 제외 하고 함수 가 guards 문 구 를 제공 할 수 있 습 니 다.guard 문 구 를 통 해 매개 변 수 를 걸 러 냅 니 다.
iex(8)> defmodule TestNum do
...(8)> def test(x) when x < 0 do
...(8)> :negative
...(8)> end
...(8)>
...(8)> def test(0) , do: :zero
...(8)>
...(8)> def test(x) when x > 0 do
...(8)>
...(8)> :positive
...(8)> end
...(8)>
...(8)> end
{:module, TestNum,
<<70, 79, 82, 49, 0, 0, 4, 184, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 111, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
{:test, 1}}
iex(9)> TestNum.test(-1)
:negative
iex(10)> TestNum.test(0)
:zero
iex(11)> TestNum.test(1)
:positive
iex(12)> TestNum.test(:not_a_number)
:positive
마지막 일치 도 값 을 되 돌려 줍 니 다.Elixir 에서 데이터 형식 은 모두 비교 문자
>
와 <
를 통 해 조작 할 수 있 는데 그 우선 순 위 는 다음 과 같다.number < atom < reference < fun < port < pid < tuple < map < list < bitstring (binary)
비 숫자 를 걸 러 내기 위해 서 는 guards 를 다음 과 같이 수정 할 수 있 습 니 다.
iex(15)> defmodule TestNum do
...(15)> def test(x) when is_number(x) and x < 0 do
...(15)> :negative
...(15)> end
...(15)> def test(0), do: :zero
...(15)> def test(x) when is_number(x) and x > 0 do
...(15)> :positive
...(15)> end end
iex:15: warning: redefining module TestNum
{:module, TestNum,
<<70, 79, 82, 49, 0, 0, 4, 248, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 111, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
{:test, 1}}
iex(16)> TestNum.test(-1)
:negative
iex(17)> TestNum.test(:not_a_number)
** (FunctionClauseError) no function clause matching in TestNum.test/1
iex:16: TestNum.test(:not_a_number)
guards 문 구 를 쓸 때 주의해 야 합 니 다. 함 수 를 호출 하면 오류 가 발생 할 수 있 습 니 다.그러나 guard 문 구 를 쓴 후에 오 류 는 숨겨 지고 던 지지 않 습 니 다. gurad 문 구 는 false 로 돌아 갑 니 다.예 를 들 어 length / 1 함 수 는 list 에 만 길 이 를 구 합 니 다.
iex(25)> defmodule ListHelper do
...(25)> def smallest(list) when length(list) > 0 do
...(25)> Enum.min(list)
...(25)> end
...(25)> def smallest(_), do: {:error, :invalid_argument}
...(25)> end
iex:25: warning: redefining module ListHelper
{:module, ListHelper,
<<70, 79, 82, 49, 0, 0, 5, 56, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 118, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
{:smallest, 1}}
iex(26)> length [1, 2, 3]
3
iex(27)> length {1, 2, 3} # tuple
** (ArgumentError) argument error
:erlang.length({1, 2, 3})
iex(27)> length 123 #
** (ArgumentError) argument error
:erlang.length(123)
iex(27)> ListHelper.smallest([1, 2, 3])
1
iex(28)> ListHelper.smallest(123) # ,
{:error, :invalid_argument}
iex(29)> ListHelper.smallest({1, 2, 3}) # ,
{:error, :invalid_argument}
iex(30)> ListHelper.smallest(1, 2, 3)
** (UndefinedFunctionError) undefined function: ListHelper.smallest/3
ListHelper.smallest(1, 2, 3)
마지막 예 는 매우 재 미 있 습 니 다. 함수 매개 변 수 는 패턴 매 칭 을 할 수 있 지만 매개 변수 서명 과 같은 함 수 를 말 합 니 다.마지막 예 가 잘못 되 었 고 일치 하 는 오류 가 없습니다. ListHelper. smallest / 1 은 하나의 인 자 를 표시 하고 ListHelper. smallest / 3 은 세 개의 인 자 를 표시 합 니 다.모듈 은 ListHelper. smallest / 1 의 오류 일치 만 정 의 했 고, ListHelper. smallest / 3 은 없 었 기 때문에 일치 실패 로 오 류 를 던 졌 습 니 다.
lambdas 일치
명명 함 수 는 여러 함수 서명 을 정의 하여 다 중 모드 매 칭 을 사용 할 수 있 습 니 다. 익명 함 수 는 여러 def 정 의 를 쓸 수 없 지만 다 중 매개 변 수 를 사용 하여 패턴 매 칭 을 할 수 있 습 니 다. 쓰기 도 간단 하고 guards 문 구 를 지원 합 니 다.
기본 적 인 형식 은:
fn
pattern_1 ->
... Executed if pattern_1 matches
...
end
pattern_2 ->
... Executed if pattern_2 matches
...
end
iex(30)> test_num = fn
...(30)> x when is_number(x) and x < 0 ->
...(30)> :negative
...(30)> 0 -> :zero
...(30)> x when is_number(x) and x > 0 ->
...(30)> :positive
...(30)> end
#Function<6.90072148/1 in :erl_eval.expr/5>
iex(31)> test_num.(-1)
패턴 매 칭 을 통 해 많은 제어 구 조 를 실현 할 수 있 습 니 다.함수 에 맞 는 guard 자 구 는 if 조건 문 이 필요 하지 않 습 니 다.물론 Elixir 는 if 조건문 이 없 지만 if 매크로 를 제공 합 니 다.그 역할 은 if 조건 문 과 유사 하 며, 매크로 에 깊이 들 어가 기 전에 일단 하나의 일 로 여 긴 다.다음 절 에 서 는 Elixir 의 조건 제어 방식 을 소개 할 것 입 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.