অলস তালিকাগুলি প্রয়োগ করুন, পছন্দসই ভাষায় আপনি ভাল জানেন না [বন্ধ]


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]
      ( :হাস্কেলের কনস অপারেটর)
    • থাঙ্ক - একটি স্থগিত গণনা যা প্রয়োজন হলে তালিকার নোড তৈরি করে।
  • এটি নিম্নলিখিত ক্রিয়াকলাপগুলিকে সমর্থন করে:
    • শূন্য - একটি খালি তালিকা তৈরি করুন।
    • কনস - একটি কনস সেল গঠন করুন।
    • থাঙ্ক - একটি থান্ক তৈরি করুন, এমন কোনও ফাংশন দেওয়া হয়েছে যা কোনও আর্গুমেন্ট নেয় না এবং একটি নীল বা কনস ফেরত দেয়।
    • বল - একটি তালিকা নোড দেওয়া:
      • যদি এটি শূন্য বা কনস হয়, কেবল এটিকে ফেরত দিন।
      • যদি এটি একটি থাঙ্ক হয়, তবে নীল বা কনস পেতে তার ফাংশনটিতে কল করুন। থঙ্কটিকে সেই নীল বা কনসের সাথে প্রতিস্থাপন করুন এবং এটি ফিরিয়ে দিন।
        দ্রষ্টব্য: থাবকে তার জোর করে মান দিয়ে প্রতিস্থাপন করা "অলস" সংজ্ঞাটির একটি গুরুত্বপূর্ণ অঙ্গ । যদি এই পদক্ষেপটি এড়ানো যায় তবে উপরের ফিবোনাকির অ্যালগোরিদমটি খুব ধীর হবে।
    • খালি - একটি তালিকা নোড নীল কিনা তা দেখুন (এটি চাপানোর পরে)।
    • হেড (ওরফে "গাড়ি") - তালিকার প্রথম আইটেমটি পান (বা কোনও শিট যদি এটি নিল হয়)।
    • লেজ (ওরফে "সিডিআর") - একটি তালিকার মাথার পরে উপাদানগুলি পান (বা এটি নিলে হলে কোনও ফিট নিক্ষেপ করুন)।
    • জিপউইথ - একটি বাইনারি ফাংশন দেওয়া (যেমন (+)) এবং দুটি (সম্ভবত অসীম) তালিকাগুলি তালিকাগুলির সংশ্লিষ্ট আইটেমগুলিতে প্রয়োগ করুন। উদাহরণ:
      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))
      

      দ্রষ্টব্য: হাস্কেলের অ-কঠোর মূল্যায়ন অফ সীমা নয়, তবে আপনার অলস তালিকাগুলির প্রয়োগটি সেখান থেকে সরাসরি তার ক্ষমতা অর্জন করা উচিত নয়। প্রকৃতপক্ষে, একটি দক্ষ, খাঁটি কার্যকরী সমাধান দেখার জন্য আগ্রহী হবে যার জন্য অলসতার প্রয়োজন নেই।

    • পাইথন:

      • ইটারটুলগুলি ব্যবহার করবেন না।
      • জেনারেটরগুলি ঠিক আছে, তবে আপনি সেগুলি ব্যবহার করুন, আপনাকে জোর করে মানগুলি স্মরণ করার জন্য কোনও উপায় খুঁজে বের করতে হবে।

zipWithবিভিন্ন দৈর্ঘ্যের দুটি তালিকায় কল করার সময় আচরণটি কী হওয়া উচিত ?
বলফা

@ বালফা: আমি হাস্কেলস আচরণটি বেছে নিয়েছি: তালিকার কোনওটি যদি শূন্য হয়, তবে শূন্য করুন।
FUZxxl

@ বালফা: হাস্কেল-এ, জিপউইথ থামবে যখন দুটি আইটেমের তালিকা শেষ হবে না। সুতরাং zipWith (+) [1,2,3,4,5] [0,0,0] == [1,2,3],। তবে উপরের ফিবোনাচি অ্যালগরিদমের পক্ষে এটি কোনও ব্যাপার নয় কারণ জিপবিথের উভয় যুক্তিই অসীম তালিকা।
জোয়ে অ্যাডামস

