2015-05-27 5 views
9

मान लीजिए कि आप इस संघ करते हैं:क्या एक पैटर्न एक यूनियन केस से जुड़े डेटा प्राप्त करने का एकमात्र तरीका है?

type Thing = 
| Eagle 
| Elephant of int 

और अपने कोड

let l = [Elephant (1000); Elephant (1200)] 

में के रूप में, हाथी की एक सूची है और तुम l से अधिक पुनरावृति, और प्रत्येक के साथ जुड़े डेटा प्रिंट आउट करना चाहता था Elephant। पैटर्न मिलान का उपयोग किए बिना ऐसा करने का कोई तरीका है?

+0

खराब पैटर्न मिलान क्यों? –

+0

अच्छी तरह से आप 'सदस्य' या कार्यों का उपयोग कर सकते हैं ... लेकिन उन्हें पैटर्न-मिलान का उपयोग करके deconstruct करने की आवश्यकता होगी - लेकिन वास्तव में आप और क्या उम्मीद कर सकते हैं? – Carsten

उत्तर

0

आप Microsoft.FSharp.Reflection नामस्थान से प्रतिबिंब का उपयोग कर सकते हैं लेकिन यह अधिक बोझिल और धीमा है।

पैटर्न मिलान शायद भेदभाव वाले संघ से डेटा प्राप्त करने का सबसे आसान तरीका है।

(इसके अलावा आपके पास Things की एक सूची है, इसके सभी सदस्य Elephant यूनियन केस के होते हैं)।

10

अपने उदाहरण में, आप कहते हैं कि तुम हाथियों की एक सूची है कि - जो इस मामले में सच है - लेकिन l के प्रकार वास्तव में Thing मानों की सूची है और इसलिए यह दोनों हाथियों और ईगल हो सकते हैं। यही कारण है कि आपको सभी संभावित मामलों को संभालने के लिए पैटर्न मिलान का उपयोग करने की आवश्यकता है।

यदि आपको नियमित रूप से ऐसी सूची का उपयोग करने की आवश्यकता है जिसमें केवल हाथी हैं, तो यह अलग-अलग प्रकार के हाथियों को परिभाषित करने के लिए समझ में आ सकता है। कुछ की तरह:,

let l1 = [ {Size=1}; {Size=2} ] 
for el in l1 do printfn "%d" el.Size 

दूसरी ओर अगर आप चाहते हैं:

type ElephantInfo = { Size : int } 

type Thing = 
    | Elephant of ElephantInfo 
    | Eagle 

अब आप जो सिर्फ हाथियों शामिल कर सकते हैं और इसलिए आप पैटर्न मिलान की जरूरत नहीं है प्रकार list<ElephantInfo> की एक सूची बना सकते हैं मिश्रण हाथियों और ईगल, आप list<Thing> पैदा हो जाएगी और उसके बाद पैटर्न मिलान का उपयोग:

let l2 = [ Elephant {Size=1}; Eagle ] 
3

आप ऐसा कर सकता है:

l 
|> List.collect (function Elephant x -> [x] | _ -> []) 
|> List.iter (printfn "%i") 

प्रिंटों

1000 
1200 

यह अभी भी पैटर्न मिलान का उपयोग करता है, लेकिन यह काफी कम से कम है।

+1

'List.choose (फ़ंक्शन हाथी एक्स -> कुछ एक्स | _ -> कोई नहीं)' यहां बेहतर दिखता है। – bytebuster

+0

धन्यवाद, यह प्रभावी रूप से मैं अब क्या कर रहा हूं। –

+0

