lambda - लैम्ब्डा(फ़ंक्शन) क्या है?




language-agnostic computer-science (13)

एक कंप-विज्ञान पृष्ठभूमि के बिना किसी व्यक्ति के लिए, कंप्यूटर विज्ञान की दुनिया में लैम्ब्डा क्या है?


एक कंप-विज्ञान पृष्ठभूमि के बिना किसी व्यक्ति के लिए, कंप्यूटर विज्ञान की दुनिया में लैम्ब्डा क्या है?

मैं इसे सहज और पठनीय पायथन कोड में कदम से सहजता से कदम बताऊंगा।

संक्षेप में, एक लैम्ब्डा सिर्फ एक अज्ञात और इनलाइन फ़ंक्शन है।

चलिए मूल अंकगणितीय की पृष्ठभूमि के साथ एक lambdas रूप में lambdas को समझने के लिए असाइनमेंट से शुरू करते हैं।

असाइनमेंट का ब्लूप्रिंट 'नाम = मान' है, देखें:

In [1]: x = 1
   ...: y = 'value'
In [2]: x
Out[2]: 1
In [3]: y
Out[3]: 'value'

'एक्स', 'वाई' नाम हैं और 1, 'मान' मान हैं। गणित में एक समारोह का प्रयास करें

In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined

त्रुटि रिपोर्ट,
आप सीधे गणित के रूप में गणित नहीं लिख सकते हैं, 'n' को परिभाषित किया जाना चाहिए या किसी मान को असाइन किया जाना चाहिए।

In [8]: n = 3.14
In [9]: m = n**2 + 2*n + 1
In [10]: m
Out[10]: 17.1396

यह अब काम करता है, क्या होगा यदि आप दो अलग-अलग लाइनों को एक से जोड़ने पर जोर देते हैं। lambda आता है

In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>

कोई त्रुटि रिपोर्ट नहीं की गई।

यह lambda में एक नज़र है, यह आपको एक ही पंक्ति में एक फ़ंक्शन लिखने में सक्षम बनाता है जैसा कि आप सीधे कंप्यूटर में गणित में करते हैं।

हम इसे बाद में देखेंगे।

आइए 'असाइनमेंट' पर गहराई से खुदाई करना जारी रखें।

जैसा कि ऊपर दिखाया गया है, बराबर प्रतीक = सरल डेटा (1 और 'मान') प्रकार और सरल अभिव्यक्ति (एन ** 2 + 2 * एन + 1) के लिए काम करता है।

इसे इस्तेमाल करे:

In [15]: x = print('This is a x')
This is a x
In [16]: x
In [17]: x = input('Enter a x: ')
Enter a x: x

यह सरल बयान के लिए काम करता है, उनमें से 11 प्रकार अजगर 7 में हैं । सरल कथन - पायथन 3.6.3 दस्तावेज़ीकरण

यौगिक बयान के बारे में कैसे,

In [18]: m = n**2 + 2*n + 1 if n > 0
SyntaxError: invalid syntax
#or
In [19]: m = n**2 + 2*n + 1, if n > 0
SyntaxError: invalid syntax

def काम करता है इसे काम करने में सक्षम बनाता है

In [23]: def m(n):
    ...:     if n > 0:
    ...:         return n**2 + 2*n + 1
    ...:
In [24]: m(2)
Out[24]: 9

तादा, इसका विश्लेषण करें, 'एम' नाम है, 'एन ** 2 + 2 * एन + 1' मूल्य है। : '=' का एक संस्करण है।
इसे समझें, अगर समझने के लिए, सबकुछ असाइनमेंट से शुरू होता है और सबकुछ असाइनमेंट होता है।

अब lambda लौटें, हमारे पास 'एम' नामक एक समारोह है

प्रयत्न:

In [28]: m = m(3)
In [29]: m
Out[29]: 16

यहां 'एम' के दो नाम हैं, फ़ंक्शन m पहले से ही एक नाम है, डुप्लिकेट किया गया है।

यह स्वरूपण जैसा है:

In [27]: m = def m(n):
    ...:         if n > 0:
    ...:             return n**2 + 2*n + 1
    SyntaxError: invalid syntax

यह एक स्मार्ट रणनीति नहीं है, इसलिए त्रुटि रिपोर्ट

हमें उनमें से एक को हटाना होगा, बिना किसी नाम के फ़ंक्शन सेट करना होगा।

m = lambda n:n**2 + 2*n + 1

इसे 'अज्ञात फ़ंक्शन' कहा जाता है