এই চ্যালেঞ্জটির এতে একটি গোপন আশ্চর্য ছিল: এটি fibsসঠিকভাবে প্রয়োগ করার জন্য আপনাকে সঠিকভাবে প্রয়োগ করার জন্য বিশেষ কিছু করা উচিত । আমি অলস পুনরাবৃত্তির বিষয়ে বিস্তারিত জানাতে প্রশ্নটি আপডেট করেছি। এফইউজেডএক্সএক্সএল এটি নিজেই খুঁজে পেয়েছিল।
জোয়ে অ্যাডামস

আপনি যখন একটি বড় তালিকা মুদ্রণ করেন তখন "ক্রমবর্ধমানভাবে কাজ করা" বলতে কী বোঝায়?
লোজ্যাকার

উত্তর:


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

পলিমারফিজম সম্পর্কিত: পোস্টস্ক্রিপ্ট দৃ strongly়ভাবে টাইপ করা থাকলেও এটি অভিধানের মান হিসাবে স্বেচ্ছাসেবী প্রকারকে মঞ্জুরি দেয়, তাই আপনি নিজের পছন্দ মতো কিছুতে ফেলে দিতে পারেন:

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প্রত্যাবর্তিত মানগুলি স্মরণ করতে পারে ?
জোয়ে অ্যাডামস

@ জোয়ে অ্যাডামস: এটি সত্যই করে। কোনও থাঙ্ককে মূল্যায়ন করার পরে, copyঅপারেটর মূল্যায়িত সংস্করণটির বিষয়বস্তু মূল, ওভাররাইটিং /typeএবং সম্ভবত অন্যান্য মানগুলি সেট করে অনুলিপি করে । আমাদের কাছে nilবা না হওয়া পর্যন্ত পুনরাবৃত্তিমূলক মূল্যায়ন করার পরে consএটি (মাধ্যমে undef) মুছে ফেলা হয় /funcএবং যেখানে প্রযোজ্য সেখানে /data। শেষ পদক্ষেপটি কঠোরভাবে প্রয়োজনীয় নয় ( /funcএবং /dataকেবল এড়ানো হবে), তবে এই পদক্ষেপটি
ছাড়লে

6

সি

আমি সি-তে মোট শিক্ষানবিস, এই কোডটি আসলে সি-তে কোড করা প্রথম আসল জিনিস এটি কোনও সতর্কতা ছাড়াই সংকলন করে আমার সিস্টেমে সূক্ষ্মভাবে চালায়।

কি করে নির্মাণ করতে হবে

প্রথমে, আমার সার্ভার থেকে টার্বলটি আনুন । makeএটিতে একটি মেকফাইল অন্তর্ভুক্ত রয়েছে, তাই এটি তৈরির make runজন্য চালান এবং তারপরে এটি চালান। প্রোগ্রামটি পরে প্রথম 93 ফিবোনাচি সংখ্যার একটি তালিকা মুদ্রণ করে। (94 নম্বরের পরে, স্বাক্ষরবিহীন bit৪ বিট পূর্ণসংখ্যার ওভারফ্লো)

ব্যাখ্যা

প্রোগ্রাম কোর ফাইল হয় 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, যেটি ফিট করতে পারে তাই পরিবর্তন করতে পারে।
  • তালিকার সুনির্দিষ্টতার বাইরে থেকে কেউ কেবল বিমূর্তভাবে ব্যবহার করতে পারে, তবে এটি করা কোডটি আরও জটিল করে তুলবে।
  • আমার কোডের যে অংশগুলি ভাল সি নয় তা উন্নত করতে পারে One

বিশেষ করে সি ফার্স্ট টাইমার হওয়ার জন্য দুর্দান্ত জমা দেওয়া। পলিমারফিজম সম্পর্কে, আপনি যদি আপনার সমস্ত সামগ্রী গাদাতে বরাদ্দ করতে ইচ্ছুক হন তবে আপনি void*ধরণের হিসাবে ব্যবহার করতে পারেন content_t
কেসি

