फ़ंक्शन संरचना (कंप्यूटर विज्ञान)

From Vigyanwiki

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

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

फ़ंक्शन को सरलता से संयोजित करने की क्षमता रखरखाव और कोड के पुन: उपयोग के लिए फैक्टरिंग सबरूटीन्स को प्रोत्साहित करती है। अधिक सामान्यतः, संपूर्ण प्रोग्रामों का संयोजन करके बड़े सिस्टम निर्मित किए जा सकते हैं।

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

फ़ंक्शन कॉल कंपोज़ करना

उदाहरण के लिए, मान लीजिए हमारे पास दो फ़ंक्शन f और g, z = f(y) और y = g(x). के रूप में हैं। उन्हें लिखने का तात्पर्य है कि हम पहले y = g(x) की गणना करते हैं और पुनः z = f(y) उपयोग करके y की गणना करते हैं। यहाँ C प्रोग्रामिंग लैंग्वेज में उदाहरण दिया गया है:

float x, y, z;
// ...
y = g(x);
z = f(y);

यदि हम मध्यवर्ती परिणाम को कोई नाम नहीं देते हैं तो भिन्न-भिन्न चरणों को कम्पोज़ किया जा सकता है:

z = f(g(x));

लंबाई में अंतर के बाद भी, ये दोनों फंक्शन एक ही परिणाम की गणना करते हैं। दूसरे कार्यान्वयन के लिए कोड के केवल एक पंक्ति की आवश्यकता होती है और इसे बोलचाल की भाषा में "हाईली कम्पोज़" रूप कहा जाता है। उच्चतर संयुक्त रूपों का एक लाभ है पठनीयता और इससे आरक्षणीयता, क्योंकि इनमें कम कोड लाइनों की आवश्यकता होती है, जो किसी प्रोग्राम की "सरफेस एरिया" को कम करता है।[1] डेमार्को और लिस्टर अनुभवजन्य रूप से सरफेस एरिया और रखरखाव के मध्य एक विपरीत संबंध को सत्यापित करते हैं।[2] दूसरी ओर, अत्यधिक कम्पोज़ फॉर्म का अति प्रयोग संभव हो सकता है। अत्यधिक फ़ंक्शंस के नेस्टिंग का विपरीत प्रभाव हो सकता है, जिससे कोड कम रखरखाव योग्य हो जाता है।

स्टैक-आधारित लैंग्वेज में, फंक्शनल कंपोज़िशन और भी अधिक स्वाभाविक है: यह संयोजन द्वारा किया जाता है, जो सामान्यतः प्रोग्राम डिज़ाइन की प्राथमिक विधि है। फोर्थ प्रोग्रामिंग लैंग्वेज में निम्नलिखित उदाहरण प्रदर्शित किया गया है:

g f

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

फ़ंक्शन कंपोज़िशन का नामकरण

अब मान लीजिए कि g() के परिणाम पर f() को कॉल करने का संयोजन प्रायः उपयोगी होता है, और जिसे हम foo() नाम देना चाहते हैं जिससे इसे स्वयं में एक फ़ंक्शन के रूप में उपयोग किया जा सके।

अधिकांश लैंग्वेजं में, हम रचना द्वारा कार्यान्वित एक नए फ़ंक्शन को परिभाषित कर सकते हैं। C लैंग्वेज में उदाहरण:

float foo(float x) {
    return f(g(x));
}

फोर्थ प्रोग्रामिंग लैंग्वेज में उदाहरण

: foo g f ;

सी प्रोग्रामिंग लैंग्वेज जैसे लैंग्वेजं में, एक नया फ़ंक्शन बनाने की एकमात्र विधि इसे प्रोग्राम सोर्स में परिभाषित करना है, जिसका अर्थ है कि फ़ंक्शन को रन टाइम पर नहीं बनाया जा सकता है। यद्यपि, पूर्वनिर्धारित फ़ंक्शन के यादृच्छिक संरचना का मूल्यांकन संभव है:

