2017-05-10 8 views
6

this previous answerसही साइड इफेक्ट ऑर्डर के साथ ओकैमल/एफ # में List.map को पुन: कार्यान्वित करना?

के अनुसार आप List.map इस तरह लागू हो सकते हैं:

let rec map project = function 
    | [] -> [] 
    | head :: tail -> 
     project head :: map project tail ;; 

लेकिन इसके बजाय, इसे इस तरह कार्यान्वित किया जाता है:

let rec map project = function 
    | [] -> [] 
    | head :: tail -> 
     let result = project head in 
     result :: map project tail ;; 

वे कहते हैं कि यह सुनिश्चित करने के लिए इस तरह से किया जाता है अनुमानित क्रम में प्रोजेक्शन फ़ंक्शन को साइड इफेक्ट्स के मामले में बुलाया जाता है, उदाहरण के लिए

map print_int [1;2;3] ;; 

123 प्रिंट चाहिए, लेकिन पहले कार्यान्वयन 321 प्रिंट होगा। हालांकि, जब मैं उन दोनों को ओकैमल और एफ # में स्वयं परीक्षण करता हूं, तो वे बिल्कुल उसी 123 परिणाम उत्पन्न करते हैं।

(ध्यान दें कि मैं OCaml और एफ # REPLs में यह परीक्षण कर रहा हूँ - टिप्पणी में निक पता चलता है यह मेरा पुन: पेश करने में असमर्थता का कारण हो सकता है, लेकिन क्यों)

क्या मैं गलत समझ रहा हूँ? क्या कोई विस्तृत कर सकता है क्यों उन्हें विभिन्न ऑर्डर देना चाहिए और मैं पुन: उत्पन्न कैसे कर सकता हूं? यह अतीत में लिखे गए ओकैमल कोड की मेरी पिछली समझ के विपरीत चलता है, इसलिए यह मेरे लिए आश्चर्यजनक था और मैं यह सुनिश्चित करना चाहता हूं कि गलती दोहराना न पड़े। जब मैं दोनों को पढ़ता हूं, तो मैंने इसे एक बाहरी मध्यस्थ बाध्यकारी के साथ बिल्कुल वही चीज़ के रूप में पढ़ा।

मेरा एकमात्र अनुमान यह है कि विपक्ष का उपयोग कर अभिव्यक्ति मूल्यांकन का क्रम छोड़ने का अधिकार है, लेकिन यह बहुत अजीब लगता है?


यह समझने के लिए OCaml कोड निष्पादित अनुसंधान के रूप में विशुद्ध रूप से किया जा रहा है, मैं वास्तव में मेरे अपने उत्पादन कोड List.map के लिए बनाने की जरूरत नहीं है।

+1

मैं सिर्फ दोनों का परीक्षण किया ओकैमल में 'मानचित्र' के उन कार्यान्वयनों में से क्रमशः आउटपुट के रूप में '321' और' 123' प्राप्त हुआ। क्या आप इन्हें आरईपीएल में चला रहे हैं? –

+0

@NickZuber हाँ मैं हूँ! ओकैमल और एफ # आरईपीएल के साथ-साथ बकलस्क्रिप्ट ऑनलाइन आरईपीएल में परीक्षण किया गया। जब मैं घर जाता हूं तो मैं इसे एक आरईपीएल का उपयोग नहीं करने की कोशिश करूंगा, लेकिन मेरा अगला प्रश्न यह है कि इससे कोई फर्क पड़ता है और फिर भी दोनों बराबर क्यों नहीं हैं :) – jayphelps

+2

ध्यान दें कि 'List.map' का F # कार्यान्वयन FSharp.Core वास्तव में इसे वापस करने से पहले 'सूची' ऑब्जेक्ट बनाने के लिए हुड के नीचे उत्परिवर्तन का उपयोग कर रहा है, इसलिए यह ढेर को ओवरफ़्लो नहीं कर सकता है। ऊपर 'List.map' उदाहरण सभी उदाहरण हैं, और यदि वे उपयोग किए गए थे तो ढेर को ओवरफ़्लो कर देंगे। मुझे नहीं पता कि ओकैमल कार्यान्वयन हुड के तहत क्या कर रहा है, लेकिन यह शायद एक समान चाल का उपयोग करता है ताकि लंबी सूचियों पर ढेर को ओवरफ्लो न किया जा सके। आप लगभग निश्चित रूप से इसे पहले से ही जानते हैं, @ जेप्लेप्स, लेकिन मैंने सोचा कि यह किसी और के लिए उल्लेखनीय है जो बाद में इस प्रश्न में आ सकता है। – rmunn

उत्तर

3

तो तुम इस तरह map के एक कार्यान्वयन है जब:

let rec map f = function 
    | [] -> [] 
    | a::l -> f a :: map f l 

समारोह अनुप्रयोगों (f a) map कॉल के अंतर्गत में से कोई भी आपको उम्मीद थी में क्रमिक रूप से मूल्यांकन किया जाना की गारंटी है। तो आप इस प्रयास करते हुए:

map print_int [1;2;3] 

आप समय उन समारोह अनुप्रयोगों एक विशेष क्रम में निष्पादित नहीं कर रहे थे द्वारा के बाद से उत्पादन

321- : unit list = [();();()] 

मिलता है।

अब जब आप map इस तरह लागू:

let rec map f = function 
    | [] -> [] 
    | a::l -> let r = f a in r :: map f l 

आप रहे समारोह अनुप्रयोगों के लिए मजबूर कर आपको क्योंकि आप स्पष्ट रूप से let r = f a मूल्यांकन करने के लिए एक फोन करना उम्मीद कर रहे हैं में निष्पादित किया जाना है।

तो अब आप जब कोशिश:

map print_int [1;2;3] 

आप

123- : unit list = [();();()] 

क्योंकि आप स्पष्ट रूप से क्रम में समारोह आवेदनों का मूल्यांकन करने के प्रयास कर दिया है मिल जाएगा।

+1

वाह। तो यह एसएमएल से अलग है, है ना? इस पूरे समय मैंने कभी नहीं महसूस किया कि आवेदन मूल्यांकन गैर-निर्धारिती था। ध्यान रहे = उड़ा। – jayphelps

+1

@jayphelps हाँ निश्चित रूप से कुछ गॉच्यिया हैं - जेफरी के पास [डॉक्स के लिए एक महान संदर्भ] है (http://caml.inria.fr/pub/docs/manual-ocaml/expr.html) इस व्यवहार के संबंध में यदि आप इसके बारे में अधिक पढ़ने में रुचि रखते हैं –

+0

"पूरे फ़ंक्शन समाप्त होने तक फ़ंक्शन एप्लिकेशन (जैसे 'fa') निष्पादित नहीं किया जा रहा है" गलत है।'एफ ए' निश्चित रूप से 'मैप' कॉल से पहले मूल्यांकन किया जाता है जिसमें यह शामिल है। मुद्दा यह है कि बाकी सूची में अपने "भाई" 'मानचित्र 'कॉल से पहले इसका मूल्यांकन नहीं किया जा सकता है। –

11

बिंदु यह है कि ओकैम में फ़ंक्शन एप्लिकेशन का क्रम अनिर्दिष्ट है, यह नहीं कि यह कुछ विशिष्ट अवांछित क्रम में होगा।

जब यह अभिव्यक्ति का मूल्यांकन:

project head :: map project tail 

OCaml project head पहले मूल्यांकन करने के लिए अनुमति दी है या यह map project tail पहले मूल्यांकन कर सकते हैं। जो इसे करने का विकल्प चुनता है वह अनिर्दिष्ट है। (सिद्धांत रूप में यह अलग-अलग कॉल के लिए अलग होने के लिए संभवतः स्वीकार्य होगा।) चूंकि आप एक निर्दिष्ट आदेश चाहते हैं, इसलिए आपको let के साथ फ़ॉर्म का उपयोग करने की आवश्यकता है।

तथ्य यह है कि आदेश निर्दिष्ट नहीं है ओकेमल मैनुअल के Section 6.7 में प्रलेखित है।

जिस क्रम में भाव expr, argument1, ..., argumentn मूल्यांकन किया जाता है निर्दिष्ट नहीं है: खंड समारोह आवेदन देखें।

(दावा है कि मूल्यांकन के क्रम अनिर्दिष्ट है कुछ आप परीक्षण कर सकते हैं नहीं है। एक विशेष क्रम के मामलों की कोई संख्या साबित होता है कि इसी क्रम हमेशा चुना जाना जा रहा है।)

+0

मुझे लगता है कि आपने अपना जवाब संपादित किया है, अब यह बहुत बेहतर है लेकिन मैंने पहले ही निक्स स्वीकार कर लिया है। समय निकालने के लिए आपका धन्यवाद! मेरा दिमाग उड़ाया गया था, मुझे नहीं पता था कि ओकैमल एप्लिकेशन eval गैर निर्धारक था। क्या आप पुष्टि कर सकते हैं कि यह एसएमएल से अलग है या नहीं? मैं कसम खाता हूं कि एसएमएल इस पर निर्धारक था .... फिर फिर, मैंने सोचा कि ओकैम भी HAH – jayphelps

+2

(क्षमा करें, मैं अक्सर सबमिट करने के बाद अपने उत्तरों को संपादित करता हूं।) मुझे संदेह है कि आवेदन आदेश * एसएमएल में निर्दिष्ट है, ऐसा लगता है जैसे यह होगा हो। लेकिन मेरे अलावा कोई और अधिक जानकार होगा निश्चित रूप से इसके बारे में आपके नए SO प्रश्न का उत्तर देगा। मुझे यह देखने में दिलचस्पी होगी कि वे क्या कहते हैं। –

+0

मुझे भी! एक बार फिर धन्यवाद! – jayphelps

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