डायलन (प्रोग्रामिंग भाषा)

From Vigyanwiki
Dylan
File:Dylan logo.png
Paradigmmulti-paradigm: functional, object-oriented
DeveloperOpen Source Community Apple Computer, Harlequin, Carnegie Mellon University
पहली प्रस्तुति1992; 32 years ago (1992)
Stable release
2022.1 / November 28, 2022; 2 years ago (2022-11-28)
टाइपिंग अनुशासनStrong, gradual
प्लेटफॉर्मIA-32, x86-64
ओएसCross-platform
फ़ाइल नाम एक्सटेंशनएसdylan, lid
वेबसाइटopendylan.org
Major implementations
Open Dylan, Gwydion Dylan
Dialects
infix-dylan (AKA Dylan), prefix-dylan (historical only)
Influenced by
CLOS, ALGOL, Scheme, EuLisp
Influenced
Lasso, Python, Ruby, Julia[1]

डायलन बहु-प्रतिमान योजना (प्रोग्रामिंग भाषा) जिसमें कार्यात्मक प्रोग्रामिंग और ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग (ओओपी) के लिए समर्थन सम्मिलित है, और गतिशील प्रोग्रामिंग भाषा और प्रतिबिंब (कंप्यूटर प्रोग्रामिंग) है, जबकि कुशल मशीन कोड उत्पन्न करने के लिए डिज़ाइन किया गया प्रोग्रामिंग मॉडल प्रदान करता है, जिसमें ठीक- गतिशील और स्थिर व्यवहारों पर सूक्ष्म नियंत्रण सम्मिलित है। इसे 1990 के दशक की प्रारंभ में एप्पल कंप्यूटर के नेतृत्व वाले समूह द्वारा बनाया गया था।

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

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

डायलन ने अपने शब्दार्थ को योजना और अन्य लिस्प्स से प्राप्त किया है; कुछ डायलन कार्यान्वयन प्रारंभ में उपस्थित लिस्प प्रणाली के अन्दर बनाए गए थे। चुकीं, डायलन में लिस्प-जैसे उपसर्ग वाक्य-विन्यास के अतिरिक्त अल्गोल जैसा वाक्य-विन्यास है।

इतिहास

डायलन को 1990 के दशक की प्रारंभ में एप्पल कंप्यूटर के नेतृत्व वाले समूह द्वारा बनाया गया था। इसके विकास के समय में, इसे एप्पल न्यूटन कंप्यूटर के साथ उपयोग करने का नियत था, लेकिन डायलन कार्यान्वयन समय पर पर्याप्त परिपक्वता तक नहीं पहुंचा, और न्यूटन ने इसके अतिरिक्त वाल्टर स्मिथ द्वारा विकसित सी और न्यूटनस्क्रिप्ट के मिश्रण का उपयोग किया। एप्पल ने 1995 में अपने डायलन विकास प्रयास को समाप्त कर दिया, चुकीं उन्होंने प्रौद्योगिकी रिलीज़ संस्करण उपलब्ध कराया (एप्पल डायलन टी.आर.1) जिसमें उन्नत एकीकृत विकास वातावरण (आईडीई) सम्मिलित था।

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

डायलन भाषा का कोड-नाम राल्फ था। जेम्स जोआक्विन ने डायनामिक भाषा के लिए डायलन नाम चुना।

वाक्य-विन्यास

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

शाब्दिक वाक्य रचना

डायलन स्थिति की संवेदनशीलता नहीं है। डायलन का शाब्दिक वाक्य-विन्यास नामकरण सम्मेलन के उपयोग की अनुमति देता है जहां हाइफन-माइनस संकेतों का उपयोग बहु-शब्द पहचानकर्ताओं (कभी-कभी तुतलाना स्थिति या कबाब का स्थिति कहा जाता है) के भागों को जोड़ने के लिए किया जाता है। लिस्प भाषाओं में यह सम्मेलन सामान्य है।

अल्फ़ान्यूमेरिक वर्णों और हाइफ़न-माइनस संकेतों के अतिरिक्त, डायलन पहचानकर्ताओं के भाग के रूप में विभिन्न प्रकार के गैर-अल्फ़ान्यूमेरिक वर्णों की अनुमति देता है। पहचानकर्ताओं में केवल ये गैर-अक्षरांकीय वर्ण सम्मिलित नहीं हो सकते हैं।[2] यदि कोई अस्पष्टता है तो खाली स्थान का प्रयोग किया जाता है।

