आलसी सूचियों को लागू करें, अधिमानतः एक ऐसी भाषा में जिसे आप अच्छी तरह से नहीं जानते हैं [बंद]


21

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

आपका कार्य आलसी सूचियों को प्रबंधित करने के लिए कोड लिखना है, फिर फाइबोनैचि संख्याओं को उत्पन्न करने के लिए इस एल्गोरिथम को लागू करने के लिए इसका उपयोग करें:

कोड के नमूने हास्केल में हैं

let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
 in take 40 fibs

परिणाम:

[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986]

आपकी आलसी सूची कार्यान्वयन को इन दिशानिर्देशों को पूरा करना चाहिए:

  • एक सूची नोड तीन चीजों में से एक है:
    • शून्य - खाली सूची।
      []
    • विपक्ष - एक एकल आइटम, शेष वस्तुओं की सूची के साथ जोड़ा गया:
      1 : [2,3,4,5]
      ( :हास्केल में कंस ऑपरेटर है)
    • थंक - एक आस्थगित अभिकलन जो जरूरत पड़ने पर एक सूची नोड का उत्पादन करता है।
  • यह निम्नलिखित कार्यों का समर्थन करता है:
    • नील - एक खाली सूची का निर्माण।
    • cons - एक कंस सेल का निर्माण।
    • थंक - एक थंक का निर्माण करते हैं, एक ऐसा फ़ंक्शन दिया जाता है जो कोई तर्क नहीं देता है और एक निल या विपक्ष लौटाता है।
    • बल - एक सूची नोड को देखते हुए:
      • यदि यह एक निल या विपक्ष है, तो इसे वापस कर दें।
      • यदि यह एक थंक है, तो निल या कॉन्स पाने के लिए इसके फ़ंक्शन को कॉल करें। उस नील या विपक्ष के साथ ठग को बदलें, और इसे वापस करें।
        नोट: थंक को उसके मजबूर मान के साथ बदलना "आलसी" की परिभाषा का एक महत्वपूर्ण हिस्सा है । यदि यह चरण छोड़ दिया जाता है, तो ऊपर फाइबोनैचि एल्गोरिथ्म बहुत धीमा हो जाएगा।
    • खाली - देखें कि क्या एक सूची नोड निल है (इसे मजबूर करने के बाद)।
    • सिर (उर्फ "कार") - एक सूची का पहला आइटम प्राप्त करें (या यदि यह नील है तो एक फिट फेंक दें)।
    • पूंछ (उर्फ "सीडीआर") - एक सूची के प्रमुख के बाद तत्वों को प्राप्त करें (या यदि यह नील है तो एक फिट फेंक दें)।
    • zipWith - एक बाइनरी फ़ंक्शन (जैसे (+)) और दो (संभवतः अनंत) सूचियों को देखते हुए , फ़ंक्शन को सूचियों के संबंधित आइटम पर लागू करें। उदाहरण:
      zipWith (+) [1,2,3] [1,1,10] == [2,3,13]
    • ले - एक संख्या एन और एक (संभवतः अनंत) सूची को देखते हुए, सूची के पहले एन आइटम को पकड़ो।
    • प्रिंट - किसी सूची में सभी आइटम प्रिंट करें। लंबी या अनंत सूची दिए जाने पर इसे बढ़ाकर काम करना चाहिए।
  • fibsअपनी परिभाषा में खुद का उपयोग करता है। आलसी पुनरावृत्ति की स्थापना एक कठिन चाल है; आपको ऐसा कुछ करने की आवश्यकता होगी:

    • के लिए एक ठिकाना आवंटित करें fibs। इसे अभी के लिए डमी अवस्था में छोड़ दें।
    • थंक फ़ंक्शन को परिभाषित करें, जो करने के लिए एक संदर्भ पर निर्भर करता है fibs
    • इसके कार्य के साथ थन को अपडेट करें।

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

  • बहुरूपता (किसी भी प्रकार की वस्तुओं की सूचियों के साथ काम करने की क्षमता) की आवश्यकता नहीं है, लेकिन देखें कि क्या आप ऐसा करने का कोई तरीका खोज सकते हैं जो आपकी भाषा में मुहावरा है।

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

अपनी भाषा के विवरणों को समायोजित करने के लिए या आलसी सूचियों के लिए वैकल्पिक तरीकों का पता लगाने के लिए इन दिशानिर्देशों से थोड़ा विचलित होने के लिए स्वतंत्र महसूस करें।

नियम:

  • ऐसी भाषा चुनें जिसे आप अच्छी तरह से नहीं जानते हैं। मुझे इसकी आवश्यकता नहीं है, इसलिए "सम्मान-प्रणाली" टैग। हालांकि, मतदाता आपके इतिहास को यह देखने के लिए जांच सकते हैं कि आप किन भाषाओं में पोस्ट कर रहे हैं।
  • सब कुछ करने के लिए अपनी भाषा की अंतर्निहित आलसी सूची समर्थन का उपयोग न करें। कुछ पर्याप्त या कम से कम दिलचस्प पोस्ट करें।

    • हास्केल बहुत बाहर है। जब तक आप ऐसा कुछ नहीं करते हैं:

      data List a = IORef (ListNode a)
      data ListNode a = Nil | Cons !a !(List a) | Thunk !(IO (ListNode a))
      

      नोट: हास्केल का गैर-सख्त मूल्यांकन ऑफ-लिमिट्स नहीं है, लेकिन आपके आलसी सूची कार्यान्वयन को सीधे इसकी क्षमता प्राप्त नहीं करनी चाहिए। वास्तव में, यह एक कुशल, विशुद्ध रूप से कार्यात्मक समाधान देखना दिलचस्प होगा जिसमें आलस्य की आवश्यकता नहीं है।

    • अजगर:

      • Itertools का उपयोग न करें।
      • जेनरेटर ठीक हैं, लेकिन आप उनका उपयोग करते हैं, आपको मजबूर मूल्यों को याद करने का कोई तरीका खोजना होगा।