@ ক্যাসি: আপনাকে অনেক ধন্যবাদ। আমি void*খুব ব্যবহার করার কথা ভেবেছিলাম , তবে আমি ভেবেছিলাম যে টাইপ সিস্টেমটি খুব দূরে সরিয়ে ফেলবে। টেমপ্লেট ব্যবহার করে কি তা সম্ভব নয়?
FUZxxl

সি এর টেমপ্লেট নেই, এটি সি ++, তবে হ্যাঁ আপনি জেনেরিক করতে সি ++ টেম্পলেট ব্যবহার করতে পারেন।
কেসি

এগুলি কীভাবে ব্যবহার করতে হয় তা আমি জানি না। তবে আমার ধারণা, এটি কেবল টাইপ সিস্টেমের ক্ষেত্রে সীমাবদ্ধ। - আমি এমনকি void*বন্ধুদের এবং বন্ধুরা ছাড়া এই প্রোগ্রামটি কোড করতে সক্ষম হইনি ।
FUZxxl

1
"সদস্যটি kindএকটি ট্যাগের মতো।" আপনি কেবল এটি কল করতে পারেন tag, কারণ এটি ধারণার জন্য একটি দুর্দান্ত স্বীকৃত শব্দ (যেমন ট্যাগযুক্ত ইউনিয়ন , স্পাইনলেস ট্যাগলেস জি-মেশিন । অন্যদিকে, "ধরনের" এর একটি আলাদা অর্থ রয়েছে । Haskell, প্রসঙ্গ: একটি ধরণ Intধরনের হয়েছে *, []সদয় হয়েছে * -> *, এবং (,)ধরনের রয়েছে * -> * -> *
জোয়ি অ্যাডামস

5

সি ++

এটি আমি এখন পর্যন্ত সি ++ তে সবচেয়ে বড় জিনিস লিখেছি। আমি সাধারণত অবজেক্টিভ-সি ব্যবহার করি।

এটি বহুমুখী তবে এটি কখনও কিছুই মুক্ত করে না।

আমার 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
আক্ষরিকভাবে "একটি ফিট নিক্ষেপ" নেওয়ার জন্য দুর্দান্ত কাজ এবং ধন্যবাদ :-) আমি কোনও উপায়েই সি ++ বিশেষজ্ঞ নই, তবে আরও একটি সি ++ - থাঙ্ক বাস্তবায়নের উপায় হ'ল কোনও ফাংশন অবজেক্ট (ওরফে "ফান্টেক্টর") ব্যবহার করা হতে পারে (যে হয়, জমিদার ()অপারেটর), এবং ব্যবহার উত্তরাধিকার করার জন্য ব্যবহার করা এড়াতে void*এটি করার তুচ্ছ উদাহরণের জন্য এখানে দেখুন
জোয়ে অ্যাডামস 21

সম্পূর্ণ উত্স লিঙ্কটি এখন মারা গেছে। আপনি কি এটি আবার আপলোড করতে পারেন? gist.github.com এটি স্থাপন করার জন্য একটি ভাল জায়গা।
জোয় অ্যাডামস

@ জোয়্যা অ্যাডামস: সম্পন্ন হয়েছে।
মেরিনাস

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 ব্যতিক্রমটিকে হিট করে, যা আপাতদৃষ্টিতে অবধি অবৈধ যুক্তি __ যোগ__। বড় পূর্ণসংখ্যার সমর্থন করতে, করুনfib.append(fib.zip_with(lambda a,b: a+b, fib.tail()))
জোয় অ্যাডামস 23

1
কেন আপনি খালি বা শঙ্কায় যুক্ত করতে পারবেন না?
পাইরুলেজ

4

চুনি

আমার প্রথম রুবি প্রোগ্রাম। আমরা অ্যারে হিসাবে সমস্ত নোড উপস্থাপন করি যেখানে অ্যারের দৈর্ঘ্য প্রকারটি নির্ধারণ করে:

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

