2010-03-04 10 views
9

मैं प्रपत्र के एक समारोह है का उपयोग करते हुएमें OCaml या एफ # मिलान पैटर्न में एक चर

'a -> ('a * int) list -> int 

let rec getValue identifier bindings = 
    match bindings with 
    | (identifier, value)::tail -> value 
    | (_, _)::tail -> getValue identifier tail 
    | [] -> -1 

मैं बता सकता है कि identifier तरह से मैं यह चाहते हैं के लिए बाध्य किया जा रहा है और एक नया चर के रूप में काम कर रहा है मैच अभिव्यक्ति के भीतर। फ़ंक्शन में क्या पारित होने के लिए मुझे identifier कैसे प्राप्त करें?

ठीक है! मैंने इसे पैटर्न गार्ड के साथ तय किया है, यानी | (i, value)::tail when i = indentifier -> value लेकिन मुझे मूल रूप से ऐसा करने के तरीके की तुलना में यह बदसूरत लगता है (मैं केवल इन भाषाओं का उपयोग कर रहा हूं क्योंकि वे सुंदर हैं ...)। कोई विचार?

+0

आपका मूल दृष्टिकोण मुझे प्रोलॉग के एकीकरण की याद दिलाता है, यह कार्यात्मक से अपेक्षाकृत घोषणात्मक है। – ron

उत्तर

10

आप एक पैटर्न बनाने के लिए एफ # सक्रिय पैटर्न का उपयोग कर सकते हैं जो आपको वही करेगा जो आपको चाहिए। एफ # पैरामीटरयुक्त सक्रिय पैटर्न का समर्थन करता है जो आपके द्वारा मेल खाने वाले मान को लेते हैं, लेकिन एक अतिरिक्त पैरामीटर भी लेते हैं।

let (|Test|_|) arg value = 
    if value = 0 then None else Some(value + arg) 

आप इस तरह मिलान पैटर्न में पैरामीटर निर्दिष्ट कर सकते हैं:

यहाँ एक बहुत बेवकूफ उदाहरण है कि विफल रहता है जब value शून्य है और नहीं तो सफल होता है और मूल्य के अलावा और निर्दिष्ट पैरामीटर देता है:

match 1 with 
| Test 100 res -> res // 'res' will be 101 

अब, हम आसानी से एक सक्रिय पैटर्न है कि सक्रिय पैटर्न के इनपुट तर्क के साथ मिलान मूल्य की तुलना करेंगे परिभाषित कर सकते हैं।

let (|Equals|_|) arg x = 
    if (arg = x) then Some() else None 

let foo x y = 
    match x with 
    | Equals y -> "equal" 
    | _ -> "not equal" 

आप एक नेस्टेड के रूप में उपयोग कर सकते हैं: सक्रिय पैटर्न रिटर्न unit option, जिसका अर्थ है कि यह किसी भी नए मूल्य के लिए बाध्य नहीं करता है (ऊपर के उदाहरण में, यह है कि हम एक प्रतीक res करने के लिए सौंपा कुछ मान दिया) पैटर्न, तो आप Equals सक्रिय पैटर्न का उपयोग कर अपने उदाहरण को फिर से लिखने में सक्षम होना चाहिए।

+0

दिलचस्प (एक प्रकार के लिए सक्रिय पैटर्न का लेखन बॉयलरप्लेट की तरह महसूस करना चाहिए, लेकिन आप केवल उन्हें एक बार लिखते हैं और कई बार इसका लाभ उठाते हैं)। मॉड्यूल हस्ताक्षर में वे कैसे दिखते हैं? –

+0

'बराबर' सक्रिय पैटर्न सामान्य है और किसी भी प्रकार के लिए काम करता है जो तुलना का समर्थन करता है (एफ # में उपलब्ध प्रकार चर पर एक विशेष बाधा)। सक्रिय पैटर्न हस्ताक्षर में एक विशेष नाम के कार्यों के रूप में दिखाते हैं। हस्ताक्षर इस तरह दिखता है: 'वैल (| बराबर | _ |): 'ए ->' ए -> यूनिट विकल्प जब 'ए: समानता' –

3

यह एक आम शिकायत है, लेकिन मुझे नहीं लगता कि सामान्य रूप से एक अच्छा कामकाज है; एक पैटर्न गार्ड आमतौर पर सबसे अच्छा समझौता होता है। कुछ विशिष्ट मामलों में विकल्प हैं, हालांकि, एफ # में [<Literal>] विशेषता वाले अक्षरों को चिह्नित करने के लिए, ताकि उनके खिलाफ मिलान किया जा सके।

5

यह सीधे प्रश्न का उत्तर नहीं है: एक चर के मूल्य को पैटर्न-मिलान कैसे करें। लेकिन यह पूरी तरह से असंबंधित नहीं है।

यदि आप देखना चाहते हैं कि एफ # या ओकैमल की तरह एमएल जैसी भाषा में कितना शक्तिशाली पैटर्न-मिलान हो सकता है, तो Moca पर एक नज़र डालें।

आप मोका द्वारा उत्पन्न कोड को भी देख सकते हैं :) (यह नहीं कि संकलक के साथ आपके लिए बहुत सी चीजें करने में कुछ भी गलत है। कुछ मामलों में, यह वांछनीय है, लेकिन कई प्रोग्रामर यह महसूस करने के लिए कि वे जानते हैं कि वे कौन से परिचालन लिख रहे हैं)।

