2012-10-30 28 views
8

क्या ये कार्य बिल्कुल समान हैं? यही है, अंतिम वाक्यविन्यास के लिए पहला और दूसरा वाक्यविन्यास सिर्फ सुविधाजनक शॉर्टेंड है? या क्या कुछ सैद्धांतिक या व्यावहारिक अंतर है, और यदि हां, तो यह क्या है?इन कार्यों के बीच क्या अंतर है

let f1 a b = a + b

let f2 a = (fun b -> a + b)

let f3 = (fun a -> (fun b -> a + b))

वे मेरे लिए एक ही लगता है, f1 5, f2 5 और f3 5, समान मान देने के लिए उदाहरण के लिए लग रहे हैं। बस जांच कर रहा हूं कि मैं यहां अवैध धारणा नहीं बना रहा हूं। दूसरे शब्दों में, मुझे आशा है कि ज्ञान आधारित उत्तर, कोई भी नहीं कहता "हाँ, मुझे विश्वास है कि वे वही हैं"।

+2

[मेरा जवाब यहां देखें] (http://stackoverflow.com/questions/2175940/int-int-int-what-does-this-mean-in-f/2176428#2176428), आपको समझने में मदद कर सकता है अंतर –

+0

मैंने उत्तर से तीसरे मामले को रखने के लिए प्रश्न बढ़ाया। – hyde

उत्तर

8

आपकी धारणा सही है, इस मामले में, कार्य बिल्कुल वही हैं।

आप जेनरेट किए गए आईएल कोड (जैसा कि क्रेग द्वारा दिखाया गया है) का निरीक्षण करके देख सकते हैं और आप यह भी देख सकते हैं कि एफ # कंपाइलर द्वारा अनुमानित प्रकार को देखकर। दोनों मामलों में, आप int -> int -> int देखेंगे। एफ # भाषा का विचार है कि एक समारोह के रूप में int लेता है और int -> int देता है लेकिन यह वास्तव में कई तर्कों (दक्षता के लिए) के साथ एक विधि के रूप में संकलित किया जाता है।

आप fun लिखने के तुरंत बाद let .. = तो संकलक बदल जाता है एक मानक समारोह में कि। हालांकि, अगर आप यदि आप समारोह लौटने से पहले कुछ गणना कर कोड है कि थोड़ी-सी अलग है लिख सकते हैं:

let f1 a b = printfn "hi"; a + b 
let f2 a = printfn "hi"; (fun b -> a + b) 

अब दो कार्य बहुत अलग हैं, क्योंकि एक दूसरे प्रिंट "नमस्ते" जब आप यह सिर्फ एक देना

> let f = f2 1;; 
hi      // The body is called, prints 
val f : (int -> int) // and returns function 

> f 2;;     // This runs the body of 'fun' 
val it : int = 3  // which performs the additiion 

आप एक ही कोड f1 का उपयोग कर लिख सकते हैं, लेकिन पहले आदेश सिर्फ एक नया कार्य पैदा करेगा और दूसरा आदेश प्रिंट "नमस्ते" होगा: एकल तर्क (और फिर इसे एक समारोह है कि आप कॉल कर सकते हैं देता है) और जोड़ो।

इस मामले में, f2 के लिए जेनरेट किया गया आईएल कोड अलग होगा। यह एक ऐसा कार्य होगा जो एक फ़ंक्शन (प्रकार FSharpFunc<int, int>) देता है। एफ # द्वारा प्रदर्शित प्रकार भी अलग है - int -> int -> int के बजाय यह int -> (int -> int) होगा। आप इन दो प्रकारों के मूल्यों का बिल्कुल उसी तरीके से उपयोग कर सकते हैं, लेकिन यह आपको संकेत देता है कि जब आप इसे एक ही तर्क देते हैं तो पहला प्रभाव कुछ प्रभाव डाल सकता है।

5

यहाँ f1 के लिए आईएल है:

.method public static int32 f1(int32 a, 
           int32 b) cil managed 
{ 
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = (01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00) 
    // Code size  5 (0x5) 
    .maxstack 4 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: ldarg.1 
    IL_0003: add 
    IL_0004: ret 
} // end of method Program::f1 

... और के लिए f2:

.method public static int32 f2(int32 a, 
           int32 b) cil managed 
{ 
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = (01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00) 
    // Code size  5 (0x5) 
    .maxstack 4 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: ldarg.1 
    IL_0003: add 
    IL_0004: ret 
} // end of method Program::f2 

आप देख सकते हैं, यह अनिवार्य रूप से समान है, तो हाँ, वे एक ही कर रहे हैं।

+0

क्या यह वास्तव में प्रासंगिक है कि वे कुछ परीक्षण मामले के लिए एक ही बाइट कोड उत्पन्न करते हैं? इससे कोई फर्क नहीं पड़ता कि आप फ़ंक्शन का उपयोग कैसे करते हैं, क्या यह हमेशा अंत में उस "असली" विधि को कॉल करना समाप्त करता है जब अंत में यह फ़ंक्शन के साथ कुछ करता है? – hyde

+0

हां यह ऐसा करता है। टॉमस ने क्यों समझाया। –

5

दो कार्य समान हैं। उन्हें

let f = fun a -> fun b -> a + b 

के लिए वाक्य रचनात्मक शर्करा के रूप में माना जा सकता है। इसमें थोड़ा व्यावहारिक अंतर है।f1 जोर देता है कि फ़ंक्शन एक मान देता है जबकि f2 एक बंदरगाह देता है, जो बदले में एक मूल्य उत्पन्न करता है। f2 का उपयोग संयोजक बनाने में थोड़ा अधिक आकर्षक है उदा। parser combinators

एक तरफ ध्यान दें, एफ #और f2 5 में फ़ंक्शंस पर कोई समानता नहीं है, लेकिन वे समान इनपुट पर समान आउटपुट उत्पन्न करते हैं।

+0

+1 मुझे लगता है कि यह एक उपयोगी उत्तर है और एफ # को समझने का अच्छा तरीका है। हालांकि तकनीकी रूप से बोलते हुए, वे 'चलो fab = ...' के लिए सिंटैक्टिक शर्करा दोनों हैं क्योंकि एफ # (और अन्य एमएल भाषाएं) 'चलो' और 'मजेदार' का उपयोग करके परिभाषित कार्यों का इलाज करती हैं ('चलो' का उपयोग करके परिभाषित कार्यों सामान्य और कार्य हो सकते हैं 'मजेदार' का उपयोग नहीं कर सकते हैं)। इस कोड को इस तरह माना जाता है कि यह 'let f a b = ...' का उपयोग कर रहा था जब तक कि किसी भी अन्य कोड के बिना शरीर में 'मजेदार' होता है। –

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