2013-04-04 10 views
8

निम्न कोड में झलकीरिकार्ड प्रकार निष्कर्ष

type myrec1 = {x: int; y: int} 
type myrec2 = {x: int; y: int; z: int} 

let p1 = {x = 1; y = 1} // Error. p1 compiler assumes p1 has the type myrec2 

// It works with additional type specification 
let p1: myrec1 = {x = 1; y = 1} 
let p2: myrec2 = {x = 1; y = 1; z = 1} 

टिप्पणी संकलन नहीं करता है के साथ लाइन। किसी कारण से टाइप चेकर यह नहीं समझ सकता कि पी 1 के लिए प्रकार myrec1 होना चाहिए। क्या ऐसा इसलिए है क्योंकि टाइप अनुमान का यह मामला बस असंभव है या क्या यह केवल एफ # प्रकार अनुमान की सीमा है?

उत्तर

9

here से:

सबसे हाल ही में घोषित प्रकार के लेबल से प्राथमिकता दी जाती पहले से घोषित प्रकार

तो उन लोगों के लिए यदि आप इसे इस तरह कार्य करें:

type myrec2 = {x: int; y: int; z: int} 
type myrec1 = {x: int; y: int} 

let p1 = {x = 1; y = 1} 

तो यह काम करेगा।

here से

