수색…


단순한 활성 패턴

활성 패턴은 데이터가 들어갈 수있는 명명 된 카테고리를 지정할 수있는 특별한 유형의 패턴 일치 유형이며 match 문에서 해당 범주를 사용합니다.

숫자를 양수, 음수 또는 0으로 분류하는 활성 패턴을 정의하려면 다음을 수행하십시오.

let (|Positive|Negative|Zero|) num = 
    if num > 0 then Positive 
    elif num < 0 then Negative
    else Zero

다음 패턴 일치 식에서 사용할 수 있습니다.

let Sign value = 
    match value with
    | Positive -> printf "%d is positive" value
    | Negative -> printf "%d is negative" value
    | Zero -> printf "The value is zero"

Sign -19 // -19 is negative
Sign 2 // 2 is positive
Sign 0 // The value is zero

매개 변수가있는 활성 패턴

활성 패턴은 단순한 기능입니다.

함수와 마찬가지로 추가 매개 변수를 정의 할 수 있습니다.

let (|HasExtension|_|) expected (uri : string) = 
    let result = uri.EndsWith (expected, StringComparison.CurrentCultureIgnoreCase)
    match result with
    | true -> Some true
    | _ -> None

이 방법으로 일치하는 패턴에서 사용할 수 있습니다.

    let isXMLFile uri =
        match uri with
        | HasExtension ".xml" _ -> true
        | _ -> false

활성 패턴은 함수 인수의 유효성을 검사하고 변환하는 데 사용할 수 있습니다.

F# 에서 액티브 패턴의 흥미롭지 만 사용되지 않는 사용법은 함수 인수를 검증하고 변환하는 데 사용할 수 있다는 것입니다.

인수 검증을 수행하는 고전적인 방법을 고려하십시오.

// val f : string option -> string option -> string
let f v u =
  let v = defaultArg v "Hello"
  let u = defaultArg u "There"
  v + " " + u

// val g : 'T -> 'T (requires 'T null)
let g v =
  match v with
  | null  -> raise (System.NullReferenceException ())
  | _     -> v.ToString ()

일반적으로 메소드에 코드를 추가하여 인수가 올바른지 확인합니다. F# 에서 액티브 패턴을 사용하여 이것을 일반화하고 인수 선언에서 인 텐트를 선언 할 수 있습니다.

다음 코드는 위의 코드와 동일합니다.

let inline (|DefaultArg|) dv ov = defaultArg ov dv

let inline (|NotNull|) v =
  match v with
  | null  -> raise (System.NullReferenceException ())
  | _     -> v

// val f : string option -> string option -> string
let f (DefaultArg "Hello" v) (DefaultArg "There" u) = v + " " + u

// val g : 'T -> string (requires 'T null)
let g (NotNull v) = v.ToString ()

함수 fg 의 사용자에게는 두 가지 버전간에 차이가 없습니다.

printfn "%A" <| f (Some "Test") None  // Prints "Test There"
printfn "%A" <| g "Test"              // Prints "Test"
printfn "%A" <| g null                // Will throw

Active Patterns가 성능 오버 헤드를 추가하는 경우 문제가 발생할 수 있습니다. 이 경우에 ILSpy 를 사용하여 fg 를 디 컴파일하여 봅시다.

public static string f(FSharpOption<string> _arg2, FSharpOption<string> _arg1)
{
  return Operators.DefaultArg<string>(_arg2, "Hello") + " " + Operators.DefaultArg<string>(_arg1, "There");
}

public static string g<a>(a _arg1) where a : class
{
  if (_arg1 != null)
  {
    a a = _arg1;
    return a.ToString();
  }
  throw new NullReferenceException();
}

inline 덕택에 액티브 패턴은 기존의 인수 검증 방법과 비교하여 추가 오버 헤드를 추가하지 않습니다.

.NET API 래퍼로서의 활성 패턴

Active Patterns는 좀더 자연스러운, 특히 함수 반환 값 이상을 반환하는 출력 매개 변수를 사용하는 .NET API의 느낌을 호출하는 데 사용할 수 있습니다.

예를 들어, 일반적으로 System.Int32.TryParse 메서드를 다음과 같이 호출합니다.

let couldParse, parsedInt = System.Int32.TryParse("1")
if couldParse then printfn "Successfully parsed int: %i" parsedInt
else printfn "Could not parse int"

패턴 매칭을 사용하여 조금 향상시킬 수 있습니다.

match System.Int32.TryParse("1") with 
| (true, parsedInt) -> printfn "Successfully parsed int: %i" parsedInt
| (false, _) -> printfn "Could not parse int"

그러나 System.Int32.TryParse 함수를 래핑하는 다음과 같은 활성 패턴을 정의 할 수도 있습니다.

let (|Int|_|) str =
    match System.Int32.TryParse(str) with
    | (true, parsedInt) -> Some parsedInt
    | _ -> None

이제 다음을 수행 할 수 있습니다.

match "1" with
| Int parsedInt -> printfn "Successfully parsed int: %i" parsedInt
| _ -> printfn "Could not parse int"

액티브 패턴으로 싸이기위한 또 다른 좋은 방법은 정규 표현식 API입니다.

let (|MatchRegex|_|) pattern input =
    let m = System.Text.RegularExpressions.Regex.Match(input, pattern) 
    if m.Success then Some m.Groups.[1].Value 
    else None  

match "bad" with
| MatchRegex "(good|great)" mood -> 
    printfn "Wow, it's a %s day!" mood
| MatchRegex "(bad|terrible)" mood -> 
    printfn "Unfortunately, it's a %s day." mood
| _ -> 
    printfn "Just a normal day"

전체 및 부분 활성 패턴

사용 패턴이 다소 다른 두 가지 유형의 활성 패턴 (전체 및 부분)이 있습니다.

완전한 활성 패턴은 "결과가 홀수 또는 홀수입니까?"와 같이 모든 결과를 열거 할 수있을 때 사용할 수 있습니다.

let (|Odd|Even|) number = 
  if number % 2 = 0
  then Even
  else Odd

활성 패턴 정의에는 가능한 경우와 그 외에는 모두 나열되지 않으며 본문은 나열된 사례 중 하나를 반환합니다. 일치 식에 사용하면 다음과 같이 완전 일치합니다.

let n = 13
match n with
| Odd -> printf "%i is odd" n
| Even -> printf "%i is even" n

입력 공간을 완전히 커버하는 알려진 카테고리로 나누고 싶을 때 유용합니다.

반면 부분 활성 패턴을 사용하면 option 을 반환하여 가능한 일부 결과를 명시 적으로 무시할 수 option . 그들의 정의는 타의 추종을 불허하는 경우에 _ 의 특별한 경우를 사용합니다.

let (|Integer|_|) str =
  match Int32.TryParse(str) with
  | (true, i) -> Some i
  | _ -> None

이렇게하면 우리의 파싱 기능으로는 어떤 경우를 처리 할 수없는 경우에도 일치시킬 수 있습니다.

let s = "13"
match s with
| Integer i -> "%i was successfully parsed!" i
| _ -> "%s is not an int" s

부분 활성 패턴은 다른 옵션을 무시하면서 입력이 입력 공간의 특정 범주에 속하는지 여부에 관계없이 테스트 형식으로 사용할 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow