2016-07-17 5 views
7

मैं वर्तमान में Mostly Adequate Guide on functional programming, chapter 2 पढ़ रहा हूं।इस उदाहरण में तर्क कहां गया?

वहाँ, निम्न उदाहरण

var getServerStuff = function(callback) { 
    return ajaxCall(function(json) { 
    return callback(json); 
    }); 
}; 

जो तब में पुनर्संशोधित है दिया जाता है:

var getServerStuff = ajaxCall; 

रिफैक्टरिंग समझा है, लेखक का तर्क है कि

return ajaxCall(function(json) { 
    return callback(json); 
}); 

ही है

return ajaxCall(callback); 

जबकि मैं समझता हूँ कि ajaxCall गुमनाम समारोह की वापसी मान के साथ कहा जाता है (जो callback का सिर्फ वापसी मान है), मैं करने के लिए कैसे पुनर्संशोधित संस्करण काम करने के लिए माना जाता है नहीं है - जहां json तर्क किया चले जाओ? मैं क्या खो रहा हूँ?

+3

'AJAXCall' का उपयोग एक कॉल करने योग्य तर्क लेता है जो स्वयं एक ही तर्क लेता है,' json'। यदि वह कॉलबैक करता है तो एक ही तर्क के साथ एक और फ़ंक्शन कॉल करता है, * इसे उस फ़ंक्शन * द्वारा प्रतिस्थापित किया जा सकता है। – jonrsharpe

+0

यह समान है, हालांकि सटीक समकक्ष नहीं है, जिसे अधिक अनिवार्य भाषाओं में * इनलाइनिंग * कहा जाता है। –

+0

@jonrsharpe वह क्यों है? इसे क्यों बदला जा सकता है? क्या इसके लिए कोई नाम है? –

उत्तर

5

प्रश्न का उत्तर दिया गया है, लेकिन मुझे लगता है कि कुछ बोल्ड और strikethroughs यह बहुत आसान कोड रूपांतरण भी देख सकते हैं। उम्मीद है कि यह उत्तर किसी भी व्यक्ति की मदद करता है जो समस्या को देखने के लिए संघर्ष कर रहा है।


आप लिखना और नरक नहीं लिखेंगे;

var floor = function(x) { return Math.floor(x) } 

इसके बजाय, आप लिखेंगे & hellip;

var floor = Math.floor 

और नरकिप; और यह ठीक उसी तरह काम करेगा । इसे Eta Conversion कहा जाता है और यदि आप इसे दो बार दोहराते हैं, तो आप देखेंगे कि ब्रायन को अधिकतर पर्याप्त मार्गदर्शिका में अपना परिणाम कैसे मिला।

एटा रूपांतरण के बुनियादी नियम यह है:

function(x) { return f(x) } === f

है & hellip; वे पूरी तरह से विनिमेय


होने पर आप

var getServerStuff = function(callback) { 
    return ajaxCall(function(json) { 
    return callback(json) 
    }) 
} 

पहला रूप में है & hellip मूल कोड में उसी तकनीक का उपयोग कर सकते हैं;

return ajaxCall(function(json) { return callback(json) }) 

ईटा रूपांतरण कहता है & hellip;

function(json) { return callback(json) } === callback

तो आइए पहले ईटा रूपांतरण और नरक के परिणामों के साथ पूरे कोड को देखें;

// first step 
var getServerStuff = function(callback) { 
    return ajaxCall(function(json) { 
    returncallback(json) 
    }) 
} 

// eta converts to ... 
var getServerStuff = function(callback) { 
    return ajaxCall(callback) 
} 

इस परिदृश्य को हमें परिचित होना चाहिए। एक और ईटा रूपांतरण हमें अंतिम सरलीकृत रूप में लाएगा।मैं बोल्डिंग एक और बार बोल्ड कर दूंगा ताकि हम इसे बेहतर देख सकें

ईटा रूपांतरण कहता है & hellip;

function(callback) { return ajaxCall(callback) } === ajaxCall
// second step 
var getServerStuff = function(callback) { 
    returnajaxCall(callback) 
} 

// eta converts to ... 
var getServerStuff = ajaxCall 