उदाहरण कोड

कई स्लॉट के साथ साधारण वर्ग:

define class <point> (<object>)
  slot point-x :: <integer>,
    required-init-keyword: x:;
  slot point-y :: <integer>,
    required-init-keyword: y:;
end class <point>;

परिपाटी के अनुसार, कक्षाओं को कोण कोष्ठक के रूप में उपयोग किए जाने वाले संकेतों से कम और अधिक से अधिक नामित किया जाता है, उदा: नामित वर्ग <point> कोड उदाहरण

में end class <point> दोनों class और <point> वैकल्पिक हैं। यह सभी के लिए सच है end खंड उदाहरण के लिए, आप लिख सकते हैं end if या केवल end समाप्त करने के लिए if कथन

का उदहारण बनाना है। <point>:

make(<point>, x: 100, y: 200)

एक ही वर्ग, सबसे कम संभव विधि से फिर से लिखा गया:

define class <point> (<object>)
  slot point-x;
  slot point-y;
end;

स्लॉट अब दोनों टाइप किए गए हैं <object>. स्लॉट को मैन्युअल रूप से प्रारंभ किया जाना चाहिए:

let p = make(<point>);
point-x(p) := 100;  // or p.point-x := 100;
point-y(p) := 200;  // or p.point-y := 200;

परंपरा के अनुसार, निरंतर नाम $ से प्रारंभ होते हैं:

define constant $pi :: <double-float> = 3.1415927d0;

फैक्टोरियल फलन:

define function factorial (n :: <integer>) => (n! :: <integer>)
  case
    n < 0     => error("Can't take factorial of negative integer: %d\n", n);
    n = 0     => 1;
    otherwise => n * factorial(n - 1);
  end
end;

यहाँ, n! और <integer> सामान्य पहचानकर्ता हैं।

कोई स्पष्ट वापसी कथन नहीं है। एक विधि या कार्य का परिणाम अंतिम अभिव्यक्ति का मूल्यांकन है। वापसी की स्थिति में अभिव्यक्ति के बाद अर्धविराम को छोड़ना सामान्य शैली है।

मॉड्यूल बनाम नामस्थान

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

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

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

उदाहरण के लिए, रेगेक्स समर्थन के लिए ऐड-ऑन लाइब्रेरी पर विचार करें String. कुछ भाषाओं में, कार्यक्षमता को स्ट्रिंग्स में सम्मिलित करने के लिए, कार्यक्षमता को इसमें जोड़ा जाना चाहिए String नाम स्थान ऐसा होते ही, द String वर्ग बड़ा हो जाता है, और जिन कार्यों को रेगेक्स का उपयोग करने की आवश्यकता नहीं होती है, उन्हें अभी भी बढ़े हुए पुस्तकालय आकार में इसके लिए भुगतान करना होगा। इस कारण से, इस प्रकार के ऐड-ऑन सामान्यतः उनके अपने नामस्थान और ऑब्जेक्ट में रखे जाते हैं। इस दृष्टिकोण का नकारात्मक पक्ष यह है कि नए कार्य अब इसका भाग नहीं हैं String; इसके अतिरिक्त, यह अपने स्वयं के कार्यों के सेट में अलग-थलग है जिसे अलग से बुलाया जाना चाहिए। के अतिरिक्त myString.parseWith(myPattern), जो ओओ के दृष्टिकोण से प्राकृतिक संगठन होगा, कुछ इस तरह myPattern.parseString(myString) का उपयोग किया जाता है, जो ऑर्डरिंग को प्रभावी ढंग से उलट देता है।

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

