मुझे अभी भी इस सवाल को थोड़ा उलझन में मिल रहा है लेकिन मुझे यह देखने दो कि क्या मैं इस प्रश्न को एक ऐसे रूप में दोहरा सकता हूं जिसे मैं उत्तर दे सकता हूं।
सी # 2.0 में, इस कोड:
int x = 123;
int y;
if (x * 0 == 0)
y = 345;
Console.WriteLine(y);
इलाज किया गया था जैसे कि आप लिखा था
int x = 123;
int y;
if (true)
y = 345;
Console.WriteLine(y);
बारी में है जो सबसे पहले, चलो मुझे फिर से राज्य सवाल की पृष्ठभूमि के रूप में माना जाता है:
int x = 123;
int y;
y = 345;
Console.WriteLine(y);
एक कानूनी कार्यक्रम कौन सा है।
लेकिन सी # 3.0 में हमने इसे रोकने के लिए ब्रेकिंग बदलाव लिया। इस तथ्य के बावजूद संकलक अब "हमेशा सत्य" होने के रूप में इस स्थिति का इलाज नहीं करता है कि आप और मैं दोनों जानते हैं कि यह हमेशा सत्य है। अब हम इसे एक अवैध कार्यक्रम बनाते हैं, क्योंकि संकलक के कारण यह नहीं जानता है कि "अगर" का शरीर हमेशा निष्पादित होता है, और इसलिए यह नहीं पता कि स्थानीय चर वाई को हमेशा इस्तेमाल होने से पहले असाइन किया जाता है।
सी # 3.0 व्यवहार सही क्यों है?
यह क्योंकि विनिर्देश कहा गया है कि सही है:
एक निरंतर अभिव्यक्ति केवल स्थिरांक शामिल होना चाहिए। x * 0 == 0
निरंतर अभिव्यक्ति नहीं है क्योंकि इसमें एक गैर-निरंतर शब्द, x
है।
if
का परिणाम केवल true
के बराबर स्थिर अभिव्यक्ति है, तो केवल हमेशा पहुंचने योग्य माना जाता है।
इसलिए, दिए गए सशर्त बयान के परिणाम को वर्गीकृत नहीं किया जाना चाहिए कोड हमेशा पहुंच योग्य होने के लिए, और इसलिए निश्चित रूप से निर्धारित किये जाने के रूप में स्थानीय y
वर्गीकृत नहीं करना चाहिए।
यह वांछनीय क्यों है कि निरंतर अभिव्यक्ति में केवल स्थिरांक होते हैं?
हम चाहते हैं कि सी # भाषा अपने उपयोगकर्ताओं द्वारा स्पष्ट रूप से समझने योग्य हो और संकलक लेखकों द्वारा सही ढंग से कार्यान्वित करने योग्य हो। यह आवश्यक है कि संकलक उन लक्ष्यों के खिलाफ अभिव्यक्ति के मूल्यों के बारे में सभी संभावित तार्किक कटौती करता है। यह निर्धारित करने के लिए सरल होना चाहिए या नहीं, और यदि हां, तो इसका मूल्य क्या है।बस रखें, निरंतर मूल्यांकन कोड को अंकगणित करने के लिए पता होना चाहिए, लेकिन तथ्यों अंकगणितीय जोड़ों के बारे में जानने की आवश्यकता नहीं है। निरंतर मूल्यांकनकर्ता कैसे 2 * 1 गुणा करने के लिए जानता है, लेकिन तथ्य को जानने की आवश्यकता नहीं है कि "1 पूर्णांक पर गुणक पहचान है"।
अब, यह संभव है कि एक कंपाइलर लेखक तय कर सकता है कि ऐसे क्षेत्र हैं जहां वे चालाक हो सकते हैं, और इस प्रकार अधिक इष्टतम कोड उत्पन्न करते हैं। कंपाइलर लेखकों को ऐसा करने की अनुमति है, लेकिन इस तरह से नहीं है कि कोड कानूनी या अवैध है। उन्हें केवल अनुकूलन करने की अनुमति है कि कानूनी कोड दिए जाने पर संकलक के आउटपुट को बेहतर बनाते हैं।
सी # 2.0 में बग कैसे हुआ?
क्या हुआ था कि गणित को अंकगणित अनुकूलक को बहुत जल्दी चलाने के लिए लिखा गया था। ऑप्टिमाइज़र थोड़ा सा चालाक माना जाता है, और के बाद इसे चलाने के लिए निर्धारित किया जाना चाहिए था। यह से पहले चल रहा था, कार्यक्रम कानूनी होने के लिए निर्धारित किया गया था, और इसलिए परिणाम को प्रभावित कर रहा था।
यह एक संभावित तोड़ने वाला परिवर्तन था: हालांकि यह संकलक को विनिर्देश के साथ लाइन में लाया, लेकिन यह संभावित रूप से कोड कोड को त्रुटि कोड में बदल गया। परिवर्तन में क्या प्रेरित हुआ?
LINQ सुविधाएं, और विशेष रूप से अभिव्यक्ति पेड़। यदि आप कुछ तरह ने कहा:
(int x)=>x * 0 == 0
और एक अभिव्यक्ति पेड़ में बदल जाती है कि, आप पाएंगे कि
(int x)=>true
के लिए अभिव्यक्ति पेड़ उत्पन्न करने के लिए उम्मीद करते हैं? शायद ऩही! आप शायद यह अभिव्यक्ति पेड़ का उत्पादन करने के लिए "शून्य से x गुणा करें और परिणाम की तुलना शून्य से करें"। अभिव्यक्ति के पेड़ों को शरीर में अभिव्यक्ति की तार्किक संरचना को संरक्षित रखना चाहिए।
जब मैं अभिव्यक्ति पेड़ कोड लिखा था यह अभी तक कि क्या डिजाइन समिति तय करने के लिए
()=>2 + 3
"तीन को दो जोड़ने के लिए" अभिव्यक्ति पेड़ या अभिव्यक्ति उत्पन्न करने के लिए जा रहा था जा रहा था स्पष्ट नहीं था "पांच" के लिए पेड़। हमने बाद में निर्णय लिया - स्थिरांक पेड़ उत्पन्न होने से पहले फ़ोल्ड किए गए हैं, लेकिन अभिव्यक्ति पेड़ उत्पन्न होने से पहले अंकगणित के माध्यम से अंकगणित नहीं किया जाना चाहिए।
तो, चलो अब निर्भरता कि हम सिर्फ कहा गया है पर विचार करें:
- अंकगणित अनुकूलन codegen से पहले होता है।
- अभिव्यक्ति पेड़ नए सिरे से लिखना अंकगणित अनुकूलन
- लगातार तह अभिव्यक्ति पेड़ को फिर से लिखने
- लगातार तह
- फ्लो विश्लेषण प्रवाह विश्लेषण से पहले होना होता है अभिव्यक्ति पेड़ को फिर से लिखने से पहले होना होता है से पहले होना होता है से पहले होना होता है (क्योंकि हम यह जानने की आवश्यकता है कि क्या एक अभिव्यक्ति वृक्ष एक अनियमित स्थानीय का उपयोग करता है)
हमें उन सभी निर्भरताओं को सम्मानित करने के लिए इस काम को करने का आदेश मिलना होगा। सी # 2.0 में संकलक इस क्रम में उन्हें क्या किया: एक ही समय में
- निरंतर तह और गणित अनुकूलन
- प्रवाह विश्लेषण
- codegen
कहाँ अभिव्यक्ति पेड़ पुनर्लेखन कर सकते हैं में वहाँ जाना? कहीं भी नहीं! और स्पष्ट रूप से यह छोटी है, क्योंकि प्रवाह विश्लेषण अब अंकगणित अनुकूलक द्वारा निर्धारित तथ्यों को ध्यान में रख रहा है। हम संकलक rework करने का फैसला किया है ताकि यह क्रम में बातें किया:
- निरंतर तह
- प्रवाह विश्लेषण
- अभिव्यक्ति पेड़ को फिर से लिखने
- अंकगणित अनुकूलन
- codegen
कौन सा स्पष्ट रूप से तोड़ने के बदलाव की जरुरत है।
जहां अनुकूलित अंकगणितीय अभिव्यक्ति में पॉइंटर को अपने अपरिवर्तित रूप में वापस रखा जाएगा। हमने फैसला किया कि को बग को सुरक्षित रखने के लिए यह बहुत जटिलता थी। हमने फैसला किया कि बग को ठीक करने के लिए बेहतर होगा, ब्रेकिंग चेंज लें, और कंपाइलर आर्किटेक्चर को आसानी से समझें।
जिस तरह से मैं इसे समझता हूं, एरिक कह रहा है कि यह विनिर्देश के अनुपालन में संकलक के व्यवहार को लाने के लिए मुख्य रूप से (यदि विशेष रूप से नहीं) तय किया गया था। –
@ कोडीग्रे, मुझे लगता है कि सवाल यह था कि यह विनिर्देशन में क्यों है। – mowwwalker
@ वाल्कर्नियो - स्पॉट ऑन। मैं समझता हूं कि परिवर्तन क्यों किया गया था (जैसे एरिक ने समझाया) लेकिन मुझे नहीं पता कि यह पहले स्थान पर क्यों है। हालांकि तर्कसंगत रूप से अवांछित यह मेरे दिमाग में बयानों की वैध श्रृंखला है। –