2012-09-20 35 views
6
let inline myfunction x y = ... 

let inline mycurried = myfunction x // error, only functions may be marked inline 

स्पष्ट रूप से inline करीबी कार्यों के लिए असंभव प्रतीत होता है। तो जब भी mycurried कहा जाता है, तो उसे inlined नहीं मिलेगा भले ही myfunctioninlined ठीक है, क्या यह सही है?बिंदु मुक्त फ़ंक्शंस इनलाइन करने में सक्षम था?

तो क्या इसे करीबी फ़ंक्शन की कमी में से एक माना जा सकता है?

उत्तर

5

मुझे लगता है कि आपके सवाल का एक point-free समारोह या inlined जा सकता है या नहीं है।

आपको जो सीमा मिली वह करीबी कार्य की वजह से नहीं है। ध्यान दें कि आपके उदाहरण में करीबी फ़ंक्शन दाएं तरफ है, बाईं तरफ आपके पास पॉइंट-फ्री फ़ंक्शन है।

एफ # केवल कार्यों को इनलाइन होने की अनुमति देता है, न कि स्थिरांक।

मैं सिद्धांत आपको सोच सकता हूं कि इसे एक बग के रूप में माना जा सकता है, यह देखते हुए कि टाइप अनुमान एक (पॉइंट-फ्री) फ़ंक्शन है, लेकिन टॉमस से दुष्प्रभावों के बारे में नोट्स पढ़ें।

जाहिर है जब संकलक बाईं ओर केवल एक पहचानकर्ता यह इस त्रुटि के साथ विफल पर पाता है:

let inline myfunction x y = x + y 

let inline mycurried = myfunction 1 

--> Only functions may be marked 'inline' 

के रूप में ब्रायन ने कहा कि एक समाधान के दोनों किनारों पर एक स्पष्ट पैरामीटर जोड़ने है:

let inline mycurried x = (myfunction 1) x 

लेकिन फिर आपका फ़ंक्शन अब बिंदु-मुक्त नहीं है, यह वही है:

let inline mycurried x = myfunction 1 x 

let inline mycurried<'a> = myfunction 1 

जब सामान्य मापदंडों बाईं ओर स्पष्ट रूप से मौजूद हैं यह संकलित: एक और तरीका है एक स्पष्ट सामान्य पैरामीटर जोड़ने का हो सकता है। यदि आपका जवाब (और अपने downvote) के लिए

Since only functions can be 'inline' this value will be compiled as a function. 

अद्यतन

धन्यवाद टॉमस:

मैं वे त्रुटि संदेश को हटाने और यह एक चेतावनी देते हैं, जैसे कुछ चाहते हैं।

मेरी व्यक्तिगत राय यह एक चेतावनी होनी चाहिए, इसलिए आप जानते हैं कि आपके कोड का अर्थात् अंततः बदल जाएगा, लेकिन फिर यह तय करना है कि क्या करना है।

आप कहते हैं कि इनलाइन "सिर्फ एक अनुकूलन" है लेकिन यह है कि पूरी तरह सच नहीं है:

। बस अपने सभी कार्यों को इनलाइन करने से इष्टतम कोड की गारंटी नहीं मिलती है।

। आप स्थिर बाधाओं का उपयोग करना चाह सकते हैं और फिर आपको इनलाइन का उपयोग करना होगा।

मैं अपने (तरह के) जेनेरिक स्थिरांक को परिभाषित करने में सक्षम होना चाहता हूं, क्योंकि एफ # लाइब्रेरी पहले से ही (यानी जेनेरिकझेरो और जेनेरिकऑन) है। मुझे पता है कि मेरा कोड शुद्ध होगा, इसलिए मुझे परवाह नहीं है कि यह हर बार निष्पादित होता है या नहीं।

+0

