패턴 일치
패턴은 입력 데이터를 변환하기 위한 규칙입니다. F# 전체에서 논리 구조 또는 구조와 데이터를 비교하거나, 데이터를 구성 요소로 분해하거나, 다양한 방법으로 데이터에서 정보를 추출하는 데 사용됩니다.
발언
패턴은 match
식과 같은 많은 언어 구문에서 사용됩니다.
let
바인딩, 람다 식 및 try...with
식과 연결된 예외 처리기에서 함수에 대한 인수를 처리할 때 사용됩니다. 자세한 내용은 일치 식, let 바인딩, 람다 식: fun
키워드및 예외: try...with
식를 참조하세요.
예를 들어 match
식에서 패턴 파이프 기호 뒤에 있습니다.
match expression with
| pattern [ when condition ] -> result-expression
...
각 패턴은 어떤 식으로든 입력을 변환하는 규칙으로 작동합니다.
match
식에서 각 패턴을 차례로 검사하여 입력 데이터가 패턴과 호환되는지 확인합니다. 일치 항목이 발견되면 결과 식이 실행됩니다. 일치 항목을 찾을 수 없으면 다음 패턴 규칙이 테스트됩니다.
조건 부분은 일치 식에서 설명될 때 선택 사항입니다.
지원되는 패턴은 다음 표에 나와 있습니다. 런타임에 입력은 테이블에 나열된 순서에서 다음 패턴 각각에 대해 테스트되며, 패턴은 코드에 표시되는 첫 번째 패턴에서 마지막까지, 각 줄의 패턴에 대해 왼쪽에서 오른쪽으로 재귀적으로 적용됩니다.
이름 | 묘사 | 본보기 |
---|---|---|
상수 패턴 | 숫자, 문자 또는 문자열 리터럴, 열거형 상수 또는 정의된 리터럴 식별자 |
1.0 , "test" , 30 , Color.Red |
식별자 패턴 | 구별된 유니온의 경우 값, 예외 레이블 또는 활성 패턴의 경우 | Some(x) Failure(msg) |
가변 패턴 | 식별자 | a |
as 패턴 |
패턴식별자 | (a, b) as tuple1 |
OR 패턴 | pattern1 | pattern2 | ([h] | [h; _]) |
AND 패턴 | 패턴1 & 패턴2 | (a, b) & (_, "test") |
단점 패턴 | 식별자 :: 목록 식별자 | h :: t |
목록 패턴 | [ pattern_1; ... ; pattern_n ] | [ a; b; c ] |
배열 패턴 | [| pattern_1; ..; pattern_n |] | [| a; b; c |] |
괄호로 묶인 패턴 | ( 패턴 ) | ( a ) |
튜플 패턴 | ( pattern_1, ... , pattern_n ) | ( a, b ) |
레코드 패턴 | { identifier1 = pattern_1; ... ; identifier_n = pattern_n } | { Name = name; } |
와일드카드 패턴 | _ | _ |
패턴과 형식 주석 함께하기 | 패턴 : 형식 | a : int |
타입 테스트 패턴 | :? 형식 [ 식별자로서 ] | :? System.DateTime as dt |
Null 패턴 | 널 | null |
이름의 패턴 | 표현 이름 | nameof str |
상수 패턴
상수 패턴은 숫자, 문자 및 문자열 리터럴, 열거형 상수입니다(열거형 형식 이름이 포함됨). 상수 패턴만 있는 match
식은 다른 언어의 case 문과 비교할 수 있습니다. 입력은 리터럴 값과 비교되며 값이 같으면 패턴이 일치합니다. 리터럴의 형식은 입력 형식과 호환되어야 합니다.
다음 예제에서는 리터럴 패턴의 사용을 보여 줍니다. 또한 변수 패턴 및 OR 패턴을 사용합니다.
[<Literal>]
let Three = 3
let filter123 x =
match x with
// The following line contains literal patterns combined with an OR pattern.
| 1 | 2 | Three -> printfn "Found 1, 2, or 3!"
// The following line contains a variable pattern.
| var1 -> printfn "%d" var1
for x in 1..10 do filter123 x
리터럴 패턴의 또 다른 예는 열거형 상수에 기반한 패턴입니다. 열거형 상수를 사용하는 경우 열거형 형식 이름을 지정해야 합니다.
type Color =
| Red = 0
| Green = 1
| Blue = 2
let printColorName (color:Color) =
match color with
| Color.Red -> printfn "Red"
| Color.Green -> printfn "Green"
| Color.Blue -> printfn "Blue"
| _ -> ()
printColorName Color.Red
printColorName Color.Green
printColorName Color.Blue
식별자 패턴
패턴이 유효한 식별자를 형성하는 문자 문자열인 경우 식별자 형식에 따라 패턴이 일치하는 방법이 결정됩니다. 식별자가 단일 문자보다 길고 대문자로 시작하는 경우 컴파일러는 식별자 패턴과 일치시키려고 시도합니다. 이 패턴의 식별자는 리터럴 특성, 구분된 공용 구조체 사례, 예외 식별자 또는 활성 패턴 사례로 표시된 값일 수 있습니다. 일치하는 식별자를 찾을 수 없으면 일치가 실패하고 다음 패턴 규칙인 변수 패턴이 입력과 비교됩니다.
식별된 유니온 패턴은 단순한 명명된 경우일 수도 있고, 하나의 값 또는 여러 값을 포함하는 튜플일 수도 있습니다. 값이 있는 경우 값의 식별자를 지정해야 합니다. 튜플의 경우 튜플의 각 요소에 대한 식별자가 있는 튜플 패턴을 제공하거나 하나 이상의 명명된 공용 구조체 필드에 대한 필드 이름을 가진 식별자를 제공해야 합니다. 예제는 이 섹션의 코드 예제를 참조하세요.
option
형식은 Some
및 None
두 가지 사례가 있는 차별된 공용 구조체입니다. 한 사례(Some
)에는 값이 있지만 다른 사례(None
)는 명명된 사례일 뿐입니다. 따라서 Some
Some
사례와 연결된 값에 대한 변수가 있어야 하지만 None
그 자체로 나타나야 합니다. 다음 코드에서 변수 var1
Some
사례와 일치하여 얻은 값이 제공됩니다.
let printOption (data : int option) =
match data with
| Some var1 -> printfn "%d" var1
| None -> ()
다음 예제에서 PersonName
구별된 유니온에는 이름의 가능한 형식을 나타내는 문자열과 문자가 혼합되어 있습니다. 차별된 공용 구조체의 경우는 FirstOnly
, LastOnly
및 FirstLast
.
type PersonName =
| FirstOnly of string
| LastOnly of string
| FirstLast of string * string
let constructQuery personName =
match personName with
| FirstOnly(firstName) -> printf "May I call you %s?" firstName
| LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
| FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName
명명된 필드가 있는 구분된 공용 구조체의 경우 등호(=)를 사용하여 명명된 필드의 값을 추출합니다. 예를 들어 다음과 같은 선언이 있는 판별된 합집합을 고려하십시오.
type Shape =
| Rectangle of height : float * width : float
| Circle of radius : float
다음과 같이 패턴 일치 식에서 명명된 필드를 사용할 수 있습니다.
let matchShape shape =
match shape with
| Rectangle(height = h) -> printfn $"Rectangle with length %f{h}"
| Circle(r) -> printfn $"Circle with radius %f{r}"
명명된 필드의 사용은 선택 사항이므로 이전 예제에서는 Circle(r)
및 Circle(radius = r)
모두 동일한 효과를 갖습니다.
여러 필드를 지정할 때 세미콜론(;)을 구분 기호로 사용합니다.
match shape with
| Rectangle(height = h; width = w) -> printfn $"Rectangle with height %f{h} and width %f{w}"
| _ -> ()
활성 패턴을 사용하면 더 복잡한 사용자 지정 패턴 일치를 정의할 수 있습니다. 활성 패턴에 대한 자세한 내용은 활성 패턴참조하세요.
식별자가 예외인 경우 예외 처리기의 컨텍스트에서 패턴 일치에 사용됩니다. 예외 처리의 패턴 일치에 대한 자세한 내용은 예외: try...with
식참조하세요.
변수 패턴
변수 패턴은 일치하는 값을 변수 이름에 할당한 다음 ->
기호의 오른쪽에 있는 실행 식에서 사용할 수 있습니다. 변수 패턴만으로도 모든 입력과 일치하지만 변수 패턴은 종종 다른 패턴 내에 표시되므로 튜플 및 배열과 같은 더 복잡한 구조체를 변수로 분해할 수 있습니다.
다음 예제에서는 튜플 패턴 내의 변수 패턴을 보여 줍니다.
let function1 x =
match x with
| (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
| (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
| (var1, var2) -> printfn "%d equals %d" var1 var2
function1 (1,2)
function1 (2, 1)
function1 (0, 0)
패턴으로
as
패턴은 as
절이 추가된 패턴입니다.
as
절은 일치하는 값을 match
식의 실행 식에 사용할 수 있는 이름에 바인딩하거나, 이 패턴이 let
바인딩에서 사용되는 경우 이름이 로컬 범위에 바인딩으로 추가됩니다.
다음 예제에서는 as
패턴을 사용합니다.
let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1
또는 패턴
OR 패턴은 입력 데이터가 여러 패턴과 일치할 수 있고 결과와 동일한 코드를 실행하려는 경우에 사용됩니다. OR 패턴의 양면 형식은 호환되어야 합니다.
다음 예제에서는 OR 패턴을 보여 줍니다.
let detectZeroOR point =
match point with
| (0, 0) | (0, _) | (_, 0) -> printfn "Zero found."
| _ -> printfn "Both nonzero."
detectZeroOR (0, 0)
detectZeroOR (1, 0)
detectZeroOR (0, 10)
detectZeroOR (10, 15)
AND 패턴
AND 패턴을 사용하려면 입력이 두 패턴과 일치해야 합니다. AND 패턴의 양면 형식은 호환되어야 합니다.
다음 예제는 이 항목의 뒷부분에 있는 튜플 패턴 섹션에 표시된 detectZeroTuple
같지만 여기서는 var1
및 var2
모두 AND 패턴을 사용하여 값으로 가져옵니다.
let detectZeroAND point =
match point with
| (0, 0) -> printfn "Both values zero."
| (var1, var2) & (0, _) -> printfn "First value is 0 in (%d, %d)" var1 var2
| (var1, var2) & (_, 0) -> printfn "Second value is 0 in (%d, %d)" var1 var2
| _ -> printfn "Both nonzero."
detectZeroAND (0, 0)
detectZeroAND (1, 0)
detectZeroAND (0, 10)
detectZeroAND (10, 15)
단점 패턴
컨스 패턴은 목록을 첫 번째 요소인 헤드와 나머지 요소를 포함하는 목록인 테일로 분해하는 데 사용됩니다.
let list1 = [ 1; 2; 3; 4 ]
// This example uses a cons pattern and a list pattern.
let rec printList l =
match l with
| head :: tail -> printf "%d " head; printList tail
| [] -> printfn ""
printList list1
목록 패턴
목록 패턴을 사용하면 목록을 여러 요소로 분해할 수 있습니다. 목록 패턴 자체는 특정 개수의 요소 목록만 일치시킬 수 있습니다.
// This example uses a list pattern.
let listLength list =
match list with
| [] -> 0
| [ _ ] -> 1
| [ _; _ ] -> 2
| [ _; _; _ ] -> 3
| _ -> List.length list
printfn "%d" (listLength [ 1 ])
printfn "%d" (listLength [ 1; 1 ])
printfn "%d" (listLength [ 1; 1; 1; ])
printfn "%d" (listLength [ ] )
배열 패턴
배열 패턴은 목록 패턴과 유사하며 특정 길이의 배열을 분해하는 데 사용할 수 있습니다.
// This example uses array patterns.
let vectorLength vec =
match vec with
| [| var1 |] -> var1
| [| var1; var2 |] -> sqrt (var1*var1 + var2*var2)
| [| var1; var2; var3 |] -> sqrt (var1*var1 + var2*var2 + var3*var3)
| _ -> failwith (sprintf "vectorLength called with an unsupported array size of %d." (vec.Length))
printfn "%f" (vectorLength [| 1. |])
printfn "%f" (vectorLength [| 1.; 1. |])
printfn "%f" (vectorLength [| 1.; 1.; 1.; |])
printfn "%f" (vectorLength [| |] )
괄호로 감싼 패턴
괄호는 원하는 결합성을 달성하기 위해 패턴을 중심으로 그룹화할 수 있습니다. 다음 예제에서 괄호는 AND 패턴과 단점 패턴 간의 결합성을 제어하는 데 사용됩니다.
let countValues list value =
let rec checkList list acc =
match list with
| (elem1 & head) :: tail when elem1 = value -> checkList tail (acc + 1)
| head :: tail -> checkList tail acc
| [] -> acc
checkList list 0
let result = countValues [ for x in -10..10 -> x*x - 4 ] 0
printfn "%d" result
튜플 패턴
튜플 패턴은 튜플 형식의 입력과 일치하며 튜플의 각 위치에 대해 패턴 일치 변수를 사용하여 튜플을 해당 구성 요소로 분해할 수 있습니다.
다음 예제에서는 튜플 패턴을 보여 줍니다. 리터럴 패턴, 변수 패턴 및 와일드카드 패턴도 사용합니다.
let detectZeroTuple point =
match point with
| (0, 0) -> printfn "Both values zero."
| (0, var2) -> printfn "First value is 0 in (0, %d)" var2
| (var1, 0) -> printfn "Second value is 0 in (%d, 0)" var1
| _ -> printfn "Both nonzero."
detectZeroTuple (0, 0)
detectZeroTuple (1, 0)
detectZeroTuple (0, 10)
detectZeroTuple (10, 15)
레코드 패턴
레코드 패턴은 레코드를 분해하여 필드 값을 추출하는 데 사용됩니다. 패턴이 레코드의 모든 필드를 참조할 필요는 없습니다. 생략된 필드는 일치에 참여하지 않고 추출되지 않습니다.
// This example uses a record pattern.
type MyRecord = { Name: string; ID: int }
let IsMatchByName record1 (name: string) =
match record1 with
| { MyRecord.Name = nameFound; MyRecord.ID = _; } when nameFound = name -> true
| _ -> false
let recordX = { Name = "Parker"; ID = 10 }
let isMatched1 = IsMatchByName recordX "Parker"
let isMatched2 = IsMatchByName recordX "Hartono"
와일드카드 패턴
와일드카드 패턴은 밑줄(_
) 문자로 표현되며 변수 패턴과 마찬가지로 모든 입력과 일치합니다. 단, 입력은 변수에 할당되지 않고 삭제됩니다. 와일드카드 패턴은 종종 다른 패턴 내에서 ->
기호 오른쪽의 식에 필요하지 않은 값의 자리 표시자로 사용됩니다. 와일드카드 패턴은 종종 패턴 목록의 끝에 사용되어 아직 일치하지 않은 입력을 매칭합니다. 와일드카드 패턴은 이 항목의 많은 코드 예제에서 보여 줍니다. 한 가지 예제는 위의 코드를 참조하세요.
형식 주석이 있는 패턴
패턴에는 형식 주석이 있을 수 있습니다. 이러한 주석은 다른 형식 주석과 같이 동작하며 다른 형식 주석과 같이 유추를 안내합니다. 패턴의 형식 주석에는 괄호가 필요합니다. 다음 코드는 형식 주석이 있는 패턴을 보여 줍니다.
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1
타입 테스트 패턴
형식 테스트 패턴은 입력과 형식을 일치시킬 때 사용됩니다. 입력 형식이 패턴에 지정된 형식과 일치(또는 파생 형식)이면 일치가 성공합니다.
다음 예제에서는 형식 테스트 패턴을 보여 줍니다.
open System.Windows.Forms
let RegisterControl(control:Control) =
match control with
| :? Button as button -> button.Text <- "Registered."
| :? CheckBox as checkbox -> checkbox.Text <- "Registered."
| _ -> ()
식별자가 특정 파생 형식인지만 확인하는 경우 다음 예제와 같이 패턴의 as identifier
부분이 필요하지 않습니다.
type A() = class end
type B() = inherit A()
type C() = inherit A()
let m (a: A) =
match a with
| :? B -> printfn "It's a B"
| :? C -> printfn "It's a C"
| _ -> ()
Null 패턴
null 패턴은 null 값을 허용하는 형식으로 작업할 때 나타날 수 있는 null 값과 일치합니다. Null 패턴은 .NET Framework 코드와 상호 운용할 때 자주 사용됩니다. 예를 들어 .NET API의 반환 값은 match
식에 대한 입력일 수 있습니다. 반환 값이 null인지 여부와 반환된 값의 다른 특성에 따라 프로그램 흐름을 제어할 수 있습니다. null 패턴을 사용하여 null 값이 프로그램의 나머지 부분에 전파되지 않도록 방지할 수 있습니다.
다음 예제에서는 null 패턴과 변수 패턴을 사용합니다.
let ReadFromFile (reader : System.IO.StreamReader) =
match reader.ReadLine() with
| null -> printfn "\n"; false
| line -> printfn "%s" line; true
let fs = System.IO.File.Open("..\..\Program.fs", System.IO.FileMode.Open)
let sr = new System.IO.StreamReader(fs)
while ReadFromFile(sr) = true do ()
sr.Close()
Null 패턴은 F# 9의 null 허용 여부 기능에도 권장됩니다.
let len (str: string | null) =
match str with
| null -> -1
| s -> s.Length
마찬가지로, 새로운 널러빌리티 관련 전용 패턴을 사용할 수 있습니다.
let let str = // str is inferred to be `string | null`
match str with
| Null -> -1
| NonNull (s: string) -> s.Length
Nameof 패턴
nameof
패턴은 해당 값이 nameof
키워드 뒤에 있는 식과 같을 때 문자열과 일치합니다. 예를 들어:
let f (str: string) =
match str with
| nameof str -> "It's 'str'!"
| _ -> "It is not 'str'!"
f "str" // matches
f "asdf" // does not match
이름을 사용할 수 있는 항목에 대한 자세한 내용은 nameof
연산자를 참조하세요.
참고 항목
.NET