निष्कर्ष के तौर पर,

  1. एक इनलाइन फ़ंक्शन में lambda जो आपको गणित में एक सीधी रेखा में एक फ़ंक्शन लिखने में सक्षम बनाता है
  2. lambda अज्ञात है

उम्मीद है की यह मदद करेगा।


"लैम्ब्डा" नाम सिर्फ एक ऐतिहासिक आर्टिफैक्ट है। हम जिस बारे में बात कर रहे हैं वह एक अभिव्यक्ति है जिसका मूल्य एक कार्य है।

एक साधारण उदाहरण (अगली पंक्ति के लिए स्कैला का उपयोग करके) है:

args.foreach(arg => println(arg))

जहां foreach विधि के लिए तर्क एक अज्ञात समारोह के लिए एक अभिव्यक्ति है। उपर्युक्त रेखा इस तरह कुछ लिखने के समान ही कम है (बिल्कुल वास्तविक कोड नहीं है, लेकिन आपको विचार मिल जाएगा):

void printThat(Object that) {
  println(that)
}
...
args.foreach(printThat)

सिवाय इसके कि आपको परेशान करने की आवश्यकता नहीं है:

  1. फ़ंक्शन को कहीं और घोषित करना (और जब आप बाद में कोड पर फिर से जाएं तो इसकी तलाश करें)।
  2. कुछ ऐसा नामकरण जो आप केवल एक बार उपयोग कर रहे हैं।

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

int tempVar = 2 * a + b
...
println(tempVar)

केवल उस अभिव्यक्ति को लिखने के बजाय जहां आपको इसकी आवश्यकता है:

println(2 * a + b)

सटीक नोटेशन भाषा से भाषा में भिन्न होता है; यूनानी हमेशा की आवश्यकता नहीं है! ;-)



एक लैम्ब्डा एक प्रकार का फ़ंक्शन है, परिभाषित इनलाइन। लैम्ब्डा के साथ-साथ आपके पास आमतौर पर कुछ प्रकार का चर प्रकार होता है जो किसी फ़ंक्शन, लैम्ब्डा या अन्यथा संदर्भ का संदर्भ रख सकता है।

उदाहरण के लिए, यहां कोड का सी # टुकड़ा है जो लैम्ब्डा का उपयोग नहीं करता है:

public Int32 Add(Int32 a, Int32 b)
{
    return a + b;
}

public Int32 Sub(Int32 a, Int32 b)
{
    return a - b;
}

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, Add);
    Calculator(10, 23, Sub);
}

यह कैलकुलेटर को कॉल करता है, केवल दो संख्याओं के साथ गुजरता है, लेकिन गणना के परिणामों को प्राप्त करने के लिए कैलक्यूलेटर के अंदर कॉल करने की कौन सी विधि।

सी # 2.0 में हमें अज्ञात विधियां मिलीं, जो उपर्युक्त कोड को निम्न प्रकार से कम करती हैं:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a + b;
    });
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a - b;
    });
}

और फिर सी # 3.0 में हमें भेड़ का बच्चा मिला जो कोड को भी छोटा बनाता है:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, (a, b) => a + b);
    Calculator(10, 23, (a, b) => a - b);
}

जावास्क्रिप्ट में, उदाहरण के लिए, कार्यों को एक ही मिश्रित प्रकार के रूप में माना जाता है जैसे कि बाकी सब कुछ ( int , string , float , bool )। इस प्रकार, आप फ्लाई पर फ़ंक्शंस बना सकते हैं, उन्हें चीजों को असाइन कर सकते हैं, और बाद में उन्हें कॉल कर सकते हैं। यह उपयोगी है, लेकिन ऐसा कुछ नहीं जिसे आप उपयोग करना चाहते हैं या आप उन सभी को भ्रमित करेंगे जिन्हें आपके बाद अपना कोड बनाए रखना है ...

यह कुछ कोड है जो मैं यह देखने के लिए खेल रहा था कि यह खरगोश छेद कितना गहरा है:

var x = new Object;
x.thingy = new Array();
x.thingy[0] = function(){ return function(){ return function(){ alert('index 0 pressed'); }; }; }
x.thingy[1] = function(){ return function(){ return function(){ alert('index 1 pressed'); }; }; }
x.thingy[2] = function(){ return function(){ return function(){ alert('index 2 pressed'); }; }; }

for(var i=0 ;i<3; i++)
    x.thingy[i]()()();

थोड़ा oversimplified: एक लैम्ब्डा समारोह वह है जो अन्य कार्यों के लिए पारित किया जा सकता है और यह तर्क का उपयोग किया जाता है।

