खोज…


सरल सक्रिय पैटर्न

सक्रिय पैटर्न एक विशेष प्रकार के पैटर्न से मेल खाते हैं जहां आप नामित श्रेणियों को निर्दिष्ट कर सकते हैं कि आपका डेटा गिर सकता है, और फिर match स्टेटमेंट में उन श्रेणियों का उपयोग कर सकते हैं।

एक सक्रिय पैटर्न को परिभाषित करने के लिए जो संख्याओं को सकारात्मक, नकारात्मक या शून्य के रूप में वर्गीकृत करता है:

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

फ़ंक्शन f और g के उपयोगकर्ता के लिए दो भिन्न संस्करणों के बीच कोई अंतर नहीं है।

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

एक चिंता यह है कि क्या सक्रिय पैटर्न ओवरहेड को जोड़ता है। चलो अगर यह मामला है तो देखने के लिए f और g को विघटित करने के लिए ILSpy का उपयोग करें।

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 रैपर के रूप में सक्रिय पैटर्न

सक्रिय नेटवर्क्स का उपयोग कुछ .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"

सक्रिय पैटर्न में लिपटे रहने के लिए एक और अच्छा उम्मीदवार नियमित अभिव्यक्ति एपीआई है:

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 लौटाकर कुछ संभावित परिणामों को स्पष्ट रूप से अनदेखा करते हैं। उनकी परिभाषा बेजोड़ मामले के लिए _ एक विशेष मामले का उपयोग करती है।

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