패턴 매칭

패턴 매칭 (Pattern Matching)

패턴은 입력 데이터를 변형하는 규칙이에요. F#에서는 패턴을 곳곳에서 씁니다. 데이터를 논리적인 구조 하나 또는 여럿과 비교하거나, 데이터를 구성 요소로 분해하거나, 데이터에서 여러 방식으로 정보를 뽑아낼 때 사용해요. 겉보기에는 복잡해 보여도, 핵심은 "입력이 어떤 모양일 때 이렇게 처리하라"는 규칙을 미리 적어 두는 것이라고 생각하면 쉬워요.

출처: Pattern Matching - F# Language Reference (learn.microsoft.com)

본문

Remarks (패턴은 어디에 쓰이나)

패턴은 match 식 같은 많은 언어 구성 요소에서 사용돼요. let 바인딩의 함수 인자를 처리할 때, 람다 식에서, 그리고 try...with 식의 예외 처리기에서도 쓰입니다. 자세한 내용은 Match Expressions, let Bindings, Lambda Expressions: The fun Keyword, Exceptions: The try...with Expression 문서를 참고하세요.

예를 들어 match 식에서는 파이프 기호( | ) 뒤에 오는 것이 바로 패턴이에요.

match expression with
| pattern [ when condition ] -> result-expression
...

각 패턴은 어떤 식으로든 입력을 변형하는 규칙처럼 동작해요. match 식에서는 각 패턴을 차례로 검사해서 입력 데이터가 그 패턴과 맞는지 봅니다. 일치하는 패턴을 찾으면 해당 결과 식을 실행하고, 일치하는 게 없으면 다음 패턴 규칙을 시험해요. 선택적인 when condition 부분에 대한 설명은 Match Expressions 문서에 있어요.

F#이 지원하는 패턴은 아래 표와 같습니다. 런타임에는 표에 나열된 순서대로 입력을 각 패턴과 시험하고, 패턴은 코드에 나타난 순서대로 처음부터 끝까지, 그리고 각 줄 안에서는 왼쪽에서 오른쪽으로 재귀적으로 적용돼요.

이름 설명 예시
상수 패턴 (Constant pattern) 숫자·문자·문자열 리터럴, 열거형 상수, 또는 정의된 리터럴 식별자 1.0, "test", 30, Color.Red
식별자 패턴 (Identifier pattern) 판별 공용체의 케이스 값, 예외 레이블, 또는 활성 패턴 케이스 Some(x), Failure(msg)
변수 패턴 (Variable pattern) identifier a
as 패턴 (as pattern) pattern as identifier (a, b) as tuple1
OR 패턴 (OR pattern) pattern1 | pattern2 ([h] | [h; _])
AND 패턴 (AND pattern) pattern1 & pattern2 (a, b) & (_, "test")
Cons 패턴 (Cons pattern) identifier :: list-identifier h :: t
목록 패턴 (List pattern) [ pattern_1 ; ... ; pattern_n ] [ a; b; c ]
배열 패턴 (Array pattern) `[ pattern_1 ; ..; pattern_n |]`
괄호 패턴 (Parenthesized pattern) ( pattern ) ( a )
튜플 패턴 (Tuple pattern) ( pattern_1 , ... , pattern_n ) ( a, b )
레코드 패턴 (Record pattern) { identifier1 = pattern_1 ; ... ; identifier_n = pattern_n } { Name = name; }
와일드카드 패턴 (Wildcard pattern) _ _
타입 주석이 붙은 패턴 (Pattern with type annotation) pattern : type a : int
타입 테스트 패턴 (Type test pattern) :? type [ as identifier ] :? System.DateTime as dt
null 패턴 (Null pattern) null null
nameof 패턴 (Nameof pattern) nameof expr nameof str

상수 패턴 (Constant Patterns)

상수 패턴은 숫자·문자·문자열 리터럴과 열거형 상수(열거형 타입 이름을 포함한 형태)를 뜻해요. 상수 패턴만으로 이뤄진 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

식별자 패턴 (Identifier Patterns)