सी # लैम्ब्डा सिंटैक्स में अक्सर अज्ञात प्रतिनिधियों के समान तरीके से सरल तरीकों से संकलित किया जाता है, लेकिन इसे भी तोड़ दिया जा सकता है और इसका तर्क पढ़ा जा सकता है।

उदाहरण के लिए (सी # 3 में):

LinqToSqlContext.Where( 
    row => row.FieldName > 15 );

LinqToSql उस फ़ंक्शन को पढ़ सकता है (x> 15) और इसे अभिव्यक्ति पेड़ों का उपयोग करके निष्पादित करने के लिए वास्तविक SQL में परिवर्तित कर सकता है।

ऊपर दिया गया बयान बन जाता है:

select ... from [tablename] 
where [FieldName] > 15      --this line was 'read' from the lambda function

यह सामान्य तरीकों या अज्ञात प्रतिनिधियों से अलग है (जो वास्तव में केवल कंपाइलर जादू हैं) क्योंकि उन्हें पढ़ा नहीं जा सकता है

सी # में सभी विधियों का प्रयोग नहीं है जो लैम्ब्डा सिंटैक्स का उपयोग अभिव्यक्ति पेड़ (यानी वास्तविक लैम्ब्डा फ़ंक्शंस) में संकलित किए जा सकते हैं। उदाहरण के लिए:

LinqToSqlContext.Where( 
    row => SomeComplexCheck( row.FieldName ) );

अब अभिव्यक्ति वृक्ष को पढ़ा नहीं जा सकता है - कुछ कॉम्प्लेक्स चेक टूटा नहीं जा सकता है। SQL कथन कहां के बिना निष्पादित होगा, और डेटा में प्रत्येक पंक्ति कुछ SomeComplexCheck माध्यम से रखी जाएगी।

लैम्ब्डा कार्यों को अज्ञात तरीकों से भ्रमित नहीं किया जाना चाहिए। उदाहरण के लिए:

LinqToSqlContext.Where( 
    delegate ( DataRow row ) { 
        return row.FieldName > 15; 
    } );

इसमें एक 'इनलाइन' फ़ंक्शन भी है, लेकिन इस बार यह केवल कंपाइलर जादू है - सी # कंपाइलर इसे स्वत: उत्पन्न नाम के साथ एक नई इंस्टेंस विधि में विभाजित कर देगा।

बेनामी विधियों को पढ़ा नहीं जा सकता है, और इसलिए तर्क का अनुवाद नहीं किया जा सकता है क्योंकि यह लैम्ब्डा कार्यों के लिए कर सकता है।


मुझे भी मिल गया। मैंने इसे जेएस में इस के साथ करने की कोशिश की है:

var addAndMult = function(x) {
        return (function(y) {
            return (function(z) {
                return (x+y)*z; 
                });
            });
        };

यह 2 से 4 जोड़ता है तो परिणाम 6 से परिणाम देता है। हालांकि मुझे कभी-कभी इसे पढ़ना मुश्किल लगता है :(

इसके अलावा मैंने प्रत्येक समारोह के लिए एक दिलचस्प बना दिया है:

var forEach = function(arr) {
            return (function(x) {
            for (var i=0; arr[i]; i++) {
                 x(arr[i]);
             }
        });
    }

foreach ([1,2,3,4,5]) (console.log);

कंसोल पर प्रिंटिंग के मामले में - यह विधि एक सरणी को फिर से सक्रिय करेगी और एक क्रिया करेगी। अब मुझे भी लगता है कि प्रयोगशालाएं शक्तिशाली क्यों हैं।


मुझे लैम्बडा एक्सप्रेशन के चारों ओर अपने सिर को लपेटने में परेशानी है क्योंकि मैं विजुअल फॉक्सप्रो में काम करता हूं, जिसमें मैक्रो प्रतिस्थापन और एक्सेस्क्रिप्ट {} और मूल्यांकन () फ़ंक्शन हैं, जो एक ही उद्देश्य को पूरा करने लगते हैं।

? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");

FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)

औपचारिक लैम्बडास का उपयोग करने के लिए एक निश्चित लाभ है (मुझे लगता है) संकलन-समय की जांच: फॉक्स को तब तक पता नहीं चलेगा जब तक आप टेक्स्ट स्ट्रिंग को तब तक टाइप नहीं करते जब तक कि इसे चलाने की कोशिश न हो जाए।

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


यह एक ऐसा कार्य है जिसका कोई नाम नहीं है। उदाहरण के लिए सी # में आप उपयोग कर सकते हैं

numberCollection.GetMatchingItems<int>(number => number > 5);

5 से अधिक संख्याओं को वापस करने के लिए।

number => number > 5

यहां भेड़ का बच्चा हिस्सा है। यह एक फ़ंक्शन का प्रतिनिधित्व करता है जो पैरामीटर (संख्या) लेता है और एक बूलियन मान देता है (संख्या> 5)। GetMatchingItems विधि संग्रह में सभी वस्तुओं पर इस lambda का उपयोग करता है और मिलान आइटम लौटाता है।


रुबी में लैम्ब्डा का एक उदाहरण निम्नानुसार है:

hello = lambda do
    puts('Hello')
    puts('I am inside a proc')
end

hello.call

निम्नलिखित आउटपुट को जोड़ देगा:

Hello
I am inside a proc

लैम्ब्डा कैलकुलेशन प्रतिस्थापन का एक सतत गणितीय सिद्धांत है। स्कूल गणित में उदाहरण के लिए x+y=5 x−y=1 साथ जोड़ा जाता है। अलग-अलग समीकरणों में हेरफेर करने के तरीकों के साथ-साथ इन दोनों को एक साथ जानकारी देना भी संभव है, बशर्ते पार-समीकरण प्रतिस्थापन तार्किक रूप से किए जाएं। लैम्ब्डा कैलकुस इन प्रतिस्थापन करने के सही तरीके को संहिताबद्ध करता है।

यह देखते हुए कि y = x−1 दूसरे समीकरण का एक वैध पुनर्गठन है, यह: λ y = x−1 अर्थ प्रतीक y लिए प्रतीकों x−1 को प्रतिस्थापित करने वाला फ़ंक्शन है। अब पहले समीकरण में प्रत्येक शब्द के लिए λ y लागू करने की कल्पना करें। यदि कोई शब्द y तो प्रतिस्थापन करें; अन्यथा कुछ भी नहीं। यदि आप कागज पर ऐसा करते हैं तो आप देखेंगे कि λ y कैसे लागू होता है पहला समीकरण सुलभ बनाता है।

यह किसी भी कंप्यूटर विज्ञान या प्रोग्रामिंग के बिना एक जवाब है।

सबसे सरल प्रोग्रामिंग उदाहरण मैं सोच सकता हूं http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works से आता है:

यहां एक स्तरीय फ़ंक्शन को एक अनिवार्य प्रोग्रामिंग भाषा (सी) में परिभाषित किया जा सकता है:

int square(int x)
{
    return x * x;
}

परिवर्तनीय एक्स एक औपचारिक पैरामीटर है जिसे फ़ंक्शन कहा जाता है जब वास्तविक मान को वर्ग के रूप में प्रतिस्थापित किया जाता है। एक कार्यात्मक भाषा (योजना) में एक ही कार्य परिभाषित किया जाएगा:

(define square
  (lambda (x) 
    (* x x)))

यह कई तरीकों से अलग है, लेकिन यह अभी भी औपचारिक पैरामीटर एक्स का उपयोग उसी तरह करता है।

जोड़ा गया: http://imgur.com/a/XBHub

http://imgur.com/a/XBHub


सवाल का औपचारिक रूप से उत्तर दिया गया है, इसलिए मैं इस पर अधिक जोड़ने की कोशिश नहीं करूंगा।

बहुत सरल, अनौपचारिक शब्दों में जो गणित या प्रोग्रामिंग पर बहुत कम या कुछ भी नहीं जानता है, मैं इसे एक छोटी "मशीन" या "बॉक्स" के रूप में समझाऊंगा जो कुछ इनपुट लेता है, कुछ काम करता है और कुछ आउटपुट बनाता है, इसका कोई विशेष नाम नहीं है , लेकिन हम जानते हैं कि यह कहां है और केवल इस ज्ञान से, हम इसका उपयोग करते हैं।

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


सीएस के संदर्भ में एक लैम्ब्डा फ़ंक्शन एक सार गणितीय अवधारणा है जो गणितीय अभिव्यक्ति के प्रतीकात्मक मूल्यांकन की समस्या का सामना करता है। उस संदर्भ में एक लैम्ब्डा फ़ंक्शन लैम्ब्डा शब्द के समान होता है।

लेकिन प्रोग्रामिंग भाषाओं में यह कुछ अलग है। यह कोड का एक टुकड़ा है जिसे "जगह में" घोषित किया गया है, और इसे "प्रथम श्रेणी के नागरिक" के रूप में पारित किया जा सकता है। यह अवधारणा उपयोगी साबित हुई ताकि यह लगभग सभी लोकप्रिय आधुनिक प्रोग्रामिंग भाषाओं में आए ( लम्बा कार्य कभी भी पोस्ट देखें)।





theory