इंटरफ़ेस निर्माण का अधिक व्यावहारिक उपयोग मॉड्यूल के सार्वजनिक और निजी संस्करणों का निर्माण करना है, कुछ ऐसा जो अन्य भाषाओं में बोल्ट ऑन प्रकार के रूप में सम्मिलित होता है जो हमेशा समस्याओं का कारण बनता है और वाक्य-विन्यास जोड़ता है। डायलन के तहत, प्रत्येक फलन कॉल को केवल निजी या विकास इंटरफ़ेस में रखा जा सकता है, और सार्वजनिक रूप से सुलभ कार्यों को एकत्र किया जा सकता है Public. जावा (प्रोग्रामिंग भाषा) या C++ के तहत किसी वस्तु की दृश्यता को कोड में परिभाषित किया गया है, जिसका अर्थ है कि समान परिवर्तन का समर्थन करने के लिए, प्रोग्रामर को परिभाषाओं को पूरी तरह से फिर से लिखने के लिए मजबूर किया जाएगा, और एक ही समय में दो संस्करण नहीं हो सकते।

कक्षाएं

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

define class <window> (<view>)
  slot title :: <string> = "untitled", init-keyword: title:;
  slot position :: <point>, required-init-keyword: position:;
end class;

इस उदाहरण में, वर्ग<window>परिभाषित किया गया। <वर्ग का नाम> वाक्य-विन्यास केवल सम्मेलन है, वर्ग के नाम को अलग करने के लिए - कोण कोष्ठक केवल वर्ग के नाम का भाग हैं। इसके विपरीत, कुछ भाषाओं में परिपाटी वर्ग के नाम के पहले अक्षर को कैपिटलाइज़ करने या नाम के आगे सी या टी (उदाहरण के लिए) लगाने की है। <window> एक ही वर्ग से विरासत में मिला है, <view>, और इसमें दो स्लॉट हैं, title विंडो शीर्षक के लिए स्ट्रिंग पकड़ना, और position खिड़की के कोने के लिए एक्स वाई बिंदु धारण करना। इस उदाहरण में, शीर्षक को डिफ़ॉल्ट मान दिया गया है, जबकि स्थिति को नहीं दिया गया है। वैकल्पिक init-कीवर्ड वाक्य-विन्यास प्रोग्रामर को क्लास के किसी ऑब्जेक्ट को इंस्टेंट करते समय स्लॉट के प्रारंभिक मान को निर्दिष्ट करने की अनुमति देता है।

C++ या Java जैसी भाषाओं में, वर्ग अपने इंटरफ़ेस को भी परिभाषित करेगा। इस स्थिति में उपरोक्त परिभाषा में कोई स्पष्ट निर्देश नहीं है, इसलिए दोनों भाषाओं में स्लॉट और विधियों तक पहुंच को protected माना जाता है, जिसका अर्थ है कि उनका उपयोग केवल उपवर्गों द्वारा किया जा सकता है। असंबंधित कोड को विंडो उदाहरणों का उपयोग करने की अनुमति देने के लिए, उन्हें public.घोषित किया जाना चाहिए ।

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

चुकीं यह उदाहरण इसका उपयोग नहीं करता है, लेकिन डायलन भी कई वंशानुक्रम का समर्थन करता है।

विधि और सामान्य कार्य

डायलन में, विधियाँ आंतरिक रूप से किसी विशिष्ट वर्ग से संबद्ध नहीं हैं; विधियों को कक्षाओं के बाहर विद्यमान माना जा सकता है। सीएलओएस की तरह, डायलन मल्टीपल डिस्पैच (मल्टीमेथड्स) पर आधारित है, जहां बुलाए जाने वाले विशिष्ट विधि को उसके सभी तर्कों के प्रकारों के आधार पर चुना जाता है। विधि को संकलित समय पर जानने की आवश्यकता नहीं है, यह समझ कि उपयोगकर्ता की प्राथमिकताओं के आधार पर आवश्यक फलन उपलब्ध हो सकता है या नहीं।

जावा के अंतर्गत विशिष्ट वर्ग में समान विधियों को अलग किया जाएगा। उस कार्यक्षमता का उपयोग करने के लिए प्रोग्रामर को उस वर्ग को आयात करने और विधि को कॉल करने के लिए स्पष्ट रूप से संदर्भित करने के लिए मजबूर किया जाता है। यदि वह वर्ग अनुपलब्ध है, या संकलन समय पर अज्ञात है, तो एप्लिकेशन केवल संकलन नहीं करेगा।