패턴이 유효한 식별자를 이루는 문자열이라면, 그 식별자의 형태에 따라 매칭 방식이 달라져요. 식별자가 한 글자보다 길고 대문자로 시작하면 컴파일러는 식별자 패턴으로 매치를 시도해요. 이 패턴의 식별자는 Literal 특성이 붙은 값, 판별 공용체 케이스, 예외 식별자, 또는 활성 패턴 케이스일 수 있어요. 일치하는 식별자를 찾지 못하면 매치는 실패하고, 다음 패턴 규칙인 변수 패턴이 입력과 비교됩니다.

판별 공용체 패턴은 단순한 이름 붙은 케이스일 수도 있고, 값을 하나 가지거나 여러 값이 담긴 튜플을 가질 수도 있어요. 값이 있으면 그 값에 대한 식별자를 지정해야 해요. 튜플인 경우에는 튜플의 각 요소에 식별자를 부여하는 튜플 패턴을 제공하거나, 이름 붙은 공용체 필드 하나 이상에 필드 이름이 달린 식별자를 제공해야 합니다. 이 섹션의 코드 예시를 참고하세요.

option 타입은 SomeNone 두 케이스를 가진 판별 공용체예요. 한 케이스( Some )는 값을 갖지만, 다른 케이스( None )는 그저 이름만 붙은 케이스입니다. 그래서 Some은 그 케이스와 연관된 값을 담을 변수가 필요하고, None은 홀로 나타나야 해요. 아래 코드에서 변수 var1Some 케이스에 매칭해서 얻은 값을 받아요.

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}"
| _ -> ()

활성 패턴(Active Patterns)을 사용하면 더 복잡한 사용자 정의 패턴 매칭을 정의할 수 있어요. 활성 패턴에 대한 자세한 내용은 Active Patterns 문서를 참고하세요.

식별자가 예외인 경우는 예외 처리기의 문맥에서 패턴 매칭에 사용됩니다. 예외 처리에서의 패턴 매칭에 대한 내용은 Exceptions: The try...with Expression 문서를 참고하세요.

변수 패턴 (Variable Patterns)

변수 패턴은 매칭되는 값을 변수 이름에 할당하는데, 그 변수는 -> 기호 오른쪽의 실행 식에서 사용할 수 있어요. 변수 패턴 단독으로는 어떤 입력이든 매치하지만, 보통 다른 패턴 안에 나타나서 튜플·배열처럼 더 복잡한 구조를 변수들로 분해할 수 있게 해 줍니다.

다음 예시는 튜플 패턴 안의 변수 패턴을 보여줘요.

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 Pattern)

as 패턴은 as 절이 붙어 있는 패턴이에요. as 절은 매치된 값을 이름에 묶어서 match 식의 실행 식에서 사용하게 하며, 이 패턴을 let 바인딩에서 쓰는 경우에는 그 이름이 로컬 스코프에 바인딩으로 추가됩니다.

아래 예시가 as 패턴을 사용해요.

let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1

OR 패턴 (OR Pattern)

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 Pattern)

AND 패턴은 입력이 두 패턴에 모두 매치될 것을 요구해요. AND 패턴 양쪽의 타입은 호환되어야 합니다.

다음 예시는 이 문서의 튜플 패턴 섹션에 나오는 detectZeroTuple과 비슷하지만, 여기서는 AND 패턴을 써서 var1var2 둘 다 값을 얻어내요.

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)

Cons 패턴 (Cons Pattern)

cons 패턴은 목록을 첫 번째 요소( head )와 나머지 요소를 담은 목록( tail )으로 분해하는 데 사용해요.

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

cons 패턴을 여러 개 연결하면 특정 요소 시퀀스로 시작하는 목록을 매치할 수도 있어요.

let charList = ['A'; 'B'; 'C'; 'D']

// This example demonstrates multiple cons patterns.
let matchChars xs =
    match xs with
    | 'A'::'B'::t -> printfn "starts with 'AB', rest: %A" t
    | 'A'::t -> printfn "starts with 'A', rest: %A" t
    | 'C'::'D'::t -> printfn "starts with 'CD', rest: %A" t
    | _ -> printfn "does not match"

matchChars charList
matchChars ['A'; 'X']
matchChars ['C'; 'D'; 'E']

목록 패턴 (List Pattern)

목록 패턴은 목록을 여러 요소로 분해할 수 있게 해 줍니다. 목록 패턴 자체는 요소 수가 정해진 목록에만 매치할 수 있어요.

// 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 [ ] )

배열 패턴 (Array Pattern)