কোডটি তখন খুব সোজা, পুনরাবৃত্তিযোগ্য ফাইব সেট আপ করার জন্য থঙ্ক ফাংশনটি পুনরায় সেট করতে একটি হ্যাক সহ is

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+F আইএন দিয়ে শিখেছি ।

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ফাংশনটি কাজ করে না কারণ গো কঠোর মূল্যায়ন ব্যবহার করে এবং 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

স্ফটিক

গিটহাবের সংগ্রহশালা অনুসরণ করেও, আমি আসলে এখনও কখনও ক্রিস্টাল ব্যবহার করি নি । ক্রিস্টাল হ'ল স্ট্যাটিকালি-টাইপযুক্ত রুবি বৈকল্পিক যা সম্পূর্ণ টাইপ ইনফরমেশন সহ। যদিও ইতিমধ্যে একটি রুবির উত্তর রয়েছে, স্ফটিকের স্ট্যাটিক টাইপিং আমাকে নোডগুলি উপস্থাপন করার জন্য অ্যারের পরিবর্তে পলিমারফিজম ব্যবহার করতে পরিচালিত করে। যেহেতু ক্রিস্টাল পরিবর্তনের অনুমতি দেয় না 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

আমি নিয়মগুলি কিছুটা বক্র করলাম কারণ এখানে এখনও একটি নেট সমাধান নেই - বা পাইথনের উত্তরাধিকার ব্যবহার করে এমন একটি ব্যতীত সাধারণত একটি ওওপি সমাধান, তবে উভয় আকর্ষণীয় করে তোলার জন্য এটি আমার সমাধান থেকে যথেষ্ট আলাদা (বিশেষত পাইথনের পর থেকে selfথাঙ্ক বাস্তবায়ন সোজা করে তোলে, উদাহরণটি পরিবর্তন করতে দেয় ।

সুতরাং এটি সি # । সম্পূর্ণ প্রকাশ: আমি সি # তে কোনও শিক্ষানবিশের কাছাকাছি কোথাও নেই তবে বর্তমানে চাকরিতে এটির কোনও ব্যবহার নেই বলে কিছুক্ষণের মধ্যে আমি ভাষাটি স্পর্শ করতে পারি নি।

মূল বিষয়গুলি:

  • সকল শ্রেণীর ( 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));
        });
    }
    

    দুর্ভাগ্যক্রমে, সি # এর একাধিক প্রেরণ নেই, অন্যথায় আমি 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অবশ্যই একটি যথাযথ সংজ্ঞা দেওয়া । পাইথন কোডটি মূলত এটিই করে - তবে এটি কাজ করে না (= একটি ফিট নিক্ষেপ)।

/ সম্পাদনা: জোয় এই সমাধানের স্পষ্ট ত্রুটি নির্দেশ করেছেন। তবে, দ্বিতীয় লাইনটি একটি থাঙ্কের সাথে প্রতিস্থাপন করলে ত্রুটিও পাওয়া যায় (মনো সেগফাল্টস; আমি স্ট্যাকের ওভারফ্লো সন্দেহ করি যা মনোো ভালভাবে পরিচালনা করতে পারে না):

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

সম্পূর্ণ উত্স কোডটি গিটহাবের টুকরো হিসাবে পাওয়া যাবে


"দুর্ভাগ্যক্রমে, সি # এর কোনও একাধিক প্রেরণ নেই" - আপনি ইভেন্টগুলি ব্যবহার করে প্রভাবটি পেতে পারেন, এটি হ্যাকিং হলেও।
পিটার টেলর

অলস মূল্যায়নের ব্যঙ্গাত্মক বিষয়টি হ'ল এর বাস্তবায়নের জন্য রাষ্ট্রের প্রয়োজন। fib.ZipWithএবং fib.Tailপুরানোটি ব্যবহার করুন fib, যা থেকে যায় [0,1]এবং পরিবর্তিত হয় না। সুতরাং, আপনি পাবেন [0,1,1](আমার মনে হয়), এবং আপনার Takeফাংশন আপনাকে শূন্য থেকে নিতে দেয় না ( যদিও হাস্কেলের গ্রহণ গ্রহণ করে)। দ্বিতীয় লাইনের অনুপাতটি একটি শাঁকে মুড়ে ফেলার চেষ্টা করুন, সুতরাং এটি পুরানোের চেয়ে নতুনটির উল্লেখ করবে fib
জোয়ে অ্যাডামস 21