zipWithअलग-अलग लंबाई की दो सूचियों पर कॉल करते समय व्यवहार कैसा होना चाहिए ?
बाल्फा

@balpha: मैंने हास्कल्स व्यवहार को चुना: यदि सूची में से कोई एक शून्य है, तो निल वापस करें।
फ़ूजएक्सएक्सएल

@balpha: हास्केल में, zipWith तब रुकता है जब या तो सूची आइटम से बाहर निकल जाती है। इसलिए, zipWith (+) [1,2,3,4,5] [0,0,0] == [1,2,3]। हालाँकि, ऊपर दिए गए फाइबोनैचि एल्गोरिथ्म के लिए यह कोई मायने नहीं रखता है, क्योंकि zipWith दोनों तर्क अनंत सूचियाँ हैं।
जॉय एडम्स

इस चुनौती में एक छिपा हुआ आश्चर्य था: आपको fibsसही तरीके से लागू करने के लिए कुछ विशेष करने की आवश्यकता है, क्योंकि यह खुद पर निर्भर करता है। मैंने आलसी पुनरावृत्ति पर विस्तार से प्रश्न को अद्यतन किया। FUZxxl ने उसे उसके / उसके द्वारा पता लगाया।
जॉय एडम्स

जब आप एक बड़ी सूची प्रिंट करते हैं तो "काम करते हुए" क्या मतलब है?
लोजैकर 22

जवाबों:


6

परिशिष्ट भाग

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

मैं आपकी कल्पना से विचलित हो गया कि जिस कार्य का उपयोग एक थंक को बनाने के लिए किया जाता है, उसे दूसरे थंक को वापस करने की अनुमति है; forceजब तक परिणाम एक nilया एक का मूल्यांकन करता रहेगा cons

सूचियों को शब्दकोशों के रूप में कार्यान्वित किया जाता है:

<< /type /nil >>

<< /type /cons
   /head someValue
   /tail someList >>

<< /type /thunk
   /func evaluationFunction >>

<< /type /dataThunk
   /func evaluationFunction
   /data someValueToBePassedToTheFunction >>

कोड इस प्रकार है। ध्यान दें कि हम कुछ बिल्टइन ऑपरेटरों को अधिलेखित कर रहे हैं (विशेष रूप से print; मैंने जांच नहीं की है कि क्या अधिक हैं); वास्तविक दुनिया में उपयोग के लिए, यह देखना होगा। बेशक, कोई वास्तविक दुनिया का उपयोग नहीं होगा, इसलिए यह ठीक है।

प्रक्रियाओं के पहले टिप्पणियों को पढ़ा जाना चाहिए

% before2 before1 before0  <| procedure |>  after1 after0

यानी कॉल से पहले अपेक्षित स्टैक सामग्री और कॉल के बाद परिणामी स्टैक सामग्री को दिखाना। प्रक्रियाओं के भीतर टिप्पणियां विशेष पंक्ति के निष्पादित होने के बाद स्टैक की सामग्री को दिखाती हैं।

% Helper procedure that creates a dictionary with the top two elements as keys
% and the next two elements as values.
%
% value1 value2 key1 key2  <| _twodict |>  << /key1 /value1 /key2 /value2 >>
/_twodict {
    << 5 1 roll    % << value1 value2 key1 key2
    4 2 roll       % << key1 key2 value1 value2
    3 2 roll       % << key1 value1 value2 key2
    exch >>
} def

/nil {
    << /type /nil >>
} def

% item list  <| cons |>  consCell
/cons {
    /head /tail _twodict
    dup /type /cons put
} def

% constructs a thunk from the function, which will be called with no
% arguments to produce the actual list node. It is legal for the function
% to return another thunk.
%
% func  <| thunk |>  lazyList
/thunk {
    /thunk /func /type _twodict
} def

% A dataThunk is like a regular thunk, except that there's an additional
% data object that will be passed to the evaluation function
%
% dataObject func  <| dataThunk |>  lazyList
/dataThunk {
    /data /func _twodict
    dup /type /dataThunk put 
} def

% lazyList  <| force |>  consOrNil
/force {
    dup /type get dup
    /thunk eq
    {
        pop
        dup /func get exec exch copy
        force
        dup /func undef
    }
    {
        /dataThunk eq
        {
            dup dup /data get exch
            /func get exec exch copy
            force
            dup dup /func undef /data undef
        } if
    } ifelse
} def

/empty {
    force
    /type get
    /nil eq
} def

/head {
    force /head get
} def

/tail {
    force /tail get
} def

/print {
    dup empty not
    {
        dup
        head ==
        tail
        print    
    }
    {
        pop
    } ifelse
} def

% sourceList n  <| take |>  resultingList
/take {
    /source /n _twodict
    {
        dup /source get exch    % source data
        /n get 1 sub dup        % source n-1 n-1
        -1 eq
        {
            pop pop nil
        }
        {                       % source n-1
            exch                % n-1 source
            dup head            % n-1 source head
            3 1 roll            % head n-1 source
            tail
            exch take           % head rest
            cons
        } ifelse
    }
    dataThunk
} def

% sourceList1 sourceList2 func  <| zipWith |>  resultList
/zipWith {
    3 1 roll
    2 array astore                  % func [L1 L2] 
    /func /sources _twodict
    {
        dup /sources get aload pop  % data L1 L2
        2 copy empty exch empty or
        {
            pop pop pop nil
        }
        {
            dup head exch tail      % data L1 H2 T2
            3 2 roll
            dup head exch tail      % data H2 T2 H1 T1
            exch                    % data H2 T2 T1 H1
            4 3 roll                % data T2 T1 H1 H2
            5 4 roll /func get      % T2 T1 H1 H2 func
            dup 4 1 roll            % T2 T1 func H1 H2 func
            exec                    % T2 T1 func NEWHEAD
            4 2 roll                % func NEWHEAD T2 T1
            exch 4 3 roll           % NEWHEAD T1 T2 func 
            zipWith cons
        } ifelse
    }
    dataThunk
} def