배열 패턴은 목록 패턴과 비슷하며, 길이가 정해진 배열을 분해하는 데 쓸 수 있어요.

// 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 [| |] )

괄호 패턴 (Parenthesized Pattern)

괄호로 패턴을 묶어 원하는 결합성(associativity)을 만들 수 있어요. 아래 예시에서는 AND 패턴과 cons 패턴 사이의 결합성을 제어하기 위해 괄호를 사용합니다.

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

튜플 패턴 (Tuple Pattern)

튜플 패턴은 튜플 형태의 입력을 매치하고, 튜플의 각 위치에 패턴 매칭 변수를 사용해 튜플을 구성 요소로 분해할 수 있게 해 줍니다.

다음 예시는 튜플 패턴을 보여주며 리터럴 패턴·변수 패턴·와일드카드 패턴도 함께 사용해요.

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)

레코드 패턴 (Record Pattern)

레코드 패턴은 레코드를 분해해서 필드 값을 추출하는 데 사용해요. 패턴이 레코드의 모든 필드를 참조할 필요는 없으며, 생략된 필드는 매칭에 참여하지도 않고 추출되지도 않습니다.

// 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"

와일드카드 패턴 (Wildcard Pattern)

와일드카드 패턴은 밑줄( _ ) 문자로 표현하며, 변수 패턴과 마찬가지로 어떤 입력이든 매치해요. 다만 입력을 변수에 할당하는 대신 버려버린다는 점이 다릅니다. 와일드카드 패턴은 -> 기호 오른쪽 식에서 필요 없는 값의 자리 표시자로 다른 패턴 안에서 자주 쓰여요. 또 매치되지 않은 입력을 처리하려고 패턴 목록의 끝에 두는 경우도 흔합니다. 와일드카드 패턴은 이 문서의 여러 코드 예시에서 볼 수 있는데, 앞선 코드에서도 예를 확인할 수 있어요.

다음 코드는 와일드카드 패턴의 몇 가지 추가 용법을 보여줍니다.

// Wildcard pattern matching "nothing" examples

// Example 1: Wildcard ignoring function parameters
let ignoreAllParams _ _ = "Ignores all input"

// Example 2: Wildcard in destructuring, ignoring elements
let getFirstOnly (first, _) = first

// Example 3: Using wildcard to ignore optional values
let handleEmpty opt =
    match opt with
    | Some _ -> "Has something"
    | None -> "Has nothing"

// Usage
printfn "%s" (ignoreAllParams 42 "test")
printfn "%d" (getFirstOnly (1, "ignored"))
printfn "%s" (handleEmpty None)

타입 주석이 붙은 패턴 (Patterns That Have Type Annotations)

패턴에는 타입 주석을 붙일 수 있어요. 타입 주석이 붙은 패턴은 다른 타입 주석처럼 동작하고, 다른 타입 주석처럼 추론을 안내합니다. 패턴에서 타입 주석 주위에는 괄호가 필요해요.

타입 주석이 붙은 패턴은 pattern : type 문법을 쓰며 컴파일 시점의 타입 정보를 타입 검사기에게 제공해요. 이는 타입 추론을 돕는 순수한 정적 타입 주석일 뿐이며, 런타임 타입 검사나 변환을 수행하지 않습니다. 컴파일러는 컴파일 중 이 정보를 사용해 패턴 변수의 타입을 결정합니다.

다음 코드는 타입 주석이 붙은 패턴을 보여줘요.