सभी इरादों और उद्देश्यों के लिए †, वे परस्पर विनिमय कर रहे। एफपी के लिए अधिकतर पर्याप्त मार्गदर्शिका गतिशील बाध्यकारी या this

+2

अरे, आपके उत्तर के लिए धन्यवाद! जबकि मुझे यह समझने में बड़ी समस्याएं थीं, बोल्डिंग/स्ट्राइकथ्रू ने वास्तव में मुझे इसके साथ बहुत मदद की, इसलिए मैंने आपका जवाब स्वीकार कर लिया। यह मुझे सबसे आश्चर्यजनक बात है! – Sven

1

मुद्दा यह है कि

function (json) { 
    return callback(json) 
} 

सिर्फ

callback 

कोई समारोह अभिव्यक्ति किसी भी अधिक है के बराबर है है, इसलिए एक पैरामीटर json के लिए कोई जरूरत नहीं है। अज्ञात फ़ंक्शन को कॉल करने के बजाय (बदले में callback तर्क के साथ कॉल करता है और इसके परिणाम को वापस पास करता है), आप सीधे उसी प्रभाव पर callback पर कॉल कर सकते हैं।

+0

वे कुछ मान्यताओं के तहत केवल समकक्ष हैं। – Oriol

+0

@ ओरियल: यह सामान्य नियम है, जिसे [ईटा कमी] कहा जाता है (https://wiki.haskell.org/Eta_conversion)। – georg

+0

@Oriol: निश्चित रूप से लेख के प्रयोजनों के लिए। हां, स्टैक ऊंचाई पर कॉल करें, 'यह' मान और आगे तर्क निश्चित रूप से भिन्न होते हैं। यह लेख एफपी के बारे में है, हम मान सकते हैं कि 'कॉलबैक' एक असामान्य कार्य है। – Bergi

2

जबकि मैं समझता हूँ कि ajaxCall गुमनाम समारोह की वापसी मान के साथ कहा जाता है (जो कॉलबैक का सिर्फ वापसी मान)

यह पीछे की ओर वास्तव में है।

ajaxCall को एक अज्ञात फ़ंक्शन के साथ तर्क के रूप में बुलाया जाता है। संभवतः यह अंततः उस फ़ंक्शन को कॉल करता है, और वह फ़ंक्शन तब callback पर कॉल करता है।

सभी कार्यों के नाम देने से आम तौर पर यह समझना आसान हो जाता है।

function callback(json) { 
    console.log('I was called with ' + json); 
} 

function intermediate(json) { 
    return callback(json); 
} 

ajaxCall(intermediate); 

यहाँ, ajaxCallintermediate पारित कर दिया जाता है। जब कॉल किया जाता है, intermediate अपना एकल तर्क लेता है और इसे callback पर भेजता है।

यह श्रृंखला एक छोटे से अनावश्यक है और यह करने के लिए सरल किया जा सकता:

function callback(json) { 
    console.log('I was called with ' + json); 
} 

ajaxCall(callback); 

मुझे आशा है कि मदद करता है!

4

यह एक कार्यात्मक रिफैक्टरिंग है और यह चारों ओर एक और तरीका यह स्पष्ट है। कल्पना करें कि आपके पास एक फ़ंक्शन है, ajaxCall जो कॉलबैक फ़ंक्शन लेता है जो परिणाम के साथ लागू होगा उदाहरण के लिए।

ajaxCall(fun); 

आप प्रतिस्थापन के नियमों से function(json){ return fun(json); } साथ fun को बदलने के लिए थे, तो यह ठीक उसी कोड है। इस प्रकार आप लिख सकते हैं:

ajaxCall(function(json){ return fun(json);}); 

जैसे हम fun लिपटे हम ajaxCall लपेट कर सकते हैं, हम fun के लिए एक प्रतिस्थापन के रूप में callback लागू करने और fun तर्क के रूप में देते हैं। प्रतिस्थापन के नियमों से इसकी ठीक उसी कोड:

(function(callback){ 
    return ajaxCall(function(json){ callback(json);}); 
})(fun) 

अब यह एक ही आप मिल गया के रूप में के बाद से मैं वास्तव में मेरी उदाहरण में यह फोन नहीं है, लेकिन आप अपने कोड के साथ एक समानता देख सकते हैं जब हम अलग हो परिभाषा और कॉल:

var getServerStuff = function(callback) { 
    return ajaxCall(function(json){return callback(json);}); 
}; 
getServerStuff(fun); 

आप ajaxCall को बहस में समारोह आवरण की जगह है कि श्रृंखला अपने पाठ विपरीत तरह से यह करता है का पालन कर सकता है:

var getServerStuff = function(callback) { 
    // return ajaxCall(function(json){return callback(json);}); 
    return ajaxCall(callback); 
}; 
getServerStuff(fun); 

और

ajaxCall(fun); 

ये लीजिए: इसलिए हम मूल्य के साथ स्थानापन्न कर सकते हैं

// var getServerStuff = function(callback){ return ajaxCall(callback);} 
var getServerStuff = ajaxCall; 
getServerStuff(fun); 

फिर getServerStuff सिर्फ एक उपनाम है: तो getServerStuff देखकर वास्तव में भी बस कोई अतिरिक्त सुविधाओं के साथ एक आवरण है। ठीक कहां से शुरू किया इसके लिए काम करने के लिए हालांकि आपके द्वारा पेश किए जाने वाले वेरिएबल प्रभावित कोड में उपयोग किए गए चर को छाया नहीं दे सकते हैं और प्रतिस्थापित कार्यों को मूल के समान समानता का समर्थन करना चाहिए। इसके अलावा यह काफी सीधे आगे है।

जिम वीरिच मानक रिफैक्टरिंग नियमों द्वारा रिफैक्टरिंग करके how to do the factorial function using only anonymous functions दिखाता है। यह रूबी में है लेकिन मुझे इसके बाद कोई समस्या नहीं थी। 21:15 पर वह कार्यात्मक रिफैक्टरिंग दिखाता है जो विषय भाग पर महत्वपूर्ण है।

2

getServerStuff एक उच्च ऑर्डर फ़ंक्शन है जो लैम्बडा (अज्ञात फ़ंक्शन) को इसके तर्क के रूप में अपेक्षा करता है (जो स्वयं एक तर्क की अपेक्षा करता है)।

ajaxCall एक उच्च आदेश फ़ंक्शन है जो लैम्ब्डा से अपेक्षा करता है (जो स्वयं एक तर्क की अपेक्षा करता है)।

डेटा (JSON) कहां हैं? आइए विचलित विवरणों को खत्म करें:

const hof = cb => hof2(x => cb(x)); // higher order function that expects a lambda 
const hof2 = cb => cb(); // another HOF that expects a lambda 
const inc = x => x + 1; 
hof(inc); // NaN 

यह व्यर्थ है। फिर, डेटा कहां है? वे एक सर्वर से अतुल्यकालिक रूप से लाए जाते हैं। इसलिए हम अपने कार्यों थोड़ा अनुकूलित करने की आवश्यकता:

const inc = x => console.log(x + 1); 
 
const hof = cb => hof2(x => cb(x)); 
 
const hof2 = cb => setTimeout(cb, 0, 2); // assumed `2` is the result of the async operation 
 
    
 
hof(inc); // 3

अंत में हम एक HOF है कि एक और HOF है कि एक सर्वर से डेटा को हासिल करेगा और उस डेटा को अपने लैम्ब्डा (कॉलबैक) लागू होता है कॉल ।

हम स्पष्ट रूप से इसे और सरल बना सकते हैं।हम सिर्फ एक HOF कि एक लैम्ब्डा कि डेटा की उम्मीद है, जो एक सर्वर द्वारा अतुल्यकालिक रूप से प्रदान की जाती है उम्मीद की जरूरत है:

const inc = x => console.log(x + 1); 
 
const hof2 = cb => setTimeout(cb, 0, 2); // assumed `2` is the result of the async operation 
 
    
 
hof2(inc); // 3

अंतिम पंक्ति ajaxCall(callback) जैसा होता है;

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

पूरक: यदि आपके कोड में सभी कार्य एक जैसे हैं, तो वे वास्तव में एक तर्क की उम्मीद करते हैं, फिर कोई और धर्मार्थ नहीं है - यह सार है। यह कार्य संरचना और पॉइंटफ्री शैली की ओर जाता है, दो विषयों जो अधिकतर पर्याप्त मार्गदर्शिका में वर्णित हैं।

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