इसे भूतलेख में लोड करें, प्रदर्शित पृष्ठ को अनदेखा करते हुए - हम केवल दुभाषिया के साथ काम कर रहे हैं। यहाँ फिबोनाची एल्गोरिथ्म है:

[balpha@localhost lazylist]$ gs lazylist.ps 
GPL Ghostscript 8.71 (2010-02-10)
Copyright (C) 2010 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
GS> /fibs 0 1 { fibs fibs tail { add } zipWith } thunk cons cons def
GS> fibs 40 take print
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
GS>

दो अतिरिक्त दिलचस्प कार्य:

% creates an infinite list that starts with the given value, incrementing
% by one for each additional element
%
% startValue  <| count |>  lazyList
/count {
    {
        dup
        1 add count
        cons
    }
    dataThunk
} def    

% apply the given function to each element of the source list, creating
% a (lazy) list that contains the corresponding results
%
% sourceList function  <| map |> resultList
/map {
    /source /func _twodict
    {
        dup /func get exch
        /source get                 % func source
        dup empty not
        {
            dup head                % func source head
            2 index                 % func source head func
            exec 3 1 roll           % newHead func source
            tail exch map cons
        }
        {
            pop pop nil
        } ifelse
    }
    dataThunk
} def

5 पर गिनती शुरू करें, परिणामी सूची के प्रत्येक तत्व को 3 से गुणा करें, और पहले दस मान प्रदर्शित करें:

GS> 5 count { 3 mul } map 10 take print
15
18
21
24
27
30
33
36
39
42

बहुरूपता के बारे में: भले ही पोस्टस्क्रिप्ट दृढ़ता से टाइप किया गया है, यह शब्दकोश मूल्यों के रूप में मनमाने प्रकार की अनुमति देता है, इसलिए आप अपनी पसंद के अनुसार कुछ भी फेंक सकते हैं:

GS> 1337 [ 42 3.14 ] << /key /value >> (Hello world) 3 count
GS<5> cons cons cons cons 10 take print
1337
[42 3.14]
-dict-
(Hello world)
3
4
5
6
7
8
GS>

ध्यान दें कि टाइप में त्रुटियां, उदाहरण के लिए संख्याओं में तार जोड़ने की कोशिश से, केवल मूल्यांकन के समय ही होगा:

GS> (some string) (another string) nil cons cons
GS<1> 13 27 nil cons cons
GS<2> { add } zipWith      % no error yet
GS<1> print
Error: /typecheck in --add--

गजब का। (कैसे) forceरिटर्न मूल्यों को याद करता है ?
जॉय एडम्स

@JoeyAdams: यह वास्तव में करता है। एक थंक का मूल्यांकन करने के बाद, copyऑपरेटर मूल्यांकन किए गए संस्करण की सामग्री को मूल, ओवरराइटिंग /typeऔर संभवतः अन्य मान सेट करने की प्रतिलिपि बनाता है । पुनरावर्ती रूप से मूल्यांकन करने के बाद जब तक हमारे पास nilया cons, यह (भी undef) हटा देता है /funcऔर, जहां लागू हो /data,। अंतिम चरण सख्ती से आवश्यक नहीं है ( /funcऔर /dataबस अनदेखा किया जाएगा), लेकिन इस कदम को छोड़ने से और भी अधिक मेमोरी लीक होगी :)
बाल्फा

6

सी

मैं सी में कुल शुरुआत कर रहा हूं, यह कोड वास्तव में सी में कोडित पहली वास्तविक चीज है। यह बिना किसी चेतावनी के संकलित करता है और मेरे सिस्टम पर ठीक चलता है।

कैसे बनाना है

सबसे पहले, मेरे सर्वर से तारबॉल प्राप्त करें । इसमें एक मेकफिल शामिल है, इसलिए बस makeइसे बनाने के make runलिए चलाएं और फिर इसे चलाने के लिए । इस कार्यक्रम के बाद पहले 93 रिटेल नंबरों की एक सूची प्रिंट होती है। (संख्या 94 के बाद, एक अहस्ताक्षरित 64 बिट पूर्णांक ओवरफ्लो)

व्याख्या

प्रोग्राम कोर फ़ाइल है lazy-list.c। संबंधित हेडर फ़ाइल में, मैं एक संरचना को परिभाषित करता हूं list, वह हमारी आलसी सूची है। यह इस तरह दिख रहा है:

enum cell_kind {
  NIL,
  CONS,
  THUNK
};

typedef enum cell_kind cell_kind;

typedef long int content_t;

struct list {
  cell_kind kind;
  union {
    struct {
      content_t* head;
      struct list* tail;
    } cons;
    struct {
      struct list* (*thunk)(void*);
      /* If you want to give arguments to the thunk, put them in here */
      void* args;
    } thunk;
  } content;
};

सदस्य kindएक तरह का टैग है। यह चिह्नित करता है, कि क्या हमने सूचियों के अंत ( NIL), एक सेल का मूल्यांकन किया है जो पहले से ही मूल्यांकन किया हुआ है ( CONSया एक थंक THUNK)। फिर, वहाँ एक संघ है। यह है

  • मूल्य और पूंछ के साथ या तो पहले से ही मूल्यांकन की गई सेल
  • या एक थंक, एक फ़ंक्शन-पॉइंटर और एक संरचना की विशेषता है, जिसमें ज़रूरत पड़ने पर फ़ंक्शन के कुछ तर्क हो सकते हैं।

टैग द्वारा संघ की सामग्री का मूल्यांकन किया जाता है। यदि टैग है NIL, तो संघ की सामग्री अपरिभाषित है।

