2016-12-06 6 views
10

जब एफ # में कोड के इस टुकड़े संकलन मैं सिर्फ ढांचा संस्करणों के बीच व्यवहार में बदलाव का सामना करना पड़ा:क्यों Lazy.CreateFromValue का व्यवहार .NET फ्रेमवर्क संस्करणों के बीच F # में बदल गया है?</p> <pre><code>let test = Lazy.CreateFromValue 1 </code></pre> <p>.NET फ्रेमवर्क 2.0 के खिलाफ संकलित, एक "पहले से ही बनाया" लेज़ी वस्तु में अभिव्यक्ति परिणाम, वह यह है कि:

test.IsValueCreated = true 

जब .NET फ़्रेमवर्क 4.0 के खिलाफ संकलित, एक "unevaluated" आलसी वस्तु में अभिव्यक्ति परिणाम, वह यह है कि:

test.IsValueCreated = false 

केवल परीक्षण तक पहुंचने के बाद। बाद के मामले में वैल्यू दोनों बराबर हैं।

मुझे कहीं भी इस बदलाव का कोई संदर्भ नहीं मिला, इसलिए मेरा सवाल यह है कि यह अलग तरीके से व्यवहार क्यों करता है और परिवर्तन के पीछे तर्क क्या था (यह तोड़ रहा है)। मेरी राय में, .NET 2.0 में व्यवहार अधिक समझ में आता है - एक ठोस मूल्य से एक आलसी वस्तु बनाने के परिणामस्वरूप "पहले ही मूल्यांकन किया गया" आलसी वस्तु होनी चाहिए।

+4

यदि इसका पहले से मूल्यांकन किया गया है, तो इसे शायद ही कभी मूल्यांकन किया जा सकता है ... –

+3

@MarkSeemann हाँ, लेकिन .NET 2 में, यह आलसी मूल्यांकन नहीं किया गया है, इसलिए मुझे लगता है कि कुछ भ्रम क्यों है। यह और भी है कि fsharp.core आलसी चीजें करता है ताकि इसे आलसी जैसा दिखने के लिए .NET 2 में किया जा सके, लेकिन यह कभी आलसी नहीं है। –

उत्तर

13

.NET 4.0 से पहले, ढांचा Lazy<'T> के साथ नहीं भेजा गया था।

यह प्राचीन इतिहास है, लेकिन एफ # मूल रूप से Lazy का अपना कार्यान्वयन था, जो हमारे पास आज से अलग है - आप इसकी एक झलक here देख सकते हैं।

यह कार्यान्वयन छोड़ दिया गया था जब यह स्पष्ट हो गया कि Lazy ढांचे में उचित रूप से आ रहा है। इसके बजाए, एफ # 2.0 (नामस्थान पर ध्यान दें) के अपने कार्यान्वयन के साथ FSharp.Core असेंबली में भेज दिया गया। यह कार्यान्वयन है कि आप अभी भी here देख सकते हैं। विचार यह था कि एक बार .NET 4.0 उपलब्ध हो जाने के बाद, एफ # उपयोगकर्ताओं को तोड़ने के बिना, वहां से System.Lazy<'T> को निर्बाध रूप से उठाएगा। जो अधिकांश भाग के लिए काम किया, लेकिन यह पूरी तरह से समस्याओं के बिना नहीं था।

आप ध्यान दें कि F # कार्यान्वयन में CreateFromValue सदस्य है जो Lazy<'T> के मान को पहले से ही मूल्यांकन के रूप में चिह्नित करता है। जो अर्थपूर्ण रूप से सही अर्थ बनाता है, क्योंकि आप स्पष्ट रूप से इसे पहले स्थान पर मूल्यांकन मान दे रहे हैं।

ऐसा क्यों है कि .NET 4.0 कार्यान्वयन ऐसा नहीं करता है?

यदि आप पर Lazy<'T> के लिए देखते हैं, तो आप पाएंगे कि मूल्यांकन किए गए राज्य में इसे बनाने का कोई तरीका नहीं है।इसमें कोई CreateFromValue सदस्य नहीं है, और कोई कन्स्ट्रक्टर 'T का मान लेता है, केवल Func<'T>CreateFromValue वास्तव में एफ # द्वारा extension method के रूप में प्रदान किया जाता है।

यह एक नॉन-ब्रेकिंग तरह से इस पद्धति प्रदान करने के लिए काफी आसान होगा:

static member CreateFromValue(value : 'T) : System.Lazy<'T> = 
    let x = System.Lazy<'T>.Create(fun() -> value) 
    x.Value |> ignore 
    x 

लेकिन यह है कि किसी कारण से नहीं हुआ। शायद यह एक जानबूझकर विकल्प था - मुझे लगता है कि आप इस तरह के परिवर्तन के लिए और दोनों के खिलाफ बहस कर सकते हैं - लेकिन शायद यह एक निरीक्षण था। यदि आप इस प्रकार के ठोस इतिहास को देखते हैं, तो मुझे लगता है कि आप सहमत होंगे कि यह और भी खराब हो सकता है।

4

Lazy<T> कक्षा .NET 4 में ढांचे में जोड़ा गया था। आलसी के लिए एफ # समर्थन एपीआई को .NET 2 पर काम करने की अनुमति देने के लिए एक स्टब का अधिक है, लेकिन इसका उपयोग करते समय वास्तव में आलसी कार्यान्वयन प्रदान नहीं करता है एपीआई।

एफ # कंपाइलर ने इसे .NET 2 संस्करण के लिए own lazy type बनाया है, क्योंकि यह .NET 4 संस्करण की भविष्यवाणी करता है। .NET 2 में, आलसी प्रकार केवल मूल्य को स्पष्ट रूप से सेट करता है, और वास्तव में आलसी नहीं है (source देखें) CreateFromValue का उपयोग करते समय।

इस वजह से, CreateFromValueextension on .NET 4 वास्तव में आलसी है - यह आलसी प्रकार को उस फ़ंक्शन के साथ तत्काल करता है जो मूल्य देता है। .NET 2 पर, internal type is used instead, जो Lazy<'T>.CreateFromValue के एपीआई को पूरा करता है, लेकिन वास्तव में आलसी नहीं है।

+1

यह बस सच नहीं है। एफ # में .NET 2 में "पूरी तरह कार्यात्मक" आलसी थी, लेकिन उस समय ढांचे में कोई 'आलसी' नहीं था, [इसका अपना कार्यान्वयन था] (https://github.com/fsharp/fsharp /blob/84b6da1bfcdc748ba1a79444f70e04708c6d3324/src/fsharp/FSharp.Core/prim-types.fs#L6296)। – scrwtp

+1

'CreateFromValue' को अलग-अलग कार्यान्वित किया गया है, लेकिन @MarkSeemann ने नोट किया है, अगर इसे पहले से मूल्यांकन किया गया है तो इसे शायद ही कभी मूल्यांकन किया जा सकता है। यदि कुछ भी हो, तो एफ # संस्करण वास्तव में अधिक समझ में आता है। – scrwtp

+0

@scrwtp अगर आप .NET 2 में createfromvalue का उपयोग करते हैं, तो यह आलसी नहीं था - मैं पुनः प्रतिक्रिया दूंगा, क्योंकि मैंने इसे खराब लिखा था। –

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

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