@ পিটার হ্যাঁ; আপনি একাধিক প্রেরণ প্রয়োগ করতে ভিজিটর প্যাটার্নটিও ব্যবহার করতে পারেন তবে আমি সমাধানটি সহজ থাকতে চেয়েছিলাম।
কনরাড রুডল্ফ

@ জোয়ে দুহ এখন অন্ধভাবে স্পষ্ট। তবে, থাঙ্ক সমাধানটি এখনও কাজ করে না (আপডেট উত্তর দেখুন) তবে আমি এখন তদন্ত করতে খুব ব্যস্ত।
কনরাড রুডলফ

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। patched হয় এটা আরও উদ্ধৃতি চিহ্ন থাকতে পারে 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>

টিপিকোতে পূর্ণসংখ্যার ডেটাটাইপের সীমাবদ্ধতার কারণে এটি 45 তম (বা 46 তম অফসেট) ফিবোনাচি নম্বর গণনা করতে ব্যর্থ হয়।

নোট করুন যে tpico 2.0pl11 এতে ভাঙা হয়েছে begin(a,b)(যা সাধারণত হিসাবে লেখা হয় {a;b}) এবং ifফাংশনটি পুরাপুরি পুনরাবৃত্ত হয় না। beginলেজ পুনরাবৃত্তি কেন হয়নি তা নির্ধারণ করতে আমার 5 বছর লেগেছিল তা উল্লেখ করার দরকার নেই । এছাড়াও আমি পিকোতে srfi-45 এর অনুবাদ লিখেছিলাম। দেখা গেল যে প্রত্যাবর্তনের আগে যখন ফিরে আসার আগে এটির beginমূল্য অপেক্ষা করছিল b। এবং একবার আমি পেয়েছি যে আমিও ঠিক করতে সক্ষম হলাম ifকারণ এটি একই সমস্যা ছিল। এবং এই অন্যান্য ত্রুটিটি ছিল যা মেটা স্তরের নির্মাণকারীকে makeনিষ্ক্রিয় করে তুলেছে ।

পিকো কোনও ফাংশনটি নিয়ন্ত্রণ করতে দেয় যদি ফাংশনটি ডাকা বা কেবল থঙ্কস হিসাবে প্যাকেজ করার আগে তার যুক্তিগুলি মূল্যায়ন করা হয়। এই কোডটির জন্য, আমি ফাংশন দ্বারা কলের বিজোড়তার উপর উপবৃত্ত করতে পারি ।

পিকোর কোনও প্রকার অনুকরণ নেই। আমি এটি সম্পর্কে কিছুক্ষণ ভেবেছিলাম তবে ফাংশন দ্বারা কল করার অদ্ভুততার কারণে আমি একটি সমস্যায় পড়েছি । আমি বিবৃতিটি নিয়ে এসেছি যে প্রকারগুলি অবশ্যই আবদ্ধ পরিবর্তনশীল নামের অস্তিত্বকে এনকোড করে । তবে আমি মূলত চিন্তা করছিলাম কীভাবে কোনও হস্তান্তর ছাড়াই পিকোর একটি উপসেটটিতে হিন্ডলি-মিলনার ধরণের সূত্রটি অভিযোজিত করা যায়। মূল ধারণাটি ছিল যে একাধিক সম্ভাব্য বাঁধাই যদি টাইপ চেকার একাধিক সম্ভাব্য স্কিমগুলি ফেরত দেয় এবং কমপক্ষে একটি সম্ভাব্য টাইপ স্কিম থাকলে টাইপ চেক সফল হয় । একটি সম্ভাব্য স্কিমটি হ'ল কোনও ধরণের নিয়োগের দ্বন্দ্ব নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.