2012-01-11 10 views
7

तो मेरी एफ # यात्रा में रिकॉर्ड करने के लिए मिल गया है और सबसे पहले वे खतरनाक लगते हैं। सबसे पहले यह चालाक लग रहा था:एफ # रिकॉर्ड्स: खतरनाक, केवल सीमित उपयोग के लिए, या अच्छी तरह से उपयोग की गई कार्यक्षमता?

type Card = { Name : string; 
      Phone : string; 
      Ok : bool } 

let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false } 

यह विचार कि कार्ड ए कार्ड से मेल खाता है। नहीं सरलीकृत पैटर्न यहाँ मिलान उल्लेख करने के लिए:

let withTrueOk = 
    list 
    |> Seq.filter 
    (function 
     | { Ok = true} -> true 
     | _ -> false 
) 

समस्या है:

type Card = { Name : string; 
      Phone : string; 
      Ok : bool } 

type CardTwo = { Name : string; 
      Phone : string; 
      Ok : bool } 

let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false } 

carda CardTwo प्रकार है जो मैं अनुमान लगा रहा हूँ आदेश में सब कुछ चल रहा है एफ # के साथ क्या करना है की अब है।

अब यह एक असंभव स्थिति हो सकती है क्योंकि दो प्रकार के समान हस्ताक्षर लेने का मौका कभी नहीं हो सकता है, लेकिन यह एक संभावना है।

कुछ रिकॉर्डिंग कर रहा है जिसमें केवल सीमित उपयोग है या क्या मैं इसे सिर्फ सोचने पर हूं?

+8

आप इसे ओवरइंक कर रहे हैं - अपने रिकॉर्ड तत्वों को अलग-अलग नाम दें या पूरी तरह योग्य करें कि आप किस रिकॉर्ड प्रकार का इरादा रखते हैं मिलान/तत्काल उदाहरण के लिए 'कार्ड ए = {कार्डनाम = "अल्फ" दें; फोन = "(206) 555-0157"; ठीक = झूठा} '। – ildjarn

+14

डिफ़ॉल्ट रूप से आईएमएचओ उत्परिवर्तन, विरासत और संरचनात्मक समानता की कमी कक्षाओं को रिकॉर्ड से अधिक खतरनाक बनाती है, लेकिन आप इसके बारे में शिकायत करने वाले कई लोगों को नहीं देखते हैं ;-) –

+7

@MauricioScheffer डिफ़ॉल्ट रूप से उस शून्यता में जोड़ें। –

उत्तर

18

वे खतरनाक नहीं हैं और वे केवल सीमित उपयोग के लिए नहीं हैं।

मुझे लगता है कि यह बहुत दुर्लभ है कि आपके पास एक ही सदस्य के साथ दो प्रकार होंगे।

let cardA = { Card.Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false } 

रिकॉर्ड्स (अधिकतर) अपरिवर्तनीय डेटा संरचनाओं बनाने के लिए बहुत उपयोगी होते हैं: लेकिन अगर आप उस स्थिति का सामना करते हैं, आप रिकॉर्ड प्रकार आप उपयोग करना चाहते अर्हता प्राप्त कर सकते हैं। और तथ्य यह है कि आप आसानी से बस कुछ क्षेत्रों के साथ एक प्रतिलिपि बना सकते हैं बदल महान भी है:

let cardB = { cardA with Ok = true } 
12

मैं मानता हूँ, संलग्न मॉड्यूल/नाम स्थान के सदस्यों के रूप रिकॉर्ड क्षेत्रों पहले और अधिक परंपरागत OO भाषाओं से आने वाले अजीब लगता है। लेकिन एफ # यहां उचित लचीलापन प्रदान करता है। मैं तुम्हें मिल जाएगा केवल काल्पनिक परिस्थितियों समस्याओं के कारण लगता है, जैसे दो रिकॉर्ड कि

  1. समान
  2. हैं एक सबसेट/सुपरसेट संबंध

पहला मामला कभी नहीं करना चाहिए। उत्तरार्द्ध को बी रिकॉर्ड रिकॉर्ड से हल किया जा सकता है।

आपको दोनों को अलग-अलग होने के लिए अलग होने के लिए केवल एक फ़ील्ड की आवश्यकता है। इसके अलावा, परिभाषाएं समान हो सकती हैं।

type Card = 
    { Name : string 
    Phone: string 
    Ok : bool } 

type CardTwo = 
    { Name : string 
    Phone: string 
    Age : int } 

let card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false } 
let cardTwo = { Name = "Alf" ; Phone = "(206) 555-0157" ; Age = 21 } 

पैटर्न मिलान के रूप में आप केवल अन्य प्रकार से अलग करने के लिए पर्याप्त खेतों पर मिलान करने की आवश्यकता भी काफी लचीला है।

let readCard card = 
    match card with 
    | { Ok = false } ->() //OK 
    | { Age = 21 } ->() //ERROR: 'card' already inferred as Card, but pattern implies CardTwo 

संयोग से, अपने परिदृश्य को आसानी से एक प्रकार टिप्पणी के साथ तय हो गई है:

let cardA : Card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false } 
+0

एक सबसेट/सुपरसेट संबंध क्यों समस्या होगी? AFAIK, आपको हमेशा सभी गुणों को निर्दिष्ट करना होगा। – svick

+2

जब पैटर्न मिलान। आपको केवल अन्य रिकॉर्ड प्रकारों से अलग करने के लिए पर्याप्त फ़ील्ड पर मिलान करना होगा। मेरा कोड जांचें। – Daniel

6

आदेश में आप की सराहना करते हैं कि क्या एफ # प्रदान करता है, मैं बस में रिकॉर्ड के लिए कोई पूरी तरह से योग्य एक्सेसर है कि वहाँ उल्लेख करना चाहते हैं OCaml।इसलिए, एक ही फ़ील्ड के साथ रिकॉर्ड प्रकारों के बीच अंतर करने के लिए, आपको उन्हें मॉड्यूल उपसर्गों का उपयोग करके उन्हें submodules में रखना होगा और उन्हें संदर्भित करना होगा।

तो एफ # में आपकी स्थिति बहुत बेहतर है। इसी तरह रिकॉर्ड प्रकार के बीच कोई अस्पष्टता रिकॉर्ड एक्सेसर का उपयोग कर जल्दी से हल किया जा सकता है:

type Card = { Name: string; 
      Phone: string; 
      Ok: bool } 

type CardSmall = { Address: string; 
      Ok: bool } 

let withTrueOk list = 
    list 
    |> Seq.filter (function 
       | { Card.Ok = true} -> true (* ambiguity could happen here *) 
       | _ -> false) 

इसके अलावा, एफ # रिकॉर्ड सब पर सीमित नहीं है। यह पैटर्न मिलान, डिफ़ॉल्ट अपरिवर्तनीयता, संरचनात्मक समानता इत्यादि सहित बहुत अच्छी सुविधाएं प्रदान करता है

+9

यदि आप एक ही फ़ील्ड के साथ दो रिकॉर्ड प्रकार परिभाषित कर रहे हैं, तो आप अपने प्रकारों को '[]' के साथ एनोटेट करके अयोग्य पहुंच (और अंतर्निहित अस्पष्टता) को रोक सकते हैं। – Daniel

+0

@ डैनियल: अच्छा पकड़ो। – pad

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