2012-02-14 21 views
8

मैं सो नहीं सकता! :)आलसी बनाम उत्सुक मूल्यांकन और डबल लिंक्ड सूची निर्माण

मैंने हास्केल में डबल प्रोग्राम बिल्डिंग डबल लिंक्ड लिस्ट लिखी है। इसे बनाने के लिए मूल भाषा की संपत्ति आलसी मूल्यांकन थी (नीचे दिए गए कोड का समूह देखें)। और मेरा सवाल यह है कि मैं शुद्धउत्सुक मूल्यांकन के साथ कार्यात्मक भाषा में ऐसा कर सकता हूं या नहीं? किसी भी मामले में, उत्सुक कार्यात्मक भाषा को ऐसी संरचना (अशुद्धता?) बनाने में सक्षम होना चाहिए?

import Data.List 

data DLList a = DLNull | 
    DLNode { prev :: DLList a 
      , x :: a 
      , next :: DLList a 
      } 
    deriving (Show) 

walkDLList :: (DLList a -> DLList a) -> DLList a -> [a] 
walkDLList _ DLNull = [] 
walkDLList f [email protected](DLNode _ x _) = x : walkDLList f (f n) 

-- Returns first and last items. 
makeDLList :: [a] -> (DLList a, DLList a) 
makeDLList xs = let (first, last) = step DLNull xs in (first, last) 
    where 
    step prev [] = (DLNull, prev) 
         -- Here I use laziness. 'next' is not built yet, it's a thunk. 
    step prev (x : xs) = let this = DLNode prev x next 
          (next, last) = step this xs 
         in (this, last) 

testList :: [Int] -> IO() 
testList l = let 
    (first, last) = makeDLList l 
    byNext = walkDLList next first 
    byPrev = walkDLList prev last 
    in do 
    putStrLn $ "Testing: " ++ show l 
    print byNext 
    print byPrev 

main = do 
    testList [] 
    testList [1, 2, 3, 4] 
+0

[* यह * कोड] देखें (http://rosettacode.org/wiki/Doubly-Linked_List_%28traversal%29#Haskell)। :) यह सिर्फ सिर नोड देता है, और असाधारण रूप से सरल है। –

उत्तर

4

जब तक किसी भाषा में बंद होने जैसे कुछ, लैम्बडा आदि होते हैं तो आप हमेशा आलसीता का अनुकरण कर सकते हैं। तुम भी जावा में (चर आदि परिवर्तनशील बिना) है कि कोड को फिर से लिखने सकता है, तो आप सिर्फ तरह

interface Thunk<A> { 
    A eval(); 
} 

बेशक इस भयानक लगेगा कुछ में हर "सुस्त" आपरेशन रैप करने के लिए की जरूरत है, लेकिन यह संभव है।

+3

आपको आलसी मूल्यांकन (अधिकतर बार मूल्यांकन) के प्रभाव को प्राप्त करने के लिए कुछ अद्यतन करने की आवश्यकता है, अन्यथा आप कॉल-बाय-नाम अनुकरण करेंगे। – augustss

+0

तो, अगस्त, आपका मुद्दा यह है कि यह केवल बंद होने और लैम्ब्डा पर्याप्त नहीं है? – demi

+2

मुझे लगता है कि वह सिर्फ संदर्भित करता है कि 'eval' के परिणाम को कैश किया जाना चाहिए, इसलिए थंक को फिर से नहीं किया जाना चाहिए' eval' कई बार चलाया जाना चाहिए। – danr

4

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

इसके अलावा, वहाँ वास्तव बनाम पूंछ-प्रत्यावर्तन सापेक्ष विपक्ष फैशन में बनाया Prolog के ओपन एंडेड सूचियों आलसी मूल्यांकन तहत हास्केल के पहरा प्रत्यावर्तन के बीच ज्यादा अंतर नहीं है। IMO। उदाहरण के लिए यहां lazy lists in Prolog का उदाहरण दिया गया है। ज्ञात साझा भंडारण सार्वभौमिक पहुंच मध्यस्थ के रूप में उपयोग किया जाता है, इसलिए पिछली गणना के परिणाम कैश किए जाने के लिए व्यवस्थित किए जा सकते हैं।

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

तो केवल सवाल यह है कि रहता है, तो आप के रूप में शुद्ध ऐसे सेट एक बार भाषाओं स्वीकार करते हैं?

6

एक दोगुनी-लिंक्ड सूची को एक अकेले-लिंक्ड सूची पर zipper के रूप में उत्सुक भाषा में पूरी तरह कार्यात्मक तरीके से कार्यान्वित किया जा सकता है। उदाहरण के लिए, Rosetta Code > Doubly-linked list > OCaml > Functional देखें।

+0

मुझे लगता है कि दोगुनी- * लिंक्ड * सूची का बिंदु यह है कि यह ** आपके द्वारा लिंक किए गए कोड के विपरीत, ** ** ट्रैवर्सल पर नया संग्रहण आवंटित नहीं करता है।इसमें, 'पिछला (अगला एलीस्ट) 'सामान्य' सी, कहने, कार्यान्वयन, और ऊपर दिए गए प्रश्न से हास्केल कोड के विपरीत 'एलिस्ट' के समान भंडारण नहीं है, जहां 'चलो (alist, zlist) = makeDLList xs के बाद 'हमारे पास' prev (अगला alist) == alist' और 'next (पिछला zlist) == zlist' है जहां' == 'का अर्थ है *" वही वास्तविक भंडारण "*, या लिस्प-पार्लान्स *" 'eq'- समकक्ष "* (पाठ्यक्रम के गैर खाली 'xs' के लिए)। –

+0

@WillNess "ट्रैवर्सल पर नए स्टोरेज [आईएनजी] आवंटित नहीं" के संबंध में, यह कार्यान्वयन विवरण है, और लागत पर आता है। आप पूरी सूची की एक प्रति बनाये बिना एक अपरिवर्तनीय दोगुनी-लिंक्ड सूची (ओपी द्वारा दी गई शैली में) में "सम्मिलित" नहीं कर सकते हैं। खैर, आप आम तौर पर आलस्य के कारण कम प्रतिलिपि से दूर हो सकते हैं, लेकिन बिंदु यह है कि नई दोगुनी-लिंक्ड सूची पुरानी दोगुनी-लिंक्ड सूची के साथ किसी भी नोड्स को साझा नहीं कर सकती है। अपरिवर्तनीय जिपर कार्यान्वयन अधिक साझा करने की अनुमति देता है, हालांकि ट्रैवर्सल के लिए आवश्यक अधिक संग्रहण की लागत पर (लेकिन * अधिक * अधिक नहीं, फिर से साझा करने की क्षमता के कारण)। –

+0

@WillNess एनबी। हास्केल 'eq'-ness के बारे में कोई गारंटी नहीं देता है। जीएचसी के समानांतर कचरा कलेक्टर इसका लाभ उठाता है, और वास्तव में * साझा * साझा कर सकता है जिसे आप वहां होने की उम्मीद कर सकते हैं। यह दुर्लभ है, और प्रदर्शन को प्रभावित करता है, हालांकि, और अपरिवर्तनीय डेटा के कारण, यह आपके परिणामों को कभी प्रभावित नहीं करेगा। –

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