let detect1 x =
    match x with
    | 1 -> printfn "Found a 1!"
    | (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1

이 예시에서 (var1 : int)는 컴파일러에게 var1int 타입임을 알려줘요. 이는 컴파일 타임에 결정되며, 생성된 코드는 match 식 전체에 걸쳐 var1을 정수로 취급해요. 이 패턴은 어떤 정수 값이든 매치해 var1에 묶어 줍니다.

주요 특징:

  • pattern : type 문법(콜론 하나)을 사용해요.
  • 컴파일 타임에 결정됩니다 — 타입 검사기에 타입 정보를 제공해요.
  • 런타임 타입 테스트는 수행하지 않아요.
  • 타입 추론과 컴파일러 안내에 사용돼요.

타입 테스트 패턴 (Type Test Pattern)

타입 테스트 패턴은 런타임 에 입력을 타입과 매치하는 데 사용해요. 입력 타입이 패턴에 지정된 타입과 일치하거나(또는 그 타입의 파생 타입이면) 매치가 성공해요.

타입 테스트 패턴은 :? type 문법을 사용하고 런타임 타입 검사 를 수행하며, C#의 is 또는 as 연산자와 유사해요. 이 패턴은 프로그램 실행 중에 어떤 값이 특정 타입인지 시험하므로, 상속 계층이나 인터페이스 구현을 다룰 때 유용해요.

다음 예시가 타입 테스트 패턴을 보여줍니다.

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"
    | _ -> ()

주요 특징:

  • :? type 또는 :? type as identifier 문법(물음표 포함)을 사용해요.
  • 런타임에 결정됩니다 — 실행 중 실제 타입 검사를 수행해요.
  • 값이 특정 타입이나 그 파생 타입의 인스턴스인지 시험해요.
  • 상속 계층과 다형 타입에서 자주 사용돼요.
  • C#의 is 연산자 또는 as 연산자와 비슷해요.

타입 주석 패턴과 타입 테스트 패턴의 대비

두 패턴 모두 타입과 관련되지만, 목적은 아주 다릅니다.

기능 타입 주석 패턴 ( pattern : type ) 타입 테스트 패턴 ( :? type )
문법 콜론 하나: a : int 물음표가 딸린 콜론: :? Button
결정 시점 컴파일 타임 런타임
목적 타입 추론을 안내 값의 실제 타입을 테스트
사용처 컴파일러가 타입을 이해하도록 도움 상속 계층에서 런타임 타입 확인
C#에서의 대응물 switch 패턴의 타입 주석 is 또는 as 연산자

다음 예시가 두 패턴의 차이를 보여줘요.

// Type annotation pattern - compile time
let detect1 x =
    match x with
    | 1 -> printfn "Found a 1!"
    | (var1 : int) -> printfn "%d" var1
// The ': int' tells the compiler var1 is an int
// Everything is resolved at compile time

// Type test pattern - runtime
type A() = class end
type B() = inherit A()

let test (a: A) =
    match a with
    | :? B -> printfn "Runtime check: it's a B"
    | _ -> printfn "Runtime check: it's not a B"
// The ':? B' performs a runtime type check
// The actual type is tested during execution

null 패턴 (Null Pattern)

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 허용(nullability) 기능에서도 권장됩니다.

let len (str: string | null) =
    match str with
    | null -> -1
    | s -> s.Length

마찬가지로 새로 추가된 null 허용 관련 전용 패턴도 쓸 수 있어요.

let len str =       // str is inferred to be `string | null`
    match str with
    | Null -> -1
    | NonNull (s: string) -> s.Length

nameof 패턴 (Nameof Pattern)

nameof 패턴은 문자열의 값이 nameof 키워드 뒤에 오는 식과 같을 때 그 문자열에 매치돼요. 이 패턴은 문자열 값을 코드 속 타입·판별 공용체 케이스·기타 심볼의 이름과 매치해야 할 때 특히 유용합니다. nameof를 사용하면 컴파일 타임 안전성을 얻을 수 있어요. 심볼 이름을 바꾸면 패턴이 자동으로 새 이름을 사용하게 되거든요.

흔한 사용처는 타입 또는 케이스 이름을 뜻하는 문자열 값이 담긴 데이터를 역직렬화(deserialize)하는 경우예요.

type EventType =
    | OrderCreated
    | OrderShipped
    | OrderDelivered

let handleEvent eventName data =
    match eventName with
    | nameof OrderCreated -> printfn "Processing order creation: %s" data
    | nameof OrderShipped -> printfn "Processing order shipment: %s" data
    | nameof OrderDelivered -> printfn "Processing order delivery: %s" data
    | _ -> printfn "Unknown event type: %s" eventName

handleEvent "OrderCreated" "Order #123" // matches first case
handleEvent "OrderShipped" "Order #123" // matches second case

이 방식이 문자열 리터럴(예: "OrderCreated")을 쓰는 것보다 나은 이유는 다음과 같아요.

  • OrderCreatedOrderPlaced로 바꾸면 패턴이 자동으로 갱신돼요.
  • 컴파일러가 심볼이 존재하는지 확인해 줘서 오타를 막아요.
  • 리팩터링할 때 코드가 일관되게 유지됩니다.

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 연산자 문서를 참고하세요.

더 알아보기