उपर्युक्त विनिर्देश में उल्लिखित सहायक कार्यों को परिभाषित करके, आमतौर पर उपयोग की सूची सूचियों को अमूर्त किया जा सकता है, जैसे कि इसका उपयोग। आप बस nil()खुद से एक बनाने के बजाय एक खाली सूची प्राप्त करने के लिए कॉल कर सकते हैं ।

तीन सबसे दिलचस्प कार्य हैं zipWith, takeऔर fibonaccis। लेकिन मैं समझाना नहीं चाहता take, क्योंकि यह बहुत समान है zipWith। सभी कार्य, जो आलसी होते हैं, के तीन घटक होते हैं:

  • एक रैपर, जो एक थन बनाता है
  • एक कार्यकर्ता, जो एक सेल के लिए गणना करता है
  • एक संरचना, जो तर्कों को बनाए रखती है

के मामले में zipWith, ये हैं zipWith, __zipWithऔर __zipArgs। मैं उन्हें बिना किसी और स्पष्टीकरण के यहाँ दिखाता हूँ, वहाँ समारोह काफी स्पष्ट होना चाहिए:

struct __zipArgs {
  content_t* (*f)(content_t*,content_t*);
  list* listA;
  list* listB;
};

static list* __zipWith(void* args_) {
  struct __zipArgs* args = args_;
  list* listA = args->listA;
  list* listB = args->listB;
  list* listC;

  content_t* (*f)(content_t*,content_t*) = args->f;
  content_t* headA = head(listA);
  content_t* headB = head(listB);
  content_t* headC;

  if (NULL == headA || NULL == headB) {
    free(args);
    return nil();
  } else {
    headC = f(headA, headB);
    args->listA = tail(listA);
    args->listB = tail(listB);
    listC = thunk(__zipWith,args);
    return cons(headC,listC);
  }
}

list* zipWith(content_t* (*f)(content_t*,content_t*),list* listA, list* listB) {
  struct __zipArgs* args = malloc(sizeof(struct __zipArgs));
  args->f = f;
  args->listA = listA;
  args->listB = listB;
  return thunk(__zipWith,args);
}

अन्य दिलचस्प कार्य है fibonaccis()। समस्या यह है, कि हमें पहले और दूसरे सेल के एक पॉइंटर को तीसरे के थंक को पास करने की आवश्यकता है, लेकिन उन सेल को बनाने के लिए हमें थंक के लिए एक पॉइंटर की भी आवश्यकता होती है। उस समस्या को हल करने के लिए, मैंने NULLपहली बार पॉइंटर को थंक से भर दिया और इसे बनाने के बाद इसे थन में बदल दिया। यहाँ सुन रहा है:

static content_t* __add(content_t* a,content_t* b) {
  content_t* result = malloc(sizeof(content_t));
  *result = *a + *b;
  return result;
}