#include <stdio.h>

typedef int FXN(int);

int f(int x) { return x+1; }
int g(int x) { return x*2; }
int h(int x) { return x-3; }

int eval(FXN *fs[], int size, int x)
{
   for (int i=0; i<size; i++) x = (*fs[i])(x);

   return x;
}

int main()
{
   // ((6+1)*2)-3 = 11
   FXN *arr[] = {f,g,h};
   printf("%d\n", eval(arr, 3, 6));

   // ((6-3)*2)+1 = 7
   arr[2] = f;  arr[0] = h;
   printf("%d\n", eval(arr, 3, 6));
}


फर्स्ट-क्लास कंपोज़िशन

कार्यात्मक प्रोग्रामिंग लैंग्वेज में, फ़ंक्शन कंपोज़िशन को स्वाभाविक रूप से उच्च-क्रम फ़ंक्शन या ऑपरेटर के रूप में व्यक्त किया जा सकता है। अन्य प्रोग्रामिंग लैंग्वेजं में आप फ़ंक्शन कंपोज़िशन निष्पादित करने के लिए अपना स्वयं का प्रोग्राम लिख सकते हैं।

हास्केल

हास्केल में, उदाहरण foo = f  ∘  g को निम्नलिखित रूप में प्रदर्शित किया गया है:

foo = f . g

बिल्ड-इन कंपोजिशन ऑपरेटर (.) का उपयोग करके जिसे जी आफ्टर एफ या जी कॉम्पोजड ऑफ एफ के रूप में पढ़ा जा सकता है।

कंपोजिशन ऑपरेटर  ∘   को लैम्ब्डा कैलकुलस का उपयोग करके हास्केल में परिभाषित किया जा सकता है:

(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)

पहली पंक्ति में, (.) के टाइप का विवरण है - यह एक फ़ंक्शन (f, g का युग्म) लेता है और एक फ़ंक्शन (दूसरी पंक्ति में दिए गए लैम्बडा अभिव्यक्ति) वापस करता है।

हैस्केल में ध्यान दें कि f और g के उपयुक्त इनपुट और आउटपुट टाइप का निर्देशन आवश्यक नहीं है; a, b, c और x प्लेसहोल्डर हैं; केवल f, g के मध्य संबंध आवश्यक है। यह (.) को एक पॉलीमोर्फिक ऑपरेटर बनाता है।

लिस्प

लिस्प प्रोग्रामिंग लैंग्वेज के विभिन्न प्रकार, विशेषकर स्कीम, कोड और डेटा के परिवर्तन और फ़ंक्शनों के व्यवहार का साथ स्वचलन रूप से वारिएडिक संयोजन ऑपरेटर की एक पुनरावृत्ति परिभाषा के लिए अत्यंत उपयुक्त होते हैं।

(define (compose . fs)
  (if (null? fs) (lambda (x) x) ; if no argument is given, evaluates to the identity function
      (lambda (x) ((car fs) ((apply compose (cdr fs)) x)))))

; examples
(define (add-a-bang str)
  (string-append str "!"))

(define givebang
  (compose string->symbol add-a-bang symbol->string))

