2010-08-24 18 views
16

यह एक बहुत ही सरल सवाल है, और मैं सिर्फ यह जांचना चाहता था कि मैं क्या कर रहा हूं और मैं एफ # की व्याख्या कैसे कर रहा हूं। अगर मैं बयानएफ # कार्य बनाम मूल्य

let printRandom = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 
इसके बजाय एक समारोह के रूप printRandom बनाने की

है, एफ # यह एक बार चलाता है और फिर इसे एक मूल्य प्रदान करती है। तो, अब, जब मैं प्रिंट यादृच्छिक मूल्य कहता हूं, तो एक नया यादृच्छिक मूल्य प्राप्त करने और इसे प्रिंट करने के बजाय, मुझे बस पहली बार जो कुछ भी लौटाया जाता है उसे प्राप्त करें। मैं इस के आसपास मिल सकता है मेरी इस तरह के रूप में यह परिभाषित करने:

let printRandom() = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

इस पैरामीटर कम कार्य करता है और मूल्यों के बीच इस तरह के अंतर आकर्षित करने के लिए उचित तरीका है? यह मेरे लिए आदर्श से कम लगता है। क्या इसका करी, रचना, आदि में परिणाम हैं?

+2

ध्यान दें कि आप लगभग निश्चित रूप से 'x' की पहली घटना के सामने 'लेट' जोड़ना चाहते हैं - अन्यथा आप तुलना कर रहे हैं और फिर परिणाम निकाल रहे हैं। – kvb

+0

बहुत बढ़िया सवाल, * सटीक * एक ही समस्या थी। दुर्भाग्य से मैंने समाधान की खोज के बाद यह पाया। – ses011

उत्तर

18

यह देखने का सही तरीका यह है कि F # में पैरामीटर-कम फ़ंक्शंस जैसी कोई चीज़ नहीं है। सभी कार्यों को एक पैरामीटर लेना पड़ता है, लेकिन कभी-कभी आपको परवाह नहीं है कि यह क्या है, इसलिए आप () (टाइप यूनिट के सिंगलटन मान) का उपयोग करते हैं।

let printRandom unused = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

या इस:

let printRandom _ = 
    x = MyApplication.getRandom() 
    printfn "%d" x 
    x 

लेकिन () डिफ़ॉल्ट तरीका व्यक्त करने के लिए है कि आप पैरामीटर का उपयोग नहीं करते है आप भी इस तरह एक समारोह बना सकता है। यह उस तथ्य को कॉलर को व्यक्त करता है, क्योंकि प्रकार unit -> int'a -> int नहीं है; साथ ही पाठक के लिए, क्योंकि कॉल साइट printRandom()printRandom "unused" नहीं है।

वास्तव में करी और रचना वास्तव में इस तथ्य पर निर्भर करती है कि सभी कार्य एक पैरामीटर लेते हैं और एक मान वापस करते हैं।

यूनिट के साथ कॉल लिखने का सबसे आम तरीका, एक जगह के साथ है, खासकर एफ # जैसे कैमरे, एसएमएल और हास्केल के गैर .NET रिश्तेदारों में। ऐसा इसलिए है क्योंकि () एक सिंगलटन मान है, सिंटैक्टिक चीज नहीं है जैसे कि यह सी # में है।

8

आपका विश्लेषण सही है।

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

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

दूसरा दृष्टिकोण एक ऐसा फ़ंक्शन बनाने का मानक तरीका है जो तर्कसंगत रूप से कोई तर्क नहीं लेता है। मुझे इस घोषणा के लिए एफ # टीम का उपयोग करने वाली सटीक शब्दावली नहीं पता है (शायद एक समारोह unit प्रकार का एक तर्क ले रहा है)। इसलिए मैं वास्तव में इस पर टिप्पणी नहीं कर सकता कि यह करी को कैसे प्रभावित करेगा।

+4

करीई वास्तव में यहां लागू नहीं होती है क्योंकि फ़ंक्शन में केवल 'पैरामीटर' होता है, प्रकार 'इकाई' टाइप करें। आंशिक आवेदन समझ में नहीं आता है: आप या तो फ़ंक्शन को पूरी तरह लागू करते हैं ('()' गुजरते हैं), या आप इसे बिल्कुल कॉल नहीं करते हैं। –

7

इस पैरामीटर कम कार्यों और मूल्यों के बीच इस अंतर करने की बात उचित तरीका है? यह मेरे लिए आदर्श से कम लगता है। क्या करी, संरचना, आदि में परिणाम हैं?

हां, आप जो वर्णन करते हैं वह सही है।

इसके लायक होने के लिए, यह एक बहुत ही रोचक परिणाम है जो घोषणा पर कार्यों का आंशिक रूप से मूल्यांकन करने में सक्षम है। इन दोनों कार्यों की तुलना करें:

// val contains : string -> bool 
let contains = 
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"] 
    fun person -> people.Contains(person) 

// val contains2 : string -> bool 
let contains2 person = 
    let people = set ["Juliet"; "Joe"; "Bob"; "Jack"] 
    people.Contains(person) 

दोनों कार्यों समान परिणाम, contains अपने लोगों घोषणा पर सेट contains2 अपने लोगों सेट हर आप फ़ंक्शन को कॉल बनाता है जबकि बनाता है और यह पुनः उपयोग कर लेता,। अंतिम परिणाम: contains थोड़ा तेज़ है। तो यहां भेद जानने के लिए आप तेजी से कोड लिखने में मदद कर सकते हैं।

3

कार्य निकायों की तरह लगने वाले असाइनमेंट निकायों ने कुछ प्रोग्रामर को अनजान माना है। आप काम के एक समारोह वापसी होने से और भी दिलचस्प बातें कर सकते हैं:

let foo = 
    printfn "This runs at startup" 
    (fun() -> printfn "This runs every time you call foo()") 

मैं सिर्फ http://blog.wezeku.com/2010/08/23/values-functions-and-a-bit-of-both/ पर इसके बारे में एक ब्लॉग पोस्ट में लिखा था।

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