अपने पढ़ने खुशी के लिए (एफ # 3.0 युक्ति):

field-initializer : long-ident = expr 

6.3.5 रिकार्ड भाव

इस मामले में हमारे क्षेत्र के प्रारंभकर्ता एक भी पहचानकर्ता नहीं है, तो यह 14.1.9 से "फ़ील्ड लेबल रेज़ोल्यूशन" का उपयोग करता है।

प्रत्येक फ़ील्ड-प्रारंभकर्ताइज़र में फॉर्म फ़ील्ड-लेबलि = एक्सपीरी है। प्रत्येक क्षेत्र-labeli एक लंबे समय से अध्यक्ष, जो एक अनूठा रिकॉर्ड प्रकार आर में एक क्षेत्र Fi से संकल्प करना चाहिए इस प्रकार है:

· क्षेत्र labeli एक भी पहचानकर्ता fld है और प्रारंभिक प्रकार माना जाता है तो एक रिकॉर्ड प्रकार आर < , ...,> जिसमें नाम फ़ील्ड के साथ फ़ील्ड Fi है, तो फ़ील्ड लेबल Fi को हल करता है।

· यदि क्षेत्र के labeli एक भी पहचानकर्ता नहीं है या यदि प्रारंभिक प्रकार एक चर प्रकार, तो क्षेत्र लेबल क्षेत्र-labeli पर प्रदर्शन फील्ड लेबल संकल्प (देखें §14.1) द्वारा हल हो गई है है। फ़ील्ड FSeti के एक सेट में यह प्रक्रिया परिणाम। इस सेट के प्रत्येक तत्व में एक समान रिकॉर्ड प्रकार है, जिसके परिणामस्वरूप रिकॉर्ड प्रकार RSeti का एक सेट होता है। सभी RSeti के चौराहे एक भी रिकॉर्ड प्रकार आर उपज चाहिए, और प्रत्येक क्षेत्र तो आर

में संगत फ़ील्ड पर ले कर जाता

14.1.9 फील्ड लेबल संकल्प

हमारे लंबे समय से अध्यक्ष एक है फील्ड लेबल, इसलिए यह 8.4.2 में वर्णित फ़ील्ड लेबल तालिका का उपयोग करके देखा गया है।

फ़ील्ड लेबल रेज़ोल्यूशन निर्दिष्ट करता है कि फ़ील्ड 1 जैसे फ़ील्ड 1 {field1 = expr; ... fieldN = expr}। फील्ड लेबल रेज़ोल्यूशन निम्न चरणों के माध्यम से प्राप्त होता है:

1. सभी तालिकाओं को फ़ील्ड टेबल और फ़ील्ड लेबल तालिका (§8.4.2) में सभी उपलब्ध प्रकारों में देखें।

2. फील्ड घोषणाओं का सेट वापस करें।

8.4.2 नाम संकल्प और रिकार्ड फील्ड

लेबल के रूप में यहां बताया गया है, FieldLabels तालिका सदस्य (14.1) के लिए नाम संकल्प में प्रयोग किया जाता है।

एक रिकॉर्ड प्रकार के लिए, रिकॉर्ड क्षेत्र लेबल फ़ील्ड 1 ... fieldN वर्तमान नाम संकल्प पर्यावरण की FieldLabels मेज पर जोड़ रहे हैं जब तक रिकॉर्ड प्रकार RequireQualifiedAccess विशेषता है। फ़ील्ड लेबल तालिका में रिकॉर्ड फ़ील्ड लेबल सदस्यों के लिए नाम समाधान (§14.1) में एक विशेष भूमिका निभाते हैं: एक अभिव्यक्ति का प्रकार रिकॉर्ड लेबल से अनुमानित हो सकता है। उदाहरण के लिए: आर = {dx: int टाइप करें; dy: int} चलिए x x = x.dx // x को टाइप करने के लिए अनुमानित किया गया है इस उदाहरण में, लुकअप .dx को फ़ील्ड लुकअप होने का हल किया गया है।

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

को देखते हुए एक इनपुट लंबे समय से अध्यक्ष, पर्यावरण env, और का एक वैकल्पिक गिनती n बाद प्रकार तर्क < की संख्या , ...,>, में भाव नाम संकल्प एक परिणाम है कि शामिल की गणना करता है लंबी पहचान < , ...,> किसी मान या अन्य अभिव्यक्ति आइटम के रूप में उपसर्ग, और अवशेष पथ आराम की व्याख्या। अभिव्यक्ति आय में नाम संकल्प पर निर्भर करता है कि लंबी पहचान एक पहचानकर्ता है या एक पहचानकर्ता से अधिक से बना है। यदि लंबी पहचान एक पहचानकर्ता पहचान है:

1. ExprItems तालिका में पहचान देखें। परिणाम और खाली आराम वापस करें।

2. यदि पहचान ExprItems तालिका में प्रकट नहीं होती है, तो सामान्य तालिका के साथ, जो उपलब्ध होने पर सामान्य मिलान के साथ टाइप टेबल में इसे देखें। इस प्रकार और खाली आराम को लौटें।

3. यदि पहचान ExprItems तालिका या प्रकार तालिका में प्रकट नहीं होती है, तो विफल हो जाती है।

...

अभिव्यक्ति अस्पष्टता, भाव में नाम संकल्प पहला परिणाम है कि इस प्रक्रिया उत्पन्न रिटर्न दें।

जिस हिस्से में आप रुचि रखते हैं वह ऊपर की आखिरी पंक्ति है: "प्रक्रिया उत्पन्न करने वाला पहला परिणाम देता है"।

+0

+ 1 यह जवाब है। – Daniel

4

यह व्यवहार डिज़ाइन द्वारा है।मैं यह नहीं कह सकता कि यह एफ # के प्रकार अनुमान की सीमा है, या सामान्य रूप से टाइप अनुमान एल्गोरिदम की सीमा है; अगर आप इसके बारे में सोचते हैं, वहाँ दो विकल्प हालांकि इस प्रकार हैं:

  1. को देखते हुए एक रिकार्ड अभिव्यक्ति {x = 1; y = 1}, 'एक्स' और 'y' पिछले प्रकार के खिलाफ क्षेत्रों उनमें से या तो घोषित करने के लिए मेल खाते हैं। यह समझने में सबसे आसान है, और यह है कि एफ # कंपाइलर रिकॉर्ड प्रकार अनुमान को लागू करता है।

  2. वर्तमान दायरे में प्रकार के क्षेत्रों के आधार पर 'सर्वश्रेष्ठ फिट' निर्धारित करने का प्रयास करें। (मुझे लगता है कि आप यही पूछ रहे हैं।)

    हालांकि, यह एल्गोरिदम अन्य मुद्दों का कारण बन सकता है; विशेष रूप से, एक रिकॉर्ड अभिव्यक्ति {x = 1; y = 1} के लिए संकलक यह नहीं बता सकता कि क्या आप myrec1 प्रकार की अभिव्यक्ति बनाना चाहते हैं, या यदि आप myrec2 की अभिव्यक्ति बनाना चाहते हैं और आप z फ़ील्ड को मान असाइन करना भूल गए हैं।

    इसके अलावा, यदि आप दो प्रकार के सटीक फ़ील्ड के साथ घोषित करते हैं तो संकलक क्या करना चाहिए? उदाहरण के लिए, क्या हुआ अगर आप जोड़ना:

    type myrec3 = {x: int; y: int} 
    

दूसरे शब्दों में, एक मुफ्त भोजन के रूप में ऐसी कोई बात नहीं है - आप प्रकार निष्कर्ष की "शक्ति" को बढ़ा सकते हैं, लेकिन यह हूँ आप संकलक से प्राप्त त्रुटि निदान में कुछ सटीकता खर्च करते हैं।

1

चूंकि कोई प्रकार की टिप्पणियां नहीं हैं, इसलिए कंपाइलर लेबल से रिकॉर्ड प्रकार का अनुमान लगाता है लेकिन पहले प्रकार के लोग दूसरे के लेबल से पर्याप्त रूप से अलग नहीं होते हैं, इसलिए बाद में प्राथमिकता होती है और पी 1 को myrec2 टाइप करने के लिए अनुमानित किया जाता है । आदेश प्रकार एनोटेशन से बचने और उम्मीद प्रकार निष्कर्ष व्यवहार प्राप्त करने के लिए अलग-अलग लेबल का उपयोग करें:

type myrec1 = {x1: int; y: int} 
type myrec2 = {x2: int; y: int; z: int} 

let p1 = {x1 = 1; y = 1} 
4

आप इसी नाम क्षेत्रों के साथ रिकॉर्ड प्रकारों चाहते हैं, जिस तरह से उन दोनों के बीच भेद करने के लिए यह है:

let p1 = {myrec1.x = 1; y = 1} 
+2

हालांकि यह सच है, यह सवाल का जवाब नहीं देता है। – mydogisbox

+0

सच है। अन्य उत्तरों में से कोई भी इसका उल्लेख नहीं करता है, इसलिए मैंने सोचा कि यह एक अच्छा विचार होगा। –

+0

मैं सहमत हूं। इस प्रश्न को पाने वाले को ध्यान में रखते हुए, यह संभवतः यहां होना उपयोगी है। – mydogisbox

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