(givebang 'set) ; ===> set!

; anonymous composition
((compose sqrt negate square) 5) ; ===> 0+5i


एपीएल

एपीएल के कई उपलैंग्वेजं में बिल्ट-इन फ़ंक्शन संयोजन एक विशेषता के रूप में सिम्बल का उपयोग करते हैं। यह हायर-आर्डर फ़ंक्शन फ़ंक्शन कंपोज़िशन को बाईं ओर के फ़ंक्शन के अनुप्रयोग तक विस्तारित करता है जैसेA f∘g B का विस्तार A f g B है। .

foofg

इसके अतिरिक्त, आप फ़ंक्शन कंपोज़िशन को परिभाषित कर सकते हैं:

o{⍺⍺ ⍵⍵ }

ऐसी सब-लैंग्वेज में जो ब्रेसिज़ का उपयोग करके इनलाइन परिभाषा का समर्थन नहीं करती है, पारंपरिक परिभाषा उपलब्ध है:

 r(f o g)x
  rf g x


राकू

हास्केल की तरह राकू में एक इन-बिल्ड फ़ंक्शन कंपोज़िशन ऑपरेटर है, मुख्य अंतर यह है कि इसे इस प्रकार या o. लिखा जाता है

my &foo = &f  &g;

इसके अतिरिक्त हास्केल की तरह आप ऑपरेटर को स्वयं परिभाषित कर सकते हैं। वास्तव में निम्नलिखित राकू कोड है जिसका उपयोग रेकुडो फंक्शन में इसे परिभाषित करने के लिए किया जाता है।

# the implementation has a slightly different line here because it cheats
proto sub infix:<∘> (&?, &?) is equiv(&[~]) is assoc<left> {*}

multi sub infix:<∘> () { *.self } # allows `[∘] @array` to work when `@array` is empty
multi sub infix:<∘> (&f) { &f }   # allows `[∘] @array` to work when `@array` has one element
multi sub infix:<∘> (&f, &g --> Block) {
    (&f).count > 1
    ?? -> |args { f |g |args }
    !! -> |args { f g |args }
}

# alias it to the "Texas" spelling ( everything is bigger, and ASCII in Texas )
my &infix:<o> := &infix:<∘>;


पायथन

पायथन में, फ़ंक्शंस के किसी भी समूह के लिए स्ट्रक्चर को परिभाषित करने की एक विधि, फ़ोल्ड फ़ंक्शन का उपयोग करना है (पायथन 3 में फनटूल.रीडूस का उपयोग करें):

# Available since Python v2.6
from functools import reduce

def compose(*funcs) -> int:
    """Compose a group of functions (f(g(h(...)))) into a single composite func."""
    return reduce(lambda f, g: lambda x: f(g(x)), funcs)

# Example
f = lambda x: x + 1
g = lambda x: x * 2
h = lambda x: x - 3

# Call the function x=10 : ((x-3)*2)+1 = 15
print(compose(f, g, h)(10))


जावास्क्रिप्ट

जावास्क्रिप्ट में हम इसे एक फ़ंक्शन के रूप में परिभाषित कर सकते हैं जो दो फ़ंक्शन f और g लेता है, और एक फ़ंक्शन उत्पन्न करता है:

function o(f, g) {
    return function(x) {
        return f(g(x));
    }
}

// Alternatively, using the rest operator and lambda expressions in ES2015
const compose = (...fs) => (x) => fs.reduceRight((acc, f) => f(acc), x)


सी#

C# में हम इसे एक एक्सटेंशन विधि के रूप में परिभाषित कर सकते हैं जो Funcs f और g लेता है, और एक नया Func तैयार करता है:

// Call example:
//   var c = f.ComposeWith(g);
//
//   Func<int, bool> g = _ => ...
//   Func<bool, string> f = _ => ...

public static Func<T1, T3> ComposeWith<T1, T2, T3>(this Func<T2, T3> f, Func<T1, T2> g) => x => f(g(x));


रूबी

रूबी जैसी लैंग्वेज आपको स्वयं एक बाइनरी ऑपरेटर निर्मित करने देती हैं:

class Proc
  def compose(other_fn)
    ->(*as) { other_fn.call(call(*as)) }
  end
  alias_method :+, :compose
end

f = ->(x) { x * 2 }
g = ->(x) { x ** 3 }
(f + g).call(12) # => 13824

यद्यपि, रूबी 2.6 में एक मूल फ़ंक्शन कंपोज़िशन ऑपरेटर प्रस्तुत किया गया था:[3]

f = proc{|x| x + 2}
g = proc{|x| x * 3}
(f << g).call(3) # -> 11; identical to f(g(3))
(f >> g).call(3) # -> 15; identical to g(f(3))


अनुसंधान सर्वेक्षण

कंपोज़िशन और कंपोज़िशन के सिद्धांत सहित कंपोज़िशन की धारणाएं इतनी सर्वव्यापी हैं कि अनुसंधान के कई पहलू भिन्न-भिन्न विकसित हुए हैं। निम्नलिखित उस प्रकार के शोध का एक प्रारूप है जिसमें कंपोज़िशन की धारणा केंद्रीय है।

  • स्टील (1994) हास्केल में 'मोनैड' के रूप में जाने जाने वाले बिल्डिंग ब्लॉक्स के संयोजन में फ़ंक्शन कंपोज़िशन को सीधे लागू किया जाता है।
  • मेयर (1988) ने कंपोजिबिलिटी के संदर्भ में कोड के पुन: उपयोग की समस्या को संबोधित किया।
  • अबाड़ी & लैंपोर्ट (1993) औपचारिक रूप से फंक्शनल कम्पोजीशन के लिए एक प्रमाण नियम परिभाषित किया गया है जो प्रोग्राम की सुरक्षा और जीवंतता का आश्वासन देता है।
  • राच (2001) इसे कम्प्यूटेशनल सांकेतिकता प्रणाली में रखकर और कम्प्यूटेशनल भाषाविज्ञान में प्रायः सामने आने वाली कम्पोजीशनल अस्पष्टता की समस्या पर लागू करके कम्पोजीशन के एक शक्तिशाली रूप की पहचान की।
  • वैन गेलडर & पोर्ट (1993) नेचुरल लैंग्वेज प्रसंस्करण के अनुरूप पहलुओं में कम्पोजीशन की भूमिका की जांच की गई।
  • गिब्बंस (2002) द्वारा एक समीक्षा के अनुसार, कम्पोजीशन का औपचारिक उपचार जावा लैंग्वेज के लिए आईबीएम की विज़ुअल एज जैसी विजुअल प्रोग्रामिंग लैंग्वेजं में कॉम्पोनेन्ट असेंबली के सत्यापन को रेखांकित करता है।

लार्ज-स्केल कम्पोजीशन

संपूर्ण प्रोग्राम या सिस्टम को फ़ंक्शंस के रूप में माना जा सकता है, जिसे यदि उनके इनपुट और आउटपुट उपयुक्त रूप से परिभाषित हों तों इन्हे सरलता से बनाया जा सकता है। [4] फ़िल्टर के सरल कम्पोजीशन की अनुमति देने वाली सॉफ्टवेयर पाइपलाइन इतनी सफल रहीं कि वे ऑपरेटिंग सिस्टम की सॉफ्टवेयर पाइपलाइन बन गईं।

इम्पेरटिव प्रोसीजर जो साइड इफ़ेक्ट्स का उल्लंघन करती हैं, संदर्भात्मक पारदर्शिता का उल्लंघन करती हैं और इसलिए उपयुक्त रूप से कम्पोसिबल नहीं होतीं। यद्यपि, यदि कोड चलाने से पहले और बाद में "स्टेट ऑफ द वर्ल्ड" को इसके इनपुट और आउटपुट के रूप में माना जाए, तो एक क्लीन फ़ंक्शन मिलता है। ऐसे फलनों के कम्पोजीशन प्रक्रियाओं को एक के बाद एक चलाने के समान होती है। मोनाड औपचारिकता इस विचार का उपयोग साइड इफेक्ट्स और इनपुट/आउटपुट (आई/ओ) को फंक्शनल लैंग्वेज में सम्मिलित करने के लिए करती है।

यह भी देखें

टिप्पणियाँ

  1. Cox (1986), pp. 15–17
  2. DeMarco & Lister (1995), pp. 133–135.
  3. "Ruby 2.6.0 Released". www.ruby-lang.org. Retrieved 2019-01-04.
  4. Raymond (2003)


संदर्भ