शायद मैं डीयू के कुएं का उपयोग नहीं कर रहा हूं। मैं उन्हें आंतरिक रूप से कमांड लाइन विकल्पों का प्रतिनिधित्व करने के लिए उपयोग कर रहा हूं, जिसे उपयोगकर्ता ने दर्ज किया है, और मामलों में से एक "स्ट्रिंग के रूप में अमान्य कॉमांड" है, जो सिस्टम को पहचानने वाले कमांड का प्रतिनिधित्व करने के लिए नहीं है। कोड में थोड़ी देर बाद, मैं इस सूची से सभी अमान्य कॉमांड निकालता हूं ताकि मैं उन्हें एक अलग उपयोग केस के रूप में संभाल सकूं। कोड जो इन अनावश्यक आदेशों को संभालता है, स्ट्रिंग डेटा (कमांड लाइन पर उपयोगकर्ता द्वारा गलत पाठ को गलत टेक्स्ट) प्राप्त करने के लिए पैटर्न मिलान करने की आवश्यकता होती है और यह केवल सूची का इलाज नहीं कर सकता क्योंकि केवल अमान्य कॉमांड है, इसे सभी के लिए खाता है डीयू –

1

पैटर्न मिलान को फ़ंक्शन के शीर्षलेख (या let बाध्यकारी) में रखने का एक तरीका है। हालांकि, यह अभी भी एक पैटर्न मैच है।

// This function takes a tuple: 
// the first argument is a Thing, 
// the second is "default" weight to be processed if the first one is NOT an Elephant 
let processElephant (Elephant weight, _ | _, weight) = 
    weight 

let [<Literal>] NON_ELEPHANT_WEIGHT = -1 

// usage: 
let totalWeight = 
    [Elephant (1000); Elephant (1200)] 
    |> List.sumBy (fun el -> processElephant(el, NON_ELEPHANT_WEIGHT)) 

This question और उसके answers अधिक विवरण के साथ प्रदान करते हैं।

3

आप निश्चित रूप से पूर्ण आइवरी टॉवर (® स्कॉट Wlaschin)

बारे में के रूप में जाने का विकल्प होता है:

type Thing = 
| Eagle 
| Elephant of int 

type MaybeElephantBuilder() =  
member this.Bind(x, f) = 
    match x with 
    | Eagle -> 0 
    | Elephant a -> f a 

member this.Return(x) = x 

let maybeElephant = new MaybeElephantBuilder() 

let l = 
[ Elephant(1000) 
    Elephant(1200) 
    ] 

let printIt v = 
let i = 
    maybeElephant { 
    let! elephantValue = v 
    return elephantValue 
    } 
printfn "%d" i 

l |> Seq.iter printIt 

यह भी सामान ईगल्स वहाँ में फेंक दिया के साथ संभाल लेंगे!

खैर ...

गैर ईगल्स निकालें और कोड के लिए उड़ान भरने जाएगा ...

let l = 
[ Eagle 
    Leadon 
    Elephant(1000) 
    Eagle 
    Meisner 
    Elephant(1200) 
    Eagle 
    Felder 
    ] 

l |> Seq.iter printIt 

लेकिन कोई। ये अच्छा नहीं है। यह छोटा नहीं है। मज़े के लिए यह और अधिक है (अगर वह!) किसी और चीज़ की तुलना में। यह शायद एफ # गणना अभिव्यक्तियों का सबसे बुरा दुरुपयोग भी है!

और आप को कहीं भी मिलान करने वाले पैटर्न की आवश्यकता होगी।

Thx स्कॉट! और पेट्रीसेक।

वास्तविकता के लिए गणना अभिव्यक्ति चिड़ियाघर! ;-)

+1

एनआईसी पहली पोस्ट। आने वाले सालों में इसी तरह की चीजों की तलाश में! –

+1

@ रूबेनबार्टेलिंक नाह, वास्तव में नहीं। वैसे भी पहले नहीं ;-) –

+0

@ user1758475 आह, लेकिन क्या आप * साबित कर सकते हैं * आप उपयोगकर्ता 4 9 46443 हैं: पी कॉमन, वहां इंटरनेट हैंडल जनरेटर ऐप्स होना चाहिए! –

संबंधित मुद्दे

 संबंधित मुद्दे