list* fibonaccis() {
  static content_t one_ = 1;
  static content_t zero_ = 0;
  list* one  = cons(&one_,NULL);
  list* two  = cons(&zero_,one);
  list* core = zipWith(__add,one,two);
  one->content.cons.tail = core;
  return two;

संभव सुधार

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

अच्छा प्रस्तुत, विशेष रूप से एक सी प्रथम-टाइमर होने के लिए। बहुरूपता के बारे में, यदि आप ढेर पर अपनी सभी सामग्री आवंटित करने के लिए तैयार हैं, तो आप void*इसके प्रकार के रूप में उपयोग कर सकते हैं content_t
केसी

@ कैसी: बहुत-बहुत धन्यवाद। मैंने void*भी उपयोग करने के बारे में सोचा था , लेकिन मुझे लगा कि यह बहुत दूर तक टाइप सिस्टम को बनाएगा। टेम्प्लेट का उपयोग करना संभव नहीं है?
फूज़ल

C में टेम्प्लेट नहीं हैं, वह C ++ है, लेकिन हाँ आप इसे सामान्य बनाने के लिए C ++ टेम्प्लेट का उपयोग कर सकते हैं।
केसी

मुझे नहीं पता कि उनका उपयोग कैसे करना है। लेकिन मुझे लगता है, यह सिर्फ यह है कि सी यह टाइपसिस्टम के मामले में सीमित है। - मैं भी इस कार्यक्रम का उपयोग void*और दोस्तों के बिना कोड करने में सक्षम नहीं था ।
फ़ूजएक्सएक्सएल

1
"सदस्य kindएक टैग की तरह है।" आप इसे सिर्फ कॉल कर सकते हैं tag, क्योंकि यह अवधारणा के लिए एक बहुत ही स्वीकृत शब्द है (उदाहरण टैग यूनियन , स्पिनलेस टैगलेस जी-मशीन । दूसरी तरफ, "तरह" का एक अलग अर्थ है हास्केल संदर्भ: एक प्रकार का प्रकार। Intदयालु है *, []दयालु है * -> *, और (,)दयालु है * -> * -> *
जॉय एडम्स

5

सी ++

यह मैंने C ++ में लिखी सबसे बड़ी चीज है। मैं आमतौर पर ऑब्जेक्टिव-सी का इस्तेमाल करता हूं।

यह बहुरूपी है, लेकिन यह कभी भी कुछ भी मुक्त नहीं करता है।

मेरा mainकार्य (और addसमारोह ZipWith) इस तरह देख समाप्त हो गया:

int add(int a, int b) {return a + b;}

int main(int argc, char **argv) {
    int numFib = 15; // amount of fibonacci numbers we'll print
    if (argc == 2) {
        numFib = atoi(argv[1]);
    }

    // list that starts off 1, 1...
    LazyList<int> fibo = LazyList<int>(new Cons<int>(1,
                     new LazyList<int>(new Cons<int>(1))));
    // zip the list with its own tail
    LazyList<int> *fiboZip = LazyList<int>::ZipWith(add, &fibo, fibo.Tail());
    // connect the begin list to the zipped list
    fibo.Tail() -> ConnectToList(fiboZip);

    // print fibonacci numbers
    int *fibonums = fibo.Take(numFib);    
    for (int i=0; i<numFib; i++) cout << fibonums[i] << " ";

    cout<<endl;

    return 0;
}

यह देता है

 ./lazylist-fibo 20
 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 

कक्षाएं इस तरह काम करती हैं:

make a thunk:    LazyList<T>(new Thunk<T>( function, *args )) 
make empty list: LazyList<T>(new Nil<T>())
make cons:       LazyList<T>(new Cons<T>( car, *cdr ))

list empty:      list.Empty()
list's head:     list.Head()
list's tail:     list.Tail()
zipWith:         LazyList<T>::ZipWith(function, a, b)
take:            list.Take(n)
print:           list.Print()

पूर्ण स्रोत: यहाँ । यह एक गड़बड़ है, मुख्यतः क्योंकि यह एक बड़ी फ़ाइल में है।

संपादित करें: लिंक को बदल दिया (पुराना वाला मृत था)।


3
बहुत बढ़िया काम करते हैं, और लेने सचमुच :-) मैं, किसी भी तरह एक सी ++ विशेषज्ञ द्वारा हूँ, लेकिन एक और अधिक सी ++ "एक फिट फेंक" के लिए धन्यवाद - thunk लागू करने के लिए एक का उपयोग हो सकता है y रास्ता समारोह वस्तु (उर्फ "functor") (कि है, ()ऑपरेटर को ओवरलोड ), और उपयोग करने से बचने के लिए विरासत का उपयोग करने के लिए void*। ऐसा करने के एक तुच्छ उदाहरण के लिए यहां देखें
जॉय एडम्स

पूर्ण स्रोत लिंक अब मृत है। क्या आप इसे फिर से अपलोड कर सकते हैं? gist.github.com इसे लगाने के लिए एक अच्छी जगह है।
जॉय एडम्स

@JoeyAdams: किया गया।
मारिनस

4

अजगर

सूची को लागू करने के लिए जनरेटर का उपयोग न करें, बस __iter__उपयोग के लिए विधि को लागू करने के लिए for

class Node(object):
    def __init__(self, head, tail):
        self.__head__ = head
        self.__tail__ = tail

    def force(self):
        return self

    def empty(self):
        return False

    def head(self):
        return self.__head__

    def tail(self):
        return self.__tail__

    def zip_with(self, func, other):
        def gen_func():
            if other.empty():
                return other
            return Node(func(self.head(), other.head()), self.tail().zip_with(func, other.tail()))
        return Thunk(gen_func)

    def __iter__(self):
        while not self.empty():
            yield self.head()
            self = self.tail()

    def append(self, other):
        while not self.tail().empty():
            self = self.tail()
        self.__tail__ = other

    def take(self, n):
        if n == 0:
            return NullNode()
        else:
            return Node(self.__head__, self.__tail__.take(n - 1))

    def _print(self):
        for item in self:
            print item

class NullNode(Node):
    def __init__(self):
        pass

    def empty(self):
        return True

    def head(self):
        raise TypeError("cannot get head of nil")

    def tail(self):
        raise TypeError("cannot get tail of nil")

    def zip_with(self, func, other):
        return self

    def append(self, other):
        raise TypeError("cannot append to nil")

    def take(self, n):
        return self

class Thunk(Node):
    def __init__(self, func):
        self.func = func

    def force(self):
        node = self.func()
        self.__class__ = node.__class__
        if not node.empty():
            self.__head__ = node.head()
            self.__tail__ = node.tail()
        return self

    def empty(self):
        return self.force().empty()

    def head(self):
        return self.force().head()

    def tail(self):
        return self.force().tail()

    def take(self, n):
        return self.force().take(n)

फाइबोनैचि सूची इस तरह बनाई गई है:

>>> from lazylist import *
>>> fib = Node(0, Node(1, NullNode()))
>>> fib.append(fib.zip_with(lambda a, b: a + b, fib.tail()))
>>> 

1
ये सुन्दर है। मेरा पसंदीदा लाइन है self.__class__ = node.__class__। ध्यान दें कि जब यह 2971215073 (लंबा) हो जाता है, तो यह NotImplemented अपवाद को हिट करता है, जो कि स्पष्ट रूप से int_____ से एक अमान्य तर्क है। बड़ा पूर्णांकों का समर्थन करने के लिए, करfib.append(fib.zip_with(lambda a,b: a+b, fib.tail()))
जॉय एडम्स

1
आप खाली या थन के लिए अपील क्यों नहीं कर सकते?
PyRulez

4

माणिक

मेरा पहला रूबी कार्यक्रम। हम सरणियों के रूप में सभी नोड्स का प्रतिनिधित्व करते हैं, जहां सरणी लंबाई प्रकार निर्धारित करती है:

0: empty list
1: thunk (call the single element to get the cons cell)
2: cons cell (1st is head, 2nd is tail)

कोड फिर बहुत सीधा है, एक हैक के साथ पुनरावर्ती फाइबर को स्थापित करने के लिए थंक फ़ंक्शन को रीसेट करने के लिए।

def nil_()
  return Array[]
end

def cons(a, b)
  return Array[a, b]
end

def thunk(f)
  return Array[f]
end

def force(x)
  if x.size == 1
    r = x[0].call
    if r.size == 2
      x[0] = r[0]
      x.push(r[1])
    else
      x.pop()
    end
  end
end

def empty(x)
  force(x)
  return x.size == 0
end

def head(x)
  force(x)
  return x[0]
end

def tail(x)
  force(x)
  return x[1]
end

def zipWith(f, a, b)
  return thunk(lambda {
    if empty(a) or empty(b)
      return nil_()
    else
      return cons(f.call(head(a), head(b)), zipWith(f, tail(a), tail(b)))
    end
  })
end

def take(n, x)
  if n == 0
    return nil_()
  else
    return cons(head(x), take(n - 1, tail(x)))
  end
end

def print(x)
  while not empty(x)
    puts x[0]
    x = x[1]
  end
end

def add(x, y)
  return x + y
end

T=thunk(nil)  # dummy thunk function
fibs=cons(0, cons(1, T))
T[0]=zipWith(method(:add), fibs, tail(fibs))[0]  # overwrite thunk function

print(take(40, fibs))

आप उपयोग कर सकते हैं [...]के बजाय Array[...]
लोजैकर

3

गूगल गो

एक अपेक्षाकृत नया भाषा, और मैं इसे से सीखा CTRL+Fing युक्ति

package main
import "fmt"

type List struct {
  isNil, isCons, isThunk bool
  head *interface { }
  tail *List
  thunk (func() List)
}

func Nil() List {
  return List { true, false, false, nil, nil, Nil }
}

func Cons(a interface { }, b List) List {
  return List { false, true, false, &a, &b, Nil }
}

func Thunk(f(func() List)) List {
  return List { false, false, true, nil, nil, f }
}

func Force(x List) List {
  if x.isNil { return Nil()
  } else if x.isCons { return Cons(*x.head, *x.tail) }
  return Force(x.thunk())
}

func Empty(x List) bool {
  return Force(x).isNil;
}

func Head(x List) interface { } {
  y := Force(x)
  if y.isNil { panic("No head for empty lists.") }
  return *y.head
}

func Tail(x List) List {
  y := Force(x)
  if y.isNil { panic("No tail for empty lists.") }
  return *y.tail
}

func Take(n int, x List) List {
  if (n == 0) { return Nil() }
  return Thunk(func() List {
    y := Force(x)
    return Cons(*y.head, Take(n - 1, *y.tail))
  })
}

func Wrap(x List) List {
  return Thunk(func() List {
    return x
  })
}

func ZipWith(f(func(interface { }, interface { }) interface { }), a List, b List) List {
  return Thunk(func() List {
    x, y := Force(a), Force(b)
    if x.isNil || y.isNil {
      return Nil()
    }
    return Cons(f(*x.head, *y.head), ZipWith(f, *x.tail, *y.tail))
  });
}

func FromArray(a []interface { }) List {
  l := Nil()
  for i := len(a) - 1; i > -1; i -- {
    l = Cons(a[i], l)
  }
  return l
}

func Print(x List) {
  fmt.Print("[")
  Print1(x)
  fmt.Print("]")
}

func Print1(x List) {
  y := Force(x)
  if y.isCons {
    fmt.Print(Head(y))
    z := Force(Tail(y))
    if z.isCons { fmt.Print(", ") }
    Print1(z)
  }
}

func Plus(a interface { }, b interface { }) interface { } {
  return a.(int) + b.(int)
}

func Fibs() List {

  return Thunk(func() List {
    return Cons(0, Cons(1, Thunk(func() List {
      return ZipWith(Plus, Thunk(Fibs), Tail(Thunk(Fibs)))
    })))
  })
}

func Fibs0() List {
  // alternative method, working
  return Cons(0, Cons(1, Fibs1(0, 1)))
}

func Fibs1(a int, b int) List {
  c := a + b
  return Cons(c, Thunk(func() List { return Fibs1(b, c) }))
}

func CountUp(x int, k int) List {
  return Cons(x, Thunk(func() List {
    return CountUp(x + k, k)
  }))
}

func main() {
  //a := []interface{} { 0, 1, 2, 3 }
  //l, s := FromArray(a), FromArray(a)
  Print(Take(40, Fibs()))
}

ठक-ठक-ठक-ठक से निपट कर समस्या तय हो गई। हालाँकि, ऐसा लगता है कि ऑनलाइन संकलक 40 तत्वों को नहीं ले सकता है, शायद स्मृति के कारण। मैं बाद में अपने लिनक्स पर इसका परीक्षण करूंगा।

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368runtime: address space conflict: map() = 
throw: runtime: address space conflict

panic during panic

मैंने ऑनलाइन कंपाइलर के साथ कोड का परीक्षण किया , क्योंकि मैं विंडोज पर गो आसानी से स्थापित नहीं कर सकता।


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

आपका Fibsफ़ंक्शन काम नहीं करता है क्योंकि Go सख्त मूल्यांकन का उपयोग करता है, और Fibsबिना किसी समाप्ति स्थिति के अपने आप को पुन: प्राप्त करता है। Fibs0/ Fibs1मेरी पोस्ट में वर्णित एल्गोरिदम के बजाय एक साधारण जनरेटर दृष्टिकोण का उपयोग करता है, इसलिए यह "आवश्यकताओं" को पूरा नहीं करता है। मैंने अपनी पोस्ट को आलसी पुनरावृत्ति पर विस्तृत करने के लिए अद्यतन किया, जिसे लागू करने की आवश्यकता है fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
जॉय एडम्स

Cons(0, Cons(1, ZipWith(Plus, Thunk(Fibs), Tail(Thunk(Fibs))))), यह स्मृति से बाहर चला जाता है
मिंग-तांग

मैंने कोशिश की Cons(0, Cons(1, Thunk(func() List { return ZipWith(Plus, Thunk(Fibs), Thunk(func() List { return Tail(Fibs()) })) })))और मुझे अमान्य मेमोरी एड्रेस की त्रुटि मिली
मिंग-तांग

1
जब से आप अभी भी सीख रहे हैं गो: आप सूचियों और थ्रो के लिए अलग-अलग प्रकार, आदि के लिए इंटरफेस का उपयोग करके इससे कुछ अधिक सुरुचिपूर्ण कोड बना सकते हैं
cthom06

3

क्रिस्टल

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

कक्षाओं के साथ, मैं निर्माता कार्यों बनाया lnil, consऔर thunk। मैंने पहले कभी भी रूबी को 20-लाइन से अधिक स्क्रिप्ट के लिए उपयोग नहीं किया है, या तो, इसलिए ब्लॉक सामान ने मुझे काफी दूर फेंक दिया।

मैं गो उत्तर से fibसमारोह आधारित हूं ।

class InvalidNodeException < Exception
end

abstract class LazyValue
end

class LNil < LazyValue
    def empty?
        true
    end

    def force!
        self
    end

    def head
        raise InvalidNodeException.new "cannot get head of LNil"
    end

    def tail
        raise InvalidNodeException.new "cannot get tail of Nil"
    end

    def take(n)
        Node.new self
    end
end

class Cons < LazyValue
    def initialize(@car, @cdr)
    end

    def empty?
        false
    end

    def force!
        @cdr.force!
        self
    end

    def head
        @car
    end

    def tail
        @cdr
    end

    def take(n)
        Node.new n > 0 ? Cons.new @car, @cdr.take n-1 : LNil.new
    end
end

class Thunk < LazyValue
    def initialize(&@func : (-> Node))
    end

    def empty?
        raise Exception.new "should not be here!"
    end

    def force!
        @func.call()
    end

    def head
        self.force!.head
    end

    def tail
        self.force!.tail
    end

    def take(n)
        self.force!.take n
    end
end

class Node
    def initialize(@value = LNil.new)
    end

    def empty?
        self.force!
        @value.empty?
    end

    def force!
        @value = @value.force!
        self
    end

    def head
        self.force!
        @value.head
    end

    def tail
        self.force!
        @value.tail
    end

    def take(n)
        self.force!
        return @value.take n
    end

    def print
        cur = self
        while !cur.empty?
            puts cur.head
            cur = cur.tail
        end
    end
end

def lnil
    Node.new LNil.new
end

def cons(x, r)
    Node.new Cons.new x, r
end

def thunk(&f : (-> Node))
    Node.new Thunk.new &f
end

def inf(st=0)
    # a helper to make an infinite list
    f = ->() { lnil }
    f = ->() { st += 1; cons st, thunk &f }
    thunk { cons st, thunk &f }
end

def zipwith(a, b, &f : Int32, Int32 -> Int32)
    thunk { a.empty? || b.empty? ? lnil :
            cons f.call(a.head, b.head), zipwith a.tail, b.tail, &f }
end

def fibs
    # based on the Go answer
    fibs2 = ->(a : Int32, b : Int32) { lnil }
    fibs2 = ->(a : Int32, b : Int32) { cons a+b, thunk { fibs2.call b, a+b } }
    cons 0, cons 1, thunk { fibs2.call 0, 1 }
end

fibs.take(40).print
zipwith(inf, (cons 1, cons 2, cons 3, lnil), &->(a : Int32, b : Int32){ a+b }).print

2

मैं नियमों को थोड़ा झुकता हूं क्योंकि अभी तक यहां एक .NET समाधान नहीं हुआ है - या अधिक सामान्यतः ओओपी समाधान पायथन में एक को छोड़कर जो विरासत का उपयोग करता है, लेकिन यह मेरे समाधान से अलग है दोनों को दिलचस्प बनाने के लिए (विशेष रूप से पायथन के बाद से) selfउदाहरण को संशोधित करने की अनुमति देता है , जिससे थंक कार्यान्वयन सीधा होता है)।