+0

+1: ठंडा! डीएसएल को लागू करने के लिए एक दिलचस्प विकल्प की तरह लग रहा है। – Juliet

6

कार्यात्मक भाषाओं की सुंदरियों में से एक उच्च आदेश कार्य है। उन कार्यों का उपयोग करके हम रिकर्सन लेते हैं और केवल उस पर ध्यान केंद्रित करते हैं जो आप वास्तव में करना चाहते हैं। जो पहले टपल है कि आपके पहचानकर्ता से मेल खाता का मूल्य प्राप्त करने के लिए है अन्यथा -1 वापसी:

let getValue identifier list = 
match List.tryFind (fun (x,y) -> x = identifier) list with 
    | None  -> -1 
    | Some(x,y) -> y 

//val getValue : 'a -> (('a * int) list -> int) when 'a : equality 

यह paper ग्राहम हटन आप उच्च आदेश कार्यों के साथ क्या कर सकते हैं के लिए एक महान परिचय है।

+1

* आंखें विस्फोट * प्वाइंट-फ्री शैली चालाक है, लेकिन अपठनीय और अनजान है। 'मजेदार एक्स -> एक्स |> List.map fst |> List.filter (मजेदार वाई -> वाई = पहचानकर्ता)' पठनीयता को बलि किए बिना एक ही चीज़ व्यक्त करता है। – Juliet

+0

प्वाइंट लिया गया। मुझे आशा है कि यह संशोधन बेहतर होगा। :) –

+0

सच है, कोशिश करें भाषा का सबसे अच्छा उपयोग होगा क्योंकि मैं केवल अस्थायी रूप से -1 का उपयोग किसी के लिए स्टैंड-इन के रूप में नहीं कर रहा था। लेकिन मुझे खुशी है कि मैंने पैटर्न मिलान और परिवर्तनीय बाध्यकारी के बारे में कुछ और सीखा। –

2

जो आप करने की कोशिश कर रहे हैं उसे समानता पैटर्न कहा जाता है, और यह उद्देश्य कैमल द्वारा प्रदान नहीं किया जाता है। उद्देश्य कैमल के पैटर्न स्थिर और पूरी तरह से संरचनात्मक हैं। यही है, क्या पैटर्न से मेल खाता मूल्य पूरी तरह से मूल्य की संरचना पर निर्भर करता है, और इस तरह संकलित समय पर निर्धारित किया जाता है। उदाहरण के लिए, (_, _)::tail एक ऐसा पैटर्न है जो किसी भी गैर-खाली सूची से मेल खाता है जिसका सिर एक जोड़ी है। (identifier, value)::tail बिल्कुल वही मान मेल खाता है; केवल अंतर यह है कि उत्तरार्द्ध दो और नाम identifier और value बांधता है।

हालांकि कुछ भाषाओं में समानता पैटर्न हैं, फिर भी गैर-मामूली व्यावहारिक विचार हैं जो उन्हें परेशान करते हैं। कौन सा समानता? ओककल में शारीरिक समानता (==), संरचनात्मक समानता (= ओकैम में), या कुछ प्रकार-निर्भर कस्टम समानता? इसके अलावा, ओकैम में, एक स्पष्ट वाक्यविन्यास संकेत है जिसमें नाम बाइंडर्स हैं और कौन से नाम पहले बाध्य मानों के संदर्भ में हैं: पैटर्न में कोई लोअरकेस पहचानकर्ता एक बाइंडर है। इन दो कारणों से पता चलता है कि क्यों ओकैम में बराबर समानता पैटर्न नहीं हैं। ओकंपल में समानता पैटर्न व्यक्त करने का मूर्ख तरीका गार्ड में है। इस तरह, यह तुरंत स्पष्ट है कि मिलान संरचनात्मक नहीं है, identifier इस पैटर्न मिलान से बंधे नहीं है, और कौन सा समानता उपयोग में है। बदसूरत के रूप में, यह दर्शक की नजर में है - एक आदत ओकंपल प्रोग्रामर के रूप में, मुझे समानता पैटर्न बदसूरत (उपरोक्त कारणों से) मिलते हैं। active patterns, जो आप गार्ड कि एक पैटर्न में एक ही साइट चिंता का विषय पूर्व परिभाषित करते हैं:

match bindings with 
| (id, value)::tail when id = identifier -> value 
| (_, _)::tail -> getValue identifier tail 
| [] -> -1 

एफ # में, आप एक और संभावना है।

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