ध्यान दें कि _value_ ('x = =' ') से _function_ (' x arg = ... ') से बाध्यकारी को बदलने के लिए फ़ंक्शन का अर्थ बदल सकता है यदि अभिव्यक्ति की गणना करने के लिए उपयोग की जाने वाली अभिव्यक्ति समारोह के कुछ प्रभाव हैं। पहले मामले में, प्रभावों का मूल्यांकन एक बार और दूसरे में किया जाएगा, उनका मूल्यांकन बार-बार किया जाएगा। यदि आप प्रभावों को केवल एक बार मूल्यांकन करना चाहते हैं, तो आप 'इनलाइन' का उपयोग नहीं कर सकते हैं। यदि आप उन्हें कई बार निष्पादित करना चाहते हैं, तो मुझे लगता है कि अतिरिक्त पैरामीटर जोड़ना उचित है। –

+0

एक सामान्य पैरामीटर जोड़ना _very subtle_ है क्योंकि यह अभी भी एक मान जैसा दिखता है, लेकिन यह वास्तव में एक फ़ंक्शन के रूप में व्यवहार करता है (यानी प्रभाव बार-बार मूल्यांकन किया जाता है), इसलिए मैं इसकी अनुशंसा नहीं करता। (इसके अलावा, मुझे पूरा यकीन है कि व्यवहार वास्तव में अनिर्धारित है - यानी संकलक का भविष्य संस्करण प्रत्येक जेनेरिक प्रकार तर्क के लिए केवल एक बार प्रभाव का मूल्यांकन करने का निर्णय ले सकता है)। –

+0

त्रुटि संदेश शुद्ध भाषाओं (जैसे हास्केल) में समझ में नहीं आता है, लेकिन मुझे लगता है कि जब आप इसे अनुकूलित करने के लिए 'इनलाइन' जोड़ते हैं तो आपके प्रोग्राम के व्यवहार को गलती से बदलने से रोकना एक बहुत अच्छा निर्णय है। –

4

मुझे लगता है कि तुम सिर्फ दोनों पक्षों के लिए एक स्पष्ट पैरामीटर जोड़ने के लिए (हालांकि मैं प्रयास नहीं किया है) की जरूरत है:

let inline myfunction x y = ... 

let inline mycurried y = myfunction 42 y // or whatever value (42) 
2

कंपाइलर केवल inline को फ़ंक्शन को परिभाषित करने वाले बाइंडिंग पर अनुमति देता है। यह अनिवार्य रूप से वही बात है जो with F# value restriction हो रहा है (और also here देखें)। जैसा कि ब्रायन कहते हैं, आप आसानी से अपने फ़ंक्शन में पैरामीटर जोड़ कर इसे हल कर सकते हैं।

यह प्रतिबंध क्यों मौजूद है? यदि यह वहां नहीं था, तो inline जोड़ना आपके कार्यक्रमों का अर्थ बदल देगा और यह बुरा होगा!

let createCounter n = 
    let state = ref n 
    (fun() -> incr state; !state) 

अब निम्नलिखित कोड,:

let counter = createCounter 0 

... बनाता

उदाहरण के लिए, अगर आप इस तरह एक समारोह (जो परिवर्तनशील राज्य बनाता है और एक काउंटर फ़ंक्शन) है कहना एक वैश्विक कार्य जिसे आप कई बार उपयोग कर सकते हैं (counter() पर कॉल करें) और यह आपको 1 से शुरू होने वाले अद्वितीय पूर्णांक देगा। यदि आप इसे inline:

पर चिह्नित कर सकते हैं

... फिर हर बार जब आप counter() का उपयोग करते हैं, तो संकलक को createCounter 0() के साथ प्रतिस्थापित करना चाहिए और इसलिए जब भी आप काउंटर को कॉल करेंगे तो आपको 1 मिल जाएगा!

+0

आप सही हैं। असल में आप इसे बताई गई चाल के रूप में संकलित कर सकते हैं: इनलाइन काउंटर <'a> = ...... ...... फिर भी मैं संकलन त्रुटि की तुलना में एक चेतावनी पसंद करूंगा और वर्कअराउंड/चाल पर निर्भर रहूंगा। – Gustavo

+0

@ गुस्तावो मुझे लगता है कि एक कंपाइलर त्रुटि प्राप्त करने के लिए उचित है, जब इनलाइनिंग (जो वास्तव में केवल एक अनुकूलन है) आपके कोड के अर्थशास्त्र को बदल देगा। त्रुटि सिर्फ आपको बताती है कि संकलक _cannot_ इनलाइन मान (और यह बहुत अच्छी समझ में आता है)। यदि आप एक फ़ंक्शन में मान बदलना चाहते हैं (और कर सकते हैं), तो यह अच्छा है कि आपको इसे स्पष्ट रूप से करना है, क्योंकि आपको यह सोचना है कि यह आपको वह अर्थ देता है जो आप चाहते हैं। –

+0

@ गुस्तावो और हाँ, यदि आप 'इनलाइन काउंटर <'T> = createCounter 0' लिखते हैं और मुझे लगता है कि यह बुरा है तो आप कोड संकलित कर सकते हैं। इसका मतलब यह है कि जब आप 'काउंटर <_>()' कहते हैं तो आपको हमेशा '1' मिल जाएगा और यह इच्छित व्यवहार नहीं है। –