तो यह C # है । पूर्ण प्रकटीकरण: मैं कहीं भी सी # में एक शुरुआत के पास नहीं हूं, लेकिन मैंने थोड़ी देर में भाषा को नहीं छुआ है क्योंकि मेरे पास वर्तमान में नौकरी के लिए इसका कोई उपयोग नहीं है।

मुख्य बिंदु:

  • सभी वर्गों ( Nil, Cons, Thunk), एक आम सार आधार वर्ग से निकाले जाते हैं List

  • Thunkक्लास का उपयोग लिफाफा-पत्र पैटर्न। यह अनिवार्य रूप self.__class__ = node.__class__से पायथन स्रोत में असाइनमेंट का अनुकरण करता है , क्योंकि thisसंदर्भ को # में संशोधित नहीं किया जा सकता है।

  • IsEmpty, Headऔर Tailगुण हैं।

  • सभी उपयुक्त फ़ंक्शंस को पुनरावर्ती और लेज़ीली ( Printजिसे छोड़कर , आलसी नहीं किया जा सकता है) को थ्रक्स वापस करके लागू किया जाता है। उदाहरण के लिए, यह है Nil<T>.ZipWith:

    public override List<T> ZipWith(Func<T, T, T> func, List<T> other) {
        return Nil();
    }
    

    … और यह है Cons<T>.ZipWith:

    public override List<T> ZipWith(Func<T, T, T> func, List<T> other) {
        return Thunk(() => {
            if (other.IsEmpty)
                return Nil();
    
            return Cons(func(Head, other.Head), Tail.ZipWith(func, other.Tail));
        });
    }
    

    दुर्भाग्य से, C # का कोई प्रेषण नहीं है, अन्यथा मैं ifकथन से छुटकारा भी पा सकता था । काश, कोई पासा नहीं।