डायलन में, कोड को कार्यों में भंडारण से अलग किया जाता है। कई वर्गों में ऐसी विधियाँ होती हैं जो अपने स्वयं के कार्यों को बुलाती हैं, जिससे अधिकांश अन्य ओओ भाषाओं की तरह दिखती हैं और महसूस होती हैं। चुकीं कोड सामान्य कार्यों में भी स्थित हो सकते हैं, जिसका अर्थ है कि वे किसी विशिष्ट वर्ग से जुड़े नहीं हैं, और किसी के द्वारा मूल रूप से कहे जा सकते हैं। विशिष्ट सामान्य कार्य को वर्ग में विधि से जोड़ना इस प्रकार पूरा किया जाता है:

define method turn-blue (w :: <window>)
  w.color := $blue;
end method;

यह परिभाषा अन्य भाषाओं की परिभाषा के समान है, और संभवतः इसके अन्दर समाहित हो जाएगी <window> कक्षा। ध्यान दें:= सेटर कॉल, जो सिंटैक्टिक सुगर के लिए है color-setter($blue, w).

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

एक्स्टेंसिबिलिटी

यह पूरी अवधारणा कुछ पाठकों को बहुत विचित्र लग सकती है। विंडो के लिए to-string को संभालने के लिए कोड को <window> में परिभाषित नहीं किया गया है?यह तब तक समझ में नहीं आता जब तक कि आप इस बात पर विचार न करें कि डायलन to-string कॉल को कैसे संभालता है। अधिकांश भाषाओं में जब प्रोग्राम को संकलित किया जाता है तो <window> के लिए to-string को देखा जाता है और विधि के लिए पॉइंटर (अधिक या कम) के साथ प्रतिस्थापित किया जाता है। डायलन में यह तब होता है जब प्रोग्राम पहली बार चलाया जाता है; रन टाइम प्रणाली विधि-नाम पैरामीटर विवरण की तालिका बनाता है और इस तालिका के माध्यम से गतिशील रूप से विधियों को देखता है। इसका अर्थ है कि विशिष्ट विधि के लिए फलन कहीं भी स्थित हो सकता है, न कि केवल संकलन-समय इकाई में हो सकता है। अंत में प्रोग्रामर को अपने कोड को रखने के स्थिति में अधिक लचीलापन दिया जाता है, जहां उचित हो, और कार्यात्मक लाइनों के साथ इसे एकत्रित करना जहां यह नहीं है।

यहाँ निहितार्थ यह है कि प्रोग्रामर अलग फ़ाइल में फलन को परिभाषित करके उपस्थित कक्षाओं में कार्यक्षमता जोड़ सकता है। उदाहरण के लिए, हो सकता है कि आप सभी में वर्तनी जाँच जोड़ना चाहें <string>s, जिसे C++ या जावा में स्ट्रिंग क्लास के सोर्स कोड तक पहुंच की आवश्यकता होगी- और ऐसी मूलभूत कक्षाएं संभवतः ही कभी स्रोत के रूप में दी जाती हैं। डायलन (और अन्य एक्स्टेंसिबल भाषाओं) में वर्तनी जाँच विधि को इसमें जोड़ा जा सकता है spell-check मॉड्यूल, उन सभी वर्गों को परिभाषित करता है जिन पर इसे प्रयुक्त किया जा सकता है define method निर्माण। इस स्थिति में वास्तविक कार्यक्षमता को एकल सामान्य फलन में परिभाषित किया जा सकता है, जो स्ट्रिंग लेता है और त्रुटियां लौटाता है। जब spell-check मॉड्यूल आपके प्रोग्राम में संकलित है, सभी स्ट्रिंग्स (और अन्य ऑब्जेक्ट्स) को अतिरिक्त कार्यक्षमता मिलेगी।

एप्पल डायलन

एप्पल डायलन, एप्पल कंप्यूटर द्वारा निर्मित डायलन का कार्यान्वयन है। यह मूल रूप से एप्पल न्यूटन उत्पाद के लिए विकसित किया गया था।

संदर्भ

  1. Stokel-Walker, Chris. "Julia: The Goldilocks language". Increment. Stripe. Retrieved 23 August 2020.
  2. 2.0 2.1 Andrew Shalit; David Moon; Orca Starbuck (11 September 1996). The Dylan Reference Manual. Apple Press. Addison-Wesley. ISBN 9780201442113.


बाहरी संबंध