अब, मैं वास्तव में अपने कार्यान्वयन से खुश नहीं हूँ। मैं अब तक खुश हूं क्योंकि उपरोक्त सभी पूरी तरह से सीधे हैं। लेकिन । मुझे लगता है कि Fibयह अनावश्यक रूप से जटिल है क्योंकि मुझे इसे काम करने के लिए तर्कों को तर्कों में लपेटने की आवश्यकता है:

List<int> fib = null;
fib = List.Cons(0, List.Cons(1,
    List.ZipWith(
        (a, b) => a + b,
        List.Thunk(() => fib),
        List.Thunk(() => fib.Tail))));

(यहाँ, List.Cons, List.Thunkऔर List.ZipWithसुविधा रैपर कर रहे हैं।)

मैं यह समझना चाहूंगा कि निम्न आसान परिभाषा काम क्यों नहीं कर रही है:

List<int> fib = List.Cons(0, List.Cons(1, List.Nil<int>()));
fib = fib.Concat(fib.ZipWith((a, b) => a + b, fib.Tail));

Concatबेशक एक उपयुक्त परिभाषा दी । यह अनिवार्य रूप से अजगर कोड क्या करता है - लेकिन यह काम नहीं कर रहा है (= एक फिट फेंकना)।

/ संपादित करें: जॉय ने इस समाधान में स्पष्ट दोष को इंगित किया है। हालाँकि, दूसरी पंक्ति को एक थन के साथ बदलने से भी एक त्रुटि उत्पन्न होती है (मोनो segfaults; मुझे एक स्टैक ओवरफ़्लो पर संदेह है जो मोनो अच्छी तरह से नहीं संभालता है):

fib = List.Thunk(() => fib.Concat(fib.ZipWith((a, b) => a + b, fib.Tail)));

पूर्ण स्रोत कोड GitHub पर एक जिस्ट के रूप में पाया जा सकता है


"दुर्भाग्य से, सी # का कोई एक से अधिक प्रेषण नहीं है" - आप घटनाओं का उपयोग करके प्रभाव प्राप्त कर सकते हैं, भले ही वह हैकी हो।
पीटर टेलर

आलसी मूल्यांकन के बारे में विडंबना यह है कि इसे लागू करने के लिए राज्य की आवश्यकता है। fib.ZipWithऔर fib.Tailपुराने का उपयोग करें fib, जो रहता है [0,1]और बदलता नहीं है। इस प्रकार, आप प्राप्त करते हैं [0,1,1](मुझे लगता है), और आपका Takeकार्य आपको शून्य से लेने नहीं देता (हास्केल के ले करता है, हालांकि)। कोशिश करें कि दूसरी लाइन के पंजे को एक थंक में लपेटें, इसलिए यह fibपुराने के बजाय नए को संदर्भित करेगा ।
जॉय एडम्स

@Peter हाँ; आप कई प्रेषण लागू करने के लिए विज़िटर पैटर्न का भी उपयोग कर सकते हैं लेकिन मैं चाहता था कि समाधान सरल रहे।
कोनराड रुडोल्फ

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

2

पिको

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

{ 
` scheme's srfi-45 begins here `

  _lazy_::"lazy";
  _eager_::"eager";

  lazy(exp())::[[_lazy_, exp]];
  eager(exp)::[[_eager_, exp]];
  delay(exp())::lazy(eager(exp()));

  force(promise)::
    { content:promise[1];
      if(content[1]~_eager_,
        content[2],
        if(content[1]~_lazy_,
          { promise_:content[2]();
            content:promise[1];
            if(content[1]~_lazy_, 
             { content_:promise_[1];
               content[1]:=content_[1];
               content[2]:=content_[2];
               promise_[1]:=content });
            force(promise) })) };

` scheme's srfi-45 ends here `

nil:delay([]);
is_nil(s):size(force(s))=0;
cons(a(),b()):delay([a(),b()]);
head(s):force(s)[1];
tail(s):force(s)[2];

zipWith(f,a,b):
  lazy(if(is_nil(a)|is_nil(b),
         nil,
         cons(f(head(a),head(b)), zipWith(f,tail(a),tail(b)))));

fibs:void;
fibs:=cons(0, cons(1, zipWith(+,fibs,tail(fibs))));

take(c,s):
  lazy(if((c=0)|(is_nil(s)),
         nil,
         cons(head(s),take(c-1,tail(s)))));

print(s):
  { comma(s):
      if(is_nil(s),
        void,
        { display(head(s));
          if(!(is_nil(tail(s))), display(","));
          comma(tail(s)) });
    display("[");
    comma(s);
    display("]");
    void };

print(take(40,fibs))

}

इस तरह उत्पादन दिखता है: (लेकिन कैसे पर निर्भर करता है tpico। समझौता है उसमें अधिक दोहरे उद्धरण चिह्नों हो सकता है display। सामान्य रूप से उद्धरण के साथ तार प्रिंट यानी की सब दिखावे [, ,, ]जैसे उनके आसपास उद्धरण के लिए होता है "["।)

[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986]<void>

tpico में पूर्णांक डेटाटाइप की सीमाओं के कारण यह 45 वीं (या 46 वीं ऑफसेट) फाइबोनैचि संख्या की गणना करने में विफल रहता है।

ध्यान दें कि tpico 2.0pl11 उस में टूट गया है begin(a,b) (जो आमतौर पर लिखा जाता है {a;b}) और ifफ़ंक्शन पूंछ पुनरावर्ती नहीं है। यह उल्लेख करने के लिए नहीं कि यह पता लगाने में मुझे 5 साल लग गए कि beginपूंछ पुनरावर्ती क्यों नहीं थी। उस समय भी मैंने पिको में srfi-45 का अनुवाद लिखा था। यह पता चला कि प्रतीक्षा करने की आवश्यकता नहीं होने beginसे bपहले लौटने के मूल्य के लिए इंतजार कर रहा था। और एक बार मुझे लगता है कि मैं भी ठीक करने में सक्षम था ifक्योंकि यह एक ही समस्या थी। और यह अन्य त्रुटि थी जिसने मेटा स्तर के कंस्ट्रक्टर को makeनिष्क्रिय कर दिया था।

पिको फ़ंक्शन को नियंत्रित करने देता है यदि फ़ंक्शन को कॉल करने से पहले उसके तर्क का मूल्यांकन किया जाता है या केवल थ्रेड के रूप में पैक किया जाता है। इस कोड के लिए, मैं फ़ंक्शन द्वारा कॉल की विषमताओं पर विचार कर सकता हूं ।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.