পরিবর্তনীয় অবস্থা ব্যতীত আপনি কীভাবে দরকারী কিছু করতে পারেন?


265

আমি ইদানীং ফাংশনাল প্রোগ্রামিং সম্পর্কে প্রচুর স্টাফ পড়ছি, এবং আমি এর বেশিরভাগটি বুঝতে পারি, তবে যে জিনিসটি আমি কেবল আমার মাথাটি গুটিয়ে রাখতে পারি না তা হল রাষ্ট্রহীন কোডিং। আমার কাছে মনে হয়েছে যে পরিবর্তনীয় স্থিতি মুছে ফেলার মাধ্যমে প্রোগ্রামিংকে সরলীকরণ করা ড্যাশবোর্ড অপসারণ করে একটি গাড়ি "সরলকরণ" এর মতো: সমাপ্ত পণ্যটি সহজ হতে পারে তবে ভাগ্যবান এটি এটিকে শেষ ব্যবহারকারীদের সাথে যোগাযোগ করে।

আমি যে প্রতিটি ব্যবহারকারীর অ্যাপ্লিকেশন সম্পর্কে ভাবতে পারি তার মধ্যে একটি মূল ধারণা হিসাবে রাষ্ট্র জড়িত। আপনি যদি কোনও দস্তাবেজ (বা একটি এসও পোস্ট) লিখেন তবে প্রতিটি নতুন ইনপুট দিয়ে রাষ্ট্র পরিবর্তন করে। বা আপনি যদি কোনও ভিডিও গেম খেলেন, সেখানে প্রচুর অক্ষরগুলির অবস্থানের সাথে শুরু করে প্রচুর রাষ্ট্রীয় চলক রয়েছে, যারা নিয়মিত ঘুরে বেড়ায়। পরিবর্তিত মূল্যবোধের ট্র্যাক না রেখে আপনি কীভাবে দরকারী কিছু করতে পারেন?

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

সম্পাদনা: এখন পর্যন্ত বেশ কয়েকটি জবাব আমাকে অপরিবর্তনীয় মূল্যবোধের সুবিধাগুলি সম্পর্কে বোঝানোর চেষ্টা করছে বলে মনে হচ্ছে। আমি সেই অংশটি পাই এটি নিখুঁত জ্ঞান দেয়। আমি যা বুঝতে পারি না তা হ'ল আপনি কীভাবে পরিবর্তনশীল ভেরিয়েবলগুলি ছাড়াই পরিবর্তন করতে হবে এবং ক্রমাগত পরিবর্তন করতে হবে এমন মানগুলিকে ট্র্যাক রাখতে পারেন।



1
আমার ব্যক্তিগত নম্র মতামত এটি শক্তি এবং অর্থের মতো। হ্রাস রিটার্ন আইন প্রয়োগ। আপনি যদি মোটামুটি শক্তিশালী হন তবে সামান্য শক্তিশালী হওয়ার জন্য কিছুটা উত্সাহ দেওয়া হতে পারে তবে এটিতে কাজ করা ক্ষতিগ্রস্থ হয় না (এবং কিছু লোক আবেগের সাথে করেন)। একই বৈশ্বিক পরিবর্তনীয় রাষ্ট্রের ক্ষেত্রে প্রযোজ্য। আমার কোডিং দক্ষতা যেহেতু এগিয়ে চলেছে তা স্বীকার করা আমার ব্যক্তিগত পছন্দ is আমার কোডে বিশ্বব্যাপী পরিবর্তনীয় রাষ্ট্রের পরিমাণ সীমাবদ্ধ করা ভাল। এটি কখনই নিখুঁত হতে পারে না তবে বৈশ্বিক পরিবর্তনীয় রাষ্ট্রকে হ্রাস করার দিকে কাজ করা ভাল।
আতুরস্যামস

অর্থের মতো, একটি বিন্দুতে পৌঁছে যাবে এতে আরও বেশি সময় ব্যয় করা, এখন আর বেশি কার্যকর নয় এবং অন্যান্য অগ্রাধিকার শীর্ষে উঠবে। উদাহরণস্বরূপ, আপনি সম্ভাব্য সর্বাধিক পরিমাণে পৌঁছেছেন (আমার রূপক অনুসারে) এটি কোনও কার্যকর উদ্দেশ্যটি পরিবেশন করতে পারে না এবং এমনকি বোঝা হয়ে উঠতে পারে। তবে এখনও সম্ভবত এটি অপ্রাপ্তযোগ্য লক্ষ্যের দিকে প্রচেষ্টা করা এবং এতে মাঝারি সংস্থাগুলি বিনিয়োগ করা ভাল।
আতুরস্যামস

7
সংক্ষেপে, এফপিতে, ফাংশন কখনই রাষ্ট্র পরিবর্তন করে না। অবশেষে তারা এমন কিছু ফেরত দেবে যা বর্তমান অবস্থাকে প্রতিস্থাপন করে। তবে রাজ্যটি কখনও স্থানে পরিবর্তিত (পরিবর্তিত) হয় না।
জিঙ্গলেস্তুলা

রূপান্তর ছাড়াই রাষ্ট্রীয়তা পাওয়ার উপায় আছে (আমি যা বুঝি তা থেকে স্ট্যাকটি ব্যবহার করে) তবে এই প্রশ্নটি বিন্দুটির পাশেই একটি অর্থে রয়েছে (যদিও এটি দুর্দান্ত)। সংক্ষিপ্তভাবে কথা বলা শক্ত, তবে এখানে এমন একটি পোস্ট রয়েছে যা আশাবাদী আপনার প্রশ্নের উত্তর মিডিয়াম . com/@jbmilgrom/… দেয় । টিএলডিআর হ'ল এমনকি একটি রাষ্ট্রীয় কার্যকরী প্রোগ্রামের শব্দার্থবিজ্ঞানগুলি অপরিবর্তনীয়, তবে প্রোগ্রামের ফাংশনের যোগাযোগ বি / ডাব্লু রান পরিচালনা করা হয়।
jbmilgrom

উত্তর:


166

বা আপনি যদি কোনও ভিডিও গেম খেলেন, সেখানে প্রচুর অক্ষরগুলির অবস্থানের সাথে শুরু করে প্রচুর রাষ্ট্রীয় চলক রয়েছে, যারা নিয়মিত ঘুরে বেড়ায়। পরিবর্তিত মূল্যবোধের ট্র্যাক না রেখে আপনি কীভাবে দরকারী কিছু করতে পারেন?

আপনি যদি আগ্রহী হন তবে এখানে একটি ধারাবাহিক নিবন্ধ রয়েছে যা এরলংয়ের সাথে গেম প্রোগ্রামিংয়ের বর্ণনা দেয়।

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

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

// Imperative
let printTo x =
    for a in 1 .. x do
        printfn "%i" a

// Recursive
let printTo x =
    let rec loop a = if a <= x then printfn "%i" a; loop (a + 1)
    loop 1

এটি খুব সুন্দর নয়, তবে কোনও রূপান্তর ছাড়াই আমরা একই প্রভাব পেয়েছি। অবশ্যই, যেখানেই সম্ভব, আমরা সম্পূর্ণরূপে লুপিং এড়ানো পছন্দ করি এবং এটি কেবল বিমূর্তভাবে দূরে সরিয়ে রাখি:

// Preferred
let printTo x = seq { 1 .. x } |> Seq.iter (fun a -> printfn "%i" a)

Seq.iter পদ্ধতি সংগ্রহের মাধ্যমে গণনা করা এবং প্রতিটি আইটেমের জন্য বেনাম ফাংশন প্রার্থনা করবে। খুব সহজ :)

আমি জানি, মুদ্রণ সংখ্যা হুবহু চিত্তাকর্ষক নয়। তবে আমরা গেমসের সাথে একই পন্থাটি ব্যবহার করতে পারি: সমস্ত স্ট্যাকটি স্ট্যাকের মধ্যে ধরে রাখি এবং পুনরাবৃত্তির কলটিতে আমাদের পরিবর্তনগুলি সহ একটি নতুন অবজেক্ট তৈরি করে। এইভাবে, প্রতিটি ফ্রেম গেমের একটি স্টেটলেস স্ন্যাপশট, যেখানে প্রতিটি ফ্রেম কেবল স্টেটলেস অবজেক্টকে আপডেট করার প্রয়োজন অনুযায়ী কাঙ্ক্ষিত পরিবর্তন সহ একদম নতুন অবজেক্ট তৈরি করে। এর জন্য সিউডোকোড হতে পারে:

// imperative version
pacman = new pacman(0, 0)
while true
    if key = UP then pacman.y++
    elif key = DOWN then pacman.y--
    elif key = LEFT then pacman.x--
    elif key = UP then pacman.x++
    render(pacman)

// functional version
let rec loop pacman =
    render(pacman)
    let x, y = switch(key)
        case LEFT: pacman.x - 1, pacman.y
        case RIGHT: pacman.x + 1, pacman.y
        case UP: pacman.x, pacman.y - 1
        case DOWN: pacman.x, pacman.y + 1
    loop(new pacman(x, y))

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

গেমের যেকোন সংখ্যক অবজেক্ট পর্যন্ত এটি স্কেল করে, কারণ সমস্ত বস্তু (বা সম্পর্কিত বস্তুর সংগ্রহ) তাদের নিজস্ব থ্রেডে রেন্ডার করা যেতে পারে।

আমি যে প্রতিটি ব্যবহারকারীর অ্যাপ্লিকেশন সম্পর্কে ভাবতে পারি তার মধ্যে একটি মূল ধারণা হিসাবে রাষ্ট্র জড়িত।

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

using System;

namespace ConsoleApplication1
{
    static class Stack
    {
        public static Stack<T> Cons<T>(T hd, Stack<T> tl) { return new Stack<T>(hd, tl); }
        public static Stack<T> Append<T>(Stack<T> x, Stack<T> y)
        {
            return x == null ? y : Cons(x.Head, Append(x.Tail, y));
        }
        public static void Iter<T>(Stack<T> x, Action<T> f) { if (x != null) { f(x.Head); Iter(x.Tail, f); } }
    }

    class Stack<T>
    {
        public readonly T Head;
        public readonly Stack<T> Tail;
        public Stack(T hd, Stack<T> tl)
        {
            this.Head = hd;
            this.Tail = tl;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Stack<int> x = Stack.Cons(1, Stack.Cons(2, Stack.Cons(3, Stack.Cons(4, null))));
            Stack<int> y = Stack.Cons(5, Stack.Cons(6, Stack.Cons(7, Stack.Cons(8, null))));
            Stack<int> z = Stack.Append(x, y);
            Stack.Iter(z, a => Console.WriteLine(a));
            Console.ReadKey(true);
        }
    }
}

উপরের কোডটি দুটি অপরিবর্তনীয় তালিকা তৈরি করে, তাদের একটি নতুন তালিকা তৈরি করতে সংযোজন করে এবং ফলাফল সংযোজন করে। অ্যাপ্লিকেশনটিতে কোথাও কোনও পরিবর্তনীয় অবস্থা ব্যবহার করা হয় না। এটি দেখতে কিছুটা ভারী মনে হচ্ছে, তবে এটি কেবল কারণ সি # একটি ভার্চুজের ভাষা। এফ # তে সমতুল্য প্রোগ্রামটি এখানে:

type 'a stack =
    | Cons of 'a * 'a stack
    | Nil

let rec append x y =
    match x with
    | Cons(hd, tl) -> Cons(hd, append tl y)
    | Nil -> y

let rec iter f = function
    | Cons(hd, tl) -> f(hd); iter f tl
    | Nil -> ()

let x = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))
let y = Cons(5, Cons(6, Cons(7, Cons(8, Nil))))
let z = append x y
iter (fun a -> printfn "%i" a) z

তালিকাগুলি তৈরি এবং পরিচালনা করার জন্য কোনও পরিবর্তনীয় প্রয়োজন। প্রায় সমস্ত ডেটা স্ট্রাকচার সহজেই তাদের কার্যকরী সমতুল্যে রূপান্তরিত হতে পারে। আমি এখানে একটি পৃষ্ঠা লিখেছি যা স্ট্যাকস, সারি, বামপন্থী apগল, লাল-কালো গাছ, অলস তালিকাগুলির অপরিবর্তনীয় বাস্তবায়ন সরবরাহ করে। কোডের একক স্নিপেটে কোনও পরিবর্তনীয় স্থিতি নেই। একটি গাছ "রূপান্তর" করতে আমি একটি নতুন নোড তৈরি করতে চাই যা আমি চাই - এটি খুব কার্যকরী কারণ আমার গাছের প্রতিটি নোডের অনুলিপি তৈরি করার দরকার নেই, আমি আমার নতুনতে পুরানোগুলি পুনরায় ব্যবহার করতে পারি গাছ।

আরও তাত্পর্যপূর্ণ উদাহরণ ব্যবহার করে, আমি এই এসকিউএল পার্সারটিও লিখেছিলাম যা সম্পূর্ণ স্টেটলেস (বা অন্তত আমার কোডটি স্টেটলেস, আমি অন্তর্নিহিত লেক্সিং লাইব্রেরি স্টেটলেস কিনা তা জানি না)।

স্টেটলেস প্রোগ্রামিং হ'ল স্টেটফুল প্রোগ্রামিংয়ের মতোই ভাববাদী এবং শক্তিশালী, রাষ্ট্রহীন চিন্তাভাবনা শুরু করার জন্য নিজেকে প্রশিক্ষণ দেওয়ার জন্য একটু অনুশীলন প্রয়োজন। অবশ্যই, "স্টেটলেস প্রোগ্রামিং যখন সম্ভব হয়, স্টেটফুল প্রোগ্রামিং যেখানে প্রয়োজন" বেশিরভাগ অপরিষ্কার কার্যকরী ভাষার মূলমন্ত্র বলে মনে হয়। কার্যকরী পদ্ধতির যতটা পরিষ্কার বা দক্ষ না হয় তখন পরিবর্তনীয়দের পিছনে ফিরে যাওয়ার কোনও ক্ষতি নেই।


7
আমি প্যাকম্যান উদাহরণ পছন্দ করি। তবে এটি একটি সমস্যা সমাধান করতে পারে কেবল অন্যটিকে উত্থাপন করার জন্য: যদি অন্য কোনও কিছু বিদ্যমান প্যাকম্যান অবজেক্টের একটি রেফারেন্স ধারণ করে তবে কী হবে? তারপরে এটি আবর্জনা সংগ্রহ এবং প্রতিস্থাপন করা হবে না; পরিবর্তে আপনি অবজেক্টের দুটি অনুলিপি সহ শেষ করেন, যার মধ্যে একটি অবৈধ। আপনি এই সমস্যাটি কীভাবে পরিচালনা করবেন?
ম্যাসন হুইলারের

9
স্পষ্টতই আপনার নতুন প্যাকম্যান অবজেক্টের সাথে একটি নতুন "অন্য কিছু" তৈরি করা দরকার;) অবশ্যই, আমরা যদি সেই রাস্তাটি খুব বেশি দূরে নিয়ে যাই, তবে প্রতিবার কিছু পরিবর্তন হলে আমরা আমাদের সমগ্র বিশ্বের জন্য অবজেক্টের গ্রাফটি পুনরুদ্ধার করব। এখানে আরও উন্নত পদ্ধতির বর্ণনা দেওয়া হয়েছে ( prog21. دادgum.com/26.html ): বস্তুগুলি নিজের এবং তাদের সমস্ত নির্ভরতা আপডেট করার পরিবর্তে তাদের ইভেন্টের লুপে তাদের রাজ্য সম্পর্কে বার্তা প্রেরণ করা আরও সহজ যা সমস্তটি পরিচালনা করে the আপডেট। গ্রাফের কোন জিনিসগুলি আপডেট করার প্রয়োজন এবং কোনটি না তা স্থির করা এটি আরও সহজ করে তোলে।
জুলিয়েট

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

9
@ ব্লুস্ট্র্যাট - ভাল প্রশ্ন ... যদি এটি "লেজ কল" হয় ... যেমন পুনরাবৃত্তি কলটি ফাংশনটির শেষ জিনিস ... তবে সিস্টেমটিকে একটি নতুন স্ট্যাক ফ্রেম তৈরি করার দরকার নেই ... এটি পারে কেবল আগেরটি পুনরায় ব্যবহার করুন। এটি কার্যকরী প্রোগ্রামিং ভাষার জন্য একটি সাধারণ অপ্টিমাইজেশন। en.wikipedia.org/wiki/Tail_call
reteptilian

4
@ মিশেল ওসফস্কি, ডেটাবেস এবং এপিআই-এর সাথে আলাপকালে, সবসময় একটি 'বাইরের বিশ্বের' থাকে যার সাথে যোগাযোগের রাষ্ট্র থাকে। এই ক্ষেত্রে, আপনি 100% কার্যকরী যেতে পারবেন না। এই 'অযৌক্তিক' কোডটি বিচ্ছিন্ন এবং বিমূর্তভাবে দূরে রাখা গুরুত্বপূর্ণ তাই বাইরের বিশ্বে কেবলমাত্র একটি প্রবেশ এবং এক প্রস্থান রয়েছে। এইভাবে আপনি আপনার বাকী কোডটি কার্যক্ষম রাখতে পারেন।
চিল্ট

76

সংক্ষিপ্ত উত্তর: আপনি পারবেন না।

তাহলে অপরিবর্তনীয়তা নিয়ে গোলমাল কী?

যদি আপনি অপরিহার্য ভাষায় দক্ষ হন তবে আপনি জানেন যে "গ্লোবালগুলি খারাপ are" কেন? কারণ তারা আপনার কোডে কিছু হার্ড-টু-অ্যাটাঙ্গেল নির্ভরতা প্রবর্তন করে (বা পরিচয় করার সম্ভাবনা রয়েছে)। এবং নির্ভরতা ভাল নয়; আপনি আপনার কোডটি মডুলার হতে চান । প্রোগ্রামের অংশগুলি যতটা সম্ভব সামান্য অংশে অন্যান্য অংশগুলিকে প্রভাবিত করে না। এবং এফপি আপনাকে মডিউলারিটির পবিত্র গ্রেলে নিয়ে আসে: কোনও প্রতিক্রিয়া নয় । আপনার সবেমাত্র আপনার f (x) = y রয়েছে। এক্স রাখুন, বের হয়ে আসুন। এক্স বা অন্য কিছুতে কোনও পরিবর্তন নেই। এফপি আপনাকে রাষ্ট্র সম্পর্কে চিন্তাভাবনা বন্ধ করে দেয় এবং মানগুলির বিবেচনায় ভাবতে শুরু করে। আপনার সমস্ত ক্রিয়াকলাপ সহজভাবে মান গ্রহণ করে এবং নতুন মান উত্পাদন করে।

এর বেশ কয়েকটি সুবিধা রয়েছে।

প্রথমত, কোনও পার্শ্ব-প্রতিক্রিয়া মানে সরল প্রোগ্রাম নয়, তর্ক করা সহজ। কোনও উদ্বেগজনক বিষয় নয় যে প্রোগ্রামের একটি নতুন অংশ প্রবর্তন একটি বিদ্যমান, কার্যকারী অংশকে হস্তক্ষেপ এবং ক্রাশ করতে চলেছে।

দ্বিতীয়ত, এটি প্রোগ্রামকে তুচ্ছভাবে সমান্তরাল করে তোলে (দক্ষ সমান্তরালিতা আরেকটি বিষয়)।

তৃতীয়ত, সম্ভাব্য পারফরম্যান্সের কিছু সুবিধা রয়েছে। বলুন আপনার একটি ফাংশন রয়েছে:

double x = 2 * x

এখন আপনি 3 এর মান রেখেছেন এবং আপনি 6 আউট এর মান পাবেন। প্রত্যেকবার. তবে আপনি তাও জরুরীভাবে করতে পারেন, তাই না? হাঁ। তবে সমস্যাটি হ'ল অপরিহার্যভাবে আপনি আরও কিছু করতে পারেন । আমি করতে পারি:

int y = 2;
int double(x){ return x * y; }

তবে আমিও করতে পারি

int y = 2;
int double(x){ return x * (y++); }

অপরিহার্য সংকলকটি জানে না যে আমার পার্শ্ব প্রতিক্রিয়া হবে কি না, যা অনুকূলিতকরণকে আরও কঠিন করে তোলে (যেমন ডাবল 2 প্রতিবার 4 হওয়ার দরকার নেই)। কার্যক্ষম ব্যক্তি জানেন যে আমি করব না - তাই এটি প্রতিবার "ডাবল 2" দেখলে এটি অনুকূলিত করতে পারে।

এখন, যদিও প্রতিটি সময় নতুন মান তৈরি করা কম্পিউটার মেমরির ক্ষেত্রে জটিল ধরণের মানগুলির জন্য অবিশ্বাস্যরূপে অপব্যয়যুক্ত বলে মনে হয়, এটি হওয়ার দরকার নেই। কারণ, যদি আপনার f (x) = y থাকে এবং x এবং y এর মানগুলি "বেশিরভাগ ক্ষেত্রে একই" থাকে (যেমন গাছগুলি কেবল কয়েকটি পাতায় পৃথক হয়) তবে x এবং y মেমরির অংশ ভাগ করতে পারে - কারণ তাদের উভয়ই পরিবর্তিত হবে না ।

সুতরাং যদি এই নিরবচ্ছিন্ন জিনিসটি দুর্দান্ত হয় তবে আমি কেন উত্তর দিলাম যে আপনি পরিবর্তনীয় অবস্থা ব্যতীত দরকারী কোনও কাজ করতে পারবেন না। ঠিক আছে, পরিবর্তনীয়তা ছাড়াই আপনার পুরো প্রোগ্রামটি একটি বিশাল f (x) = y ফাংশন হবে। এবং আপনার প্রোগ্রামের সমস্ত অংশের জন্য এটি একই হবে: কেবলমাত্র ক্রিয়াগুলি এবং এতে "বিশুদ্ধ" অর্থে ফাংশন। আমি যেমন বলেছি, এর মানে হল চ (x) এর y = প্রত্যেক সময়। সুতরাং যেমন রিডফায়ার ("মাইফাইল.টিএসটিএসটি") প্রতিবার একই স্ট্রিংয়ের মান ফেরত দিতে হবে। খুব দরকারী না।

অতএব, প্রতিটি এফপি পরিবর্তনীয় অবস্থার কিছু উপায় সরবরাহ করে । "খাঁটি" কার্যকরী ভাষা (যেমন হাস্কেল) কিছুটা ভীতিজনক ধারণাগুলি যেমন মনাদাদের ব্যবহার করে এটি করে, যখন "অপরিষ্কার "গুলি (যেমন এমএল) এটি সরাসরি অনুমতি দেয়।

এবং অবশ্যই, কার্যকরী ভাষা অন্যান্য গুডির একটি হোস্টের সাথে আসে যা প্রোগ্রামিংকে আরও দক্ষ করে তোলে, যেমন প্রথম শ্রেণির ফাংশন ইত্যাদি etc.


2
<< readFile ("myFile.txt") প্রতিবার একই স্ট্রিংয়ের মান ফেরত দিতে হবে। খুব বেশি কার্যকর নয় >> >> আমি অনুমান করছি যতক্ষণ আপনি গ্লোবাল, একটি ফাইল সিস্টেম লুকাবেন ততক্ষণ এটি কার্যকর। যদি আপনি এটিকে দ্বিতীয় প্যারামিটার হিসাবে বিবেচনা করেন এবং অন্যান্য প্রক্রিয়াগুলি প্রতিবার ফাইল-সিস্টেম 2 = রাইটিং (ফাইলসিস্টেম 1, এফডি, পোজ, "স্ট্রিং") দিয়ে এটি সংশোধন করে ফাইল সিস্টেমে একটি নতুন রেফারেন্স ফিরিয়ে দেয় এবং সমস্ত প্রক্রিয়াগুলিকে ফাইল সিস্টেমের সাথে তাদের রেফারেন্স বিনিময় করতে দিন , আমরা অপারেটিং সিস্টেমের অনেক ক্লিনার ছবি পেতে পারি।
ghল শেইজেজ

@ ইলঘিজেড, এটি ডেটামিকগুলি ডাটাবেসগুলিতে নিয়ে যায় approach
জেসন

1
অনুচ্ছেদের মধ্যে পরিষ্কার এবং সংক্ষিপ্ত তুলনার জন্য +1। একটি পরামর্শ হ'ল int double(x){ return x * (++y); }যেহেতু বর্তমানটি এখনও 4 হবে, যদিও এখনও একটি অযৌক্তিক পার্শ্ব প্রতিক্রিয়া রয়েছে, যেখানে ++y6 ফিরে আসবে
ব্রেইনএফআরজেড

@ ইলঘিইজ আমি কোনও বিকল্প সম্পর্কে নিশ্চিত নই, সত্যিই কি অন্য কেউ? কোনও (খাঁটি-) এফপি প্রসঙ্গে তথ্য প্রবর্তনের জন্য, আপনি "একটি পরিমাপ করুন", যেমন "টাইমস্ট্যাম্প এক্স এ, তাপমাত্রা হ'ল"। যদি কেউ তাপমাত্রার জন্য জিজ্ঞাসা করে, তবে তারা স্পষ্টভাবে X = এখনই বোঝাতে পারে তবে তারা সম্ভবত সময়ের সর্বজনীন কার্যকারিতা হিসাবে তাপমাত্রার জন্য জিজ্ঞাসা করতে পারে না, তাই না? এফপি অপরিবর্তনীয় রাষ্ট্রের সাথে সম্পর্কিত, এবং আপনাকে অভ্যন্তরীণ এবং বাহ্যিক উত্স থেকে - একটি পরিবর্তনীয় থেকে একটি অপরিবর্তনীয় রাষ্ট্র তৈরি করতে হবে। সূচকগুলি, টাইমস্ট্যাম্পগুলি ইত্যাদি দরকারী তবে পরিবর্তনের ক্ষেত্রে অরথোগোনাল - যেমন ভিসিএস হ'ল সংস্করণটি নিজেই নিয়ন্ত্রণ করে।
জন পি

29

নোট করুন যে ফাংশনাল প্রোগ্রামিং বলতে 'স্টেট' না করে কিছুটা বিভ্রান্তিমূলক এবং বিভ্রান্তির কারণ হতে পারে। এটির অবশ্যই কোনও 'পরিবর্তনযোগ্য অবস্থা' নেই, তবে এরপরেও মানগুলি হস্তান্তরিত হতে পারে; সেগুলিকে ঠিক জায়গায় স্থান দেওয়া যায় না (যেমন আপনাকে পুরানো মানগুলি থেকে নতুন মান তৈরি করতে হবে)।

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

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

সংযোজন: (পরিবর্তনের প্রয়োজন মানগুলি কীভাবে ট্র্যাক করা যায় সে সম্পর্কে আপনার সম্পাদনা সম্পর্কে)
সেগুলি অবশ্যই একটি অপরিবর্তনীয় ডেটা কাঠামোতে সংরক্ষণ করা হবে ...

এটি কোনও প্রস্তাবিত 'সমাধান' নয়, তবে এটি সর্বদা কার্যকর হবে তা দেখার সহজ উপায় হ'ল আপনি এই পরিবর্তনশীল মানগুলিকে কাঠামোর মতো একটি মানচিত্রে (অভিধান / হ্যাশটেবল) সংরক্ষণ করতে পারেন, এটি একটি 'পরিবর্তনশীল নাম' দ্বারা চিহ্নিত।

স্পষ্টত ব্যবহারিক সমাধানগুলিতে আপনি আরও বুদ্ধিমান পন্থা ব্যবহার করতে চাইবেন তবে এটি এমন খারাপ পরিস্থিতিটি দেখায় যে যদি অন্য কোনও কাজ না করে আপনি আপনার অনুরোধ গাছের চারপাশে বহন করে এমন মানচিত্রের সাহায্যে 'পরিবর্তন' করতে পারতেন।


2
ঠিক আছে, আমি শিরোনাম পরিবর্তন করেছি। যদিও আপনার উত্তরটি আরও খারাপ সমস্যার দিকে পরিচালিত করে। যদি প্রতিবারের বস্তুটির স্থিতিস্থানে কিছু পরিবর্তন হয় তবে আমি আমার সমস্ত সিপিইউ সময় অবজেক্ট তৈরির বাইরে ব্যয় করব। আমি এখানে গেম প্রোগ্রামিং সম্পর্কে ভাবছি, যেখানে আপনি পর্দায় প্রচুর পরিমাণে ঘুরে বেড়াচ্ছেন (এবং অফ-স্ক্রিন), একে অপরের সাথে ইন্টারঅ্যাক্ট করতে সক্ষম হওয়া প্রয়োজন। পুরো ইঞ্জিনটিতে একটি সেট ফ্রেমরেট রয়েছে: আপনি যা করতে যাচ্ছেন তা, আপনাকে X সংখ্যক মিলিসেকেন্ডে করতে হবে। ক্রমাগত পুরো বস্তু পুনর্ব্যবহার করার চেয়ে ভাল উপায় আছে?
ম্যাসন হুইলারের

4
এর সৌন্দর্য হ'ল অপরিবর্তনীয়তা ভাষার উপর, প্রয়োগের উপর নয়। কয়েকটি কৌশল দ্বারা, আপনি ভাষায় অপরিবর্তনীয় রাষ্ট্র থাকতে পারেন যখন বাস্তবায়নের ক্ষেত্রে বাস্তবে রাষ্ট্রটি পরিবর্তিত হয়। উদাহরণস্বরূপ হাস্কেলের এসটি মোনাদ দেখুন।
সিজারব

4
@ মেসন: বিন্দুটি হ'ল সংকলকটি আরও ভালভাবে সিদ্ধান্ত নিতে পারে যে এটি আপনার চেয়ে স্থানে থাকা অবস্থায় পরিবর্তন করা কোথায় (থ্রেড) নিরাপদ।
jerryjvl

আমি মনে করি গেমসের জন্য আপনার এমন কোনও অংশের জন্য পরিবর্তনহীন এড়ানো উচিত যেখানে গতি কোনও ব্যাপার নয়। একটি অপরিবর্তনীয় ভাষা আপনার জন্য অনুকূলিত করতে পারে, মেমরি যা সিপিইউগুলি দ্রুত করছে তা পরিবর্তন করার চেয়ে দ্রুত আর কিছুই হতে পারে না। এবং তাই যদি এটির সক্রিয় হয় তবে 10 বা 20 টি জায়গাগুলি রয়েছে যেখানে আপনার অপরিহার্য প্রয়োজন আমার মনে হয় আপনি গেম মেনুগুলির মতো খুব বিচ্ছিন্ন অঞ্চলের জন্য এটি পরিমিত করতে না পারলে আপনার কেবলমাত্র অপরিবর্তনীয় এড়ানো উচিত। এবং বিশেষত গেমের যুক্তি অপরিবর্তনীয় ব্যবহারের জন্য দুর্দান্ত জায়গা হতে পারে কারণ আমি মনে করি এটি ব্যবসায়ের নিয়মের মতো খাঁটি সিস্টেমগুলির জটিল মডেলিংয়ের জন্য দুর্দান্ত।
কিংবদন্তি দৈর্ঘ্য

@ লেজেন্ডেল লেংথ আপনি নিজের সাথে বিরোধিতা করছেন।
আইএক্সএক্স

18

আমি মনে করি কিছুটা ভুল বুঝাবুঝি আছে। খাঁটি কার্যকরী প্রোগ্রামগুলির রাষ্ট্র রয়েছে। পার্থক্যটি কীভাবে সেই রাজ্যটিকে মডেল করা হয়। খাঁটি ফাংশনাল প্রোগ্রামিংয়ে, রাষ্ট্রটি এমন কিছু ফাংশন দ্বারা চালিত হয় যা কিছু রাষ্ট্র নেয় এবং পরবর্তী অবস্থানে ফিরে আসে। রাজ্যগুলির মধ্য দিয়ে সিকোয়েন্সিংটি তখন খাঁটি ফাংশনগুলির ক্রম দিয়ে রাজ্যকে পাস করে অর্জিত হয়।

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

আপনি এটি অপরিহার্য প্রোগ্রামিংয়ের ক্ষেত্রে ব্যাখ্যাটি দেখতে চেয়েছিলেন। ঠিক আছে, আসুন একটি কার্যকরী ভাষায় কিছু সহজ জরুরী প্রোগ্রামিং তাকান।

এই কোডটি বিবেচনা করুন:

int x = 1;
int y = x + 1;
x = x + y;
return x;

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

let x = 1 in
let y = x + 1 in
let z = x + y in z 

এর অর্থ কী তা পরিষ্কার করার জন্য প্রথম বন্ধনী রাখুন:

let x = 1 in (let y = x + 1 in (let z = x + y in (z)))

সুতরাং আপনি দেখুন, রাষ্ট্রটি খাঁটি অভিব্যক্তির ক্রম দ্বারা মডেল করা হয় যা নিম্নলিখিত এক্সপ্রেশনগুলির ফ্রি ভেরিয়েবলগুলিকে আবদ্ধ করে।

আপনি দেখতে পাবেন যে এই প্যাটার্নটি কোনও ধরণের রাজ্য এমনকি আইওর মডেল করতে পারে।


মোনাদের মতো কি এমন?
সিএমসিডিগ্রাগনকাই

আপনি কি এটি বিবেচনা করবেন: ক স্তর 1 বি তে ঘোষণামূলক, এটি স্তরটিকে 2 আবশ্যক বলে বিবেচনা করে। সি স্তরের 3 স্তরে ঘোষণামূলক, এটি বিকে আবশ্যক হিসাবে বিবেচনা করে। যেহেতু আমরা বিমূর্ত স্তরটি বাড়িয়ে তুলি, এটি সর্বদা বিমূর্ত স্তরকে নীচের ভাষাগুলি নিজেই অধিক অপরিহার্য বলে মনে করে।
সিএমসিডিগ্রাগনকাই

14

পরিবর্তনীয় অবস্থা ছাড়াই আপনি কোডটি কীভাবে লিখছেন তা এখানে : পরিবর্তিত রাষ্ট্রকে পরিবর্তনশীল ভেরিয়েবলগুলিতে রাখার পরিবর্তে, আপনি এটিকে ফাংশনগুলির পরামিতিগুলিতে রেখেছেন। এবং লুপগুলি লেখার পরিবর্তে আপনি পুনরাবৃত্ত ফাংশন লিখেন। সুতরাং উদাহরণস্বরূপ এই আবশ্যক কোড:

f_imperative(y) {
  local x;
  x := e;
  while p(x, y) do
    x := g(x, y)
  return h(x, y)
}

এই কার্যকরী কোডে পরিণত হয় (প্রকল্পের মতো সিনট্যাক্স):

(define (f-functional y) 
  (letrec (
     (f-helper (lambda (x y)
                  (if (p x y) 
                     (f-helper (g x y) y)
                     (h x y)))))
     (f-helper e y)))

বা এই হাস্কেলিশ কোড

f_fun y = h x_final y
   where x_initial = e
         x_final   = loop x_initial
         loop x = if p x y then loop (g x y) else x

হিসেবে কেন কার্মিক প্রোগ্রামারদের এই কাজ করতে (যা আপনি জিজ্ঞাসা না) পছন্দ করি, আপনার প্রোগ্রাম আরো টুকরা, আড়ম্বরহীন হয় আরো উপায় কিছু বিরতি করেও একসঙ্গে টুকরা করা হয় । রাষ্ট্রবিহীন দৃষ্টান্তের শক্তি নিখরচায় রাষ্ট্রহীনতা (বা বিশুদ্ধতা) এর মধ্যে নেই , তবে এটি আপনাকে শক্তিশালী, পুনরায় ব্যবহারযোগ্য ফাংশন লিখতে এবং সংযুক্ত করার ক্ষমতা দেয় gives

জন হিউজেসের কাগজে কেন কার্যকরী প্রোগ্রামিং ম্যাটারগুলিতে প্রচুর উদাহরণ সহ আপনি একটি ভাল টিউটোরিয়াল খুঁজে পেতে পারেন ।


13

এটি একই জিনিসটি করার বিভিন্ন উপায়।

একটি সহজ উদাহরণ বিবেচনা করুন যেমন 3, 5 এবং 10 সংখ্যা যোগ করুন এবং প্রথমে 3 এর মান পরিবর্তন করে এটি করার বিষয়ে চিন্তাভাবনা করুন, তারপরে "3" তে 10 যুক্ত করে তারপরের বর্তমান মান আউটপুট করুন 3 "(18)। এটি আপত্তিজনকভাবে হাস্যকর বলে মনে হচ্ছে, তবে এটি মূলত রাষ্ট্র-ভিত্তিক অত্যাবশ্যক প্রোগ্রামিং যেভাবে করা হয়। প্রকৃতপক্ষে, আপনার অনেকগুলি "3" গুলি থাকতে পারে যার মান 3 রয়েছে, তবুও আলাদা। এগুলি সমস্তই অদ্ভুত বলে মনে হচ্ছে, কারণ আমরা সংখ্যাগুলি অপরিবর্তনীয়, এই ধারণাটি নিয়ে বেশ প্রচুর বুদ্ধিমান হয়েছি so

যখন আপনি পরিবর্তনগুলি মানগুলি গ্রহণ করেন তখন 3, 5 এবং 10 যোগ করার বিষয়ে ভাবুন। আপনি 8 এবং অন্য কোনও মান উত্পাদন করতে 3 এবং 5 যোগ করেন, তারপরে আপনি সেই মানটিতে 10 যুক্ত করে অন্য কোনও মান উত্পাদন করতে পারেন, 18।

এই একই জিনিস করার সমতুল উপায়। সমস্ত প্রয়োজনীয় তথ্য উভয় পদ্ধতিতেই বিদ্যমান, তবে বিভিন্ন রূপে। একটিতে তথ্য রাষ্ট্র হিসাবে এবং রাষ্ট্র পরিবর্তন করার নিয়ম হিসাবে বিদ্যমান। অপরটিতে তথ্য অপরিবর্তনীয় ডেটা এবং কার্যকরী সংজ্ঞায় বিদ্যমান।


10

আমি আলোচনায় দেরি করেছি, তবে আমি ফাংশনাল প্রোগ্রামিংয়ের সাথে লড়াই করা লোকদের জন্য কয়েকটি পয়েন্ট যুক্ত করতে চেয়েছিলাম।

  1. প্রায়োগিক ভাষায় অনুজ্ঞাসূচক ভাষা হিসেবে সঠিক একই রাষ্ট্র আপডেট বজায় রাখা কিন্তু তারা পরবর্তী ফাংশান কল আপডেট রাষ্ট্র ক্ষণস্থায়ী দ্বারা এটা করতে । এখানে একটি নম্বর লাইন ভ্রমণ খুব সহজ উদাহরণ। আপনার রাষ্ট্রটি আপনার বর্তমান অবস্থান।

প্রথম অপরিহার্য উপায় (সিউডোকোডে)

moveTo(dest, cur):
    while (cur != dest):
         if (cur < dest):
             cur += 1
         else:
             cur -= 1
    return cur

এখন কার্যকরী উপায় (সিউডোকোডে)। আমি টার্নারি অপারেটরের উপর প্রচুর ঝুঁকছি কারণ আমি চাই যে অত্যাবশ্যকীয় ব্যাকগ্রাউন্ডের লোকেরা এই কোডটি পড়তে সক্ষম হন। সুতরাং আপনি যদি টার্নারি অপারেটরটি বেশি ব্যবহার না করেন (আমি সবসময় আমার অপরিহার্য দিনগুলিতে এড়িয়ে চলেছি) এটি এখানে কীভাবে কাজ করে তা এখানে।

predicate ? if-true-expression : if-false-expression

আপনি মিথ্যা-এক্সপ্রেশনটির জায়গায় একটি নতুন ত্রৈমাসিক অভিব্যক্তি রেখে ত্রৈমাসিক ভাবটি শৃঙ্খলাবদ্ধ করতে পারেন

predicate1 ? if-true1-expression :
predicate2 ? if-true2-expression :
else-expression

তাই মনে রেখে, এখানে কার্যকরী সংস্করণ।

moveTo(dest, cur):
    return (
        cur == dest ? return cur :
        cur < dest ? moveTo(dest, cur + 1) : 
        moveTo(dest, cur - 1)
    )

এটি একটি তুচ্ছ উদাহরণ। যদি এটি কোনও গেমের জগতে লোকজনকে ঘুরে বেড়াচ্ছিল, আপনাকে পর্দার উপর অবজেক্টের বর্তমান অবস্থান অঙ্কন এবং বস্তুটি কতটা দ্রুত গতিতে চলেছে তার উপর ভিত্তি করে প্রতিটি কলটিতে কিছুটা বিলম্ব শুরু করার মতো পার্শ্ব প্রতিক্রিয়াগুলি প্রবর্তন করতে হবে। তবে আপনার এখনও পরিবর্তনীয় রাষ্ট্রের প্রয়োজন হবে না।

  1. পাঠটি হ'ল কার্যকরী ভাষাগুলি বিভিন্ন পরামিতিগুলির সাথে ফাংশনটি কল করে "পরিবর্তন" করে state স্পষ্টতই এটি কোনও ভেরিয়েবলকে রূপান্তরিত করে না, তবে আপনি একইরকম প্রভাব পাবেন get এর অর্থ আপনি যদি ক্রিয়ামূলক প্রোগ্রামিং করতে চান তবে আপনাকে পুনরাবৃত্তভাবে চিন্তা করতে অভ্যস্ত হতে হবে।

  2. পুনরাবৃত্তভাবে ভাবতে শেখা কঠিন নয়, তবে এটি অনুশীলন এবং একটি টুলকিট উভয়ই লাগে। "জাভা শিখুন" বইয়ের সেই ছোট্ট বিভাগটি যেখানে তারা ফ্যাক্টরিয়াল গণনা করার জন্য পুনরাবৃত্তি ব্যবহার করেছিল তা এটিকে কাটবে না। আপনার পুনরুত্থানের বাইরে পুনরাবৃত্তি প্রক্রিয়াগুলি তৈরি করার মতো দক্ষতার একটি সরঞ্জামকিট প্রয়োজন (এটি কারণ কার্যকরী ভাষার জন্য লেজ পুনরাবৃত্তি অপরিহার্য), ধারাবাহিকতা, আক্রমণকারী ইত্যাদি You ক্রিয়ামূলক প্রোগ্রামিং জন্য।

আমার সুপারিশটি হ'ল লিটল স্কিমার করা (নোট করুন যে আমি "করি" বলুন এবং "পড়ুন" না) এবং তারপরে এসআইসিতে সমস্ত অনুশীলন করুন। আপনি যখন কাজটি শেষ করেন, তখন আপনার শুরু করার চেয়ে আলাদা মস্তিষ্ক থাকে।


8

বাস্তবে পরিবর্তনযোগ্য রাষ্ট্র ব্যতীত ভাষায় এমন কিছু পাওয়া যায় যা পরিবর্তনীয় রাষ্ট্রের মতো দেখায়।

টাইপ সহ একটি ফাংশন বিবেচনা করুন s -> (a, s)। হাস্কেল সিনট্যাক্স থেকে অনুবাদ করে এর অর্থ একটি ফাংশন যা " s" ধরণের একটি পরামিতি নেয় এবং " a" এবং " s" প্রকারের মানগুলির একটি জোড়া দেয় । তাহলে sআমাদের রাষ্ট্র ধরণ, এই ফাংশন এক রাজ্যের এবং আয় একটি নতুন রাষ্ট্র লাগে, এবং সম্ভবত একটি মান (আপনি সর্বদা "ইউনিট" ওরফে আসতে পারেন (), যা "সমতূল্য সাজানোর void" সি / সি ++ হিসাবে " a" টাইপ)। যদি আপনি বিভিন্ন ধরণের ফাংশনগুলির কলগুলি এই জাতীয় ধরণের (চূড়ান্তভাবে একটি ফাংশন থেকে রাষ্ট্রটিকে ফিরিয়ে আনা এবং পরবর্তীটিতে স্থান দেওয়ার জন্য) শৃঙ্খলাবদ্ধ করে থাকেন তবে আপনার "পরিবর্তনযোগ্য" অবস্থা রয়েছে (বাস্তবে আপনি প্রতিটি ফাংশনে একটি নতুন রাষ্ট্র তৈরি করছেন এবং পুরানোটিকে ত্যাগ করবেন) )।

আপনার প্রোগ্রামটি যে স্থানটি চালাচ্ছে সেখানে "স্থান" হিসাবে পরিবর্তনের স্থিতিটি কল্পনা করে, এবং তারপরে সময়ের মাত্রার কথা চিন্তা করলে এটি বোঝা সহজ হতে পারে। তাত্ক্ষণিক টি 1 এ, "স্পেস" একটি নির্দিষ্ট অবস্থায় রয়েছে (উদাহরণস্বরূপ বলুন কিছু স্মৃতির অবস্থানের মান 5 থাকে)) পরবর্তী তাত্ক্ষণিক টি 2 এ এটি অন্যরকম অবস্থায় রয়েছে (উদাহরণস্বরূপ যে মেমরির অবস্থানের মান এখন 10)। এই সময়ের প্রতিটি "টুকরা" একটি রাষ্ট্র, এবং তা স্থাবর হয় (আপনি এগুলি পরিবর্তন করতে সময় মতো ফিরে যেতে পারবেন না)। সুতরাং, এই দৃষ্টিকোণ থেকে, আপনি পুরো স্পেসটাইম থেকে একটি টাইম অ্যার (আপনার পরিবর্তনীয় অবস্থা) দিয়ে স্পেসটাইমের এক টুকরো সেট (বেশ কয়েকটি অপরিবর্তনীয় রাজ্য) এ গিয়েছিলেন এবং আপনার প্রোগ্রামটি প্রতিটি স্লাইসকে কেবল একটি মান হিসাবে গণ্য করছে এবং প্রতিটিকে গণনা করছে পূর্ববর্তীটিতে প্রয়োগ করা একটি ফাংশন হিসাবে এগুলি of

ঠিক আছে, সম্ভবত এটি বুঝতে সহজ ছিল না :-)

পুরো প্রোগ্রামের স্থিতিকে একটি মান হিসাবে স্পষ্টভাবে উপস্থাপন করা অসুবিধাজনক বলে মনে হতে পারে, যা কেবলমাত্র পরবর্তী তাত্ক্ষণিকভাবে ফেলে দেওয়ার জন্য তৈরি করতে হবে (একটি নতুন তৈরি হওয়ার ঠিক পরে)। কিছু অ্যালগরিদমের জন্য এটি প্রাকৃতিক হতে পারে, কিন্তু যখন এটি না থাকে, তখন অন্য কৌশল আছে। প্রকৃত রাষ্ট্রের পরিবর্তে, আপনি একটি জাল রাষ্ট্র ব্যবহার করতে পারেন যা মার্কার ছাড়া আর কিছুই নয় (আসুন এই নকল রাষ্ট্রের ধরণটি বলি State#)। এই ভুয়া অবস্থাটি ভাষার দৃষ্টিকোণ থেকে বিদ্যমান এবং অন্য যে কোনও মানের মতো পাস করা হয়, তবে মেশিনের কোড তৈরি করার সময় সংকলকটি একে একে বাদ দেয়। এটি কেবল মৃত্যুদন্ড কার্যকর করার ক্রম চিহ্নিত করতে পরিবেশন করে।

উদাহরণস্বরূপ, ধরুন সংকলকটি নিম্নলিখিত ফাংশনগুলি আমাদের দেয়:

readRef :: Ref a -> State# -> (a, State#)
writeRef :: Ref a -> a -> State# -> (a, State#)

এই হ্যাস্কেল-জাতীয় ঘোষণাগুলি থেকে অনুবাদ করে, readRefএমন কিছু পাওয়া যায় যা " a" এর মান এবং জাল রাষ্ট্রের সাথে একটি পয়েন্টার বা হ্যান্ডেলের সাথে সাদৃশ্যযুক্ত aএবং প্রথম পরামিতি এবং একটি নতুন জাল রাষ্ট্র দ্বারা নির্দেশিত টাইপের মান প্রদান করে। writeRefঅনুরূপ, কিন্তু পরিবর্তে মান নির্দেশিত পরিবর্তিত।

যদি আপনি কল করেন readRefএবং তারপরে এটি নকল রাষ্ট্রটি ফেরত writeRefপাঠান (সম্ভবত মাঝখানে সম্পর্কযুক্ত ফাংশনে অন্যান্য কলগুলির সাথে; এই রাষ্ট্রীয় মানগুলি ফাংশন কলগুলির একটি "চেইন" তৈরি করে), এটি লিখিত মানটি ফিরিয়ে দেবে। আপনি writeRefএকই পয়েন্টার / হ্যান্ডেল দিয়ে আবার কল করতে পারেন এবং এটি একই মেমোরি অবস্থানে লিখবে - তবে, যেহেতু ধারণামূলকভাবে এটি একটি নতুন (জাল) রাষ্ট্র ফিরিয়ে আনছে, (নকল) রাষ্ট্রটি এখনও অপরিবর্তনীয় (একটি নতুন তৈরি হয়েছে "তৈরি হয়েছে" ")। সংকলকটি ক্রিয়াকলাপগুলিকে কল করবে যাতে তাদেরকে কল করতে হবে যদি সেখানে একটি সত্যিকারের রাষ্ট্রীয় পরিবর্তনশীল ছিল যা গণনা করতে হয়েছিল, তবে কেবলমাত্র সেই রাজ্যে যা সত্যিকারের হার্ডওয়্যারটির পূর্ণ (পরিবর্তনীয়) অবস্থা রয়েছে।

(যারা Haskell, জানি আমি কিছু অনেক সরলীকৃত এবং ommited বিভিন্ন গুরুত্বপূর্ণ বিবরণ লক্ষ্য করবেন। যারা চান আরো বিস্তারিত দেখতে জন্য কটাক্ষপাত করা Control.Monad.Stateথেকে mtl, এবংST s এবং IO(ওরফে ST RealWorld) মনদেসে একবার দেখুন))

আপনি ভাবতে পারেন কেন এ জাতীয় বৃত্তাকার উপায়ে এটি করা হচ্ছে (কেবলমাত্র ভাষায় পরিবর্তিত অবস্থার পরিবর্তে)। আসল সুবিধাটি হ'ল আপনি নিজের প্রোগ্রামের স্থিতিটি পুনরায় সংশোধন করেছেন । যা আগে অন্তর্নিহিত ছিল (আপনার প্রোগ্রামের রাষ্ট্রটি বিশ্বব্যাপী ছিল, দূরত্বে কর্মের মতো জিনিসের অনুমতি দেয় ) এখন তা স্পষ্ট। যে কার্যগুলি রাষ্ট্র গ্রহণ করে এবং ফেরত দেয় না সেগুলি এটিকে সংশোধন করতে পারে না বা এর দ্বারা প্রভাবিত হতে পারে না; তারা "খাঁটি" আরও ভাল, আপনার পৃথক রাষ্ট্রের থ্রেড থাকতে পারে এবং কিছুটা যাদুর সাহায্যে এগুলি অপরিষ্কার না করে খাঁটি একটিতে আবশ্যক গণনা এম্বেড করতে ব্যবহার করা যেতে পারে ( STহাস্কেলের মোনাডই সাধারণত এই কৌশলটির জন্য ব্যবহৃত হয়; State#আমি পূর্বেই উল্লেখ করা আসলে GHC এর মধ্যে আছে State# sতার বাস্তবায়ন কর্তৃক ব্যবহৃত monads)।ST এবংIO


7

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


যখন আমি আরও অ্যান্টি-ফাংশনাল ছিলাম আমি ভাবতাম যখন হার্ড ড্রাইভের মতো কিছু পরিবর্তনীয় হয় তখন কীভাবে এটি ভাল হতে পারে। আমার সি # ক্লাসগুলির সকলের পারস্পরিক পরিবর্তন এবং এটি খুব যুক্তিযুক্তভাবে একটি হার্ড ড্রাইভ বা অন্য কোনও ডিভাইস অনুকরণ করতে পারে। যদিও কার্যক্ষমতার সাথে মডেলগুলি এবং তারা যে মডেলিং করছিলেন প্রকৃত মেশিনগুলির মধ্যে একটি অমিল রয়েছে। ক্রিয়ামূলক আরও তদন্ত করার পরে আমি যে বেনিফিট পেয়েছি তা বুঝতে পেরেছি যে এই সমস্যাটিকে মোটামুটি ছাড়িয়ে যেতে সক্ষম। শারীরিকভাবে যদি এমন কোনও হার্ড ড্রাইভ আবিষ্কার করা সম্ভব হয়েছিল যা নিজেই একটি অনুলিপি তৈরি করে তবে এটি আসলে কার্যকর হবে (যেমন জার্নালিং ইতিমধ্যে হয়েছে)।
কিংবদন্তি দৈর্ঘ্য

5

অন্যরা যে দুর্দান্ত উত্তর দিচ্ছে তা ছাড়াও ক্লাসগুলি Integerএবং Stringজাভা সম্পর্কে ভাবেন । এই শ্রেণীর উদাহরণ অপরিবর্তনীয়, তবে এটি ক্লাসগুলিকে অকেজো করে তোলে না কারণ তাদের দৃষ্টান্তগুলি পরিবর্তন করা যায় না। অপরিবর্তনীয়তা আপনাকে কিছুটা সুরক্ষা দেয়। আপনি যদি জানেন যে আপনি স্ট্রিং বা পূর্ণসংখ্যার উদাহরণটি ক এর কী হিসাবে ব্যবহার করেন তবে কীটি Mapপরিবর্তন করা যাবে না। Dateএটি জাভাতে ক্লাসের সাথে তুলনা করুন :

Date date = new Date();
mymap.put(date, date.toString());
// Some time later:
date.setTime(new Date().getTime());

আপনি চুপচাপ আপনার মানচিত্রে একটি চাবি পরিবর্তন করেছেন! ফাংশনাল প্রোগ্রামিংয়ের মতো অপরিবর্তনীয় বস্তুর সাথে কাজ করা অনেক পরিষ্কার। কোন পার্শ্ব প্রতিক্রিয়া ঘটে সে সম্পর্কে তর্ক করা সহজ - কোনওটি নয়! এর অর্থ এটি প্রোগ্রামারটির পক্ষে সহজ এবং অপটিমাইজারের পক্ষেও সহজ।


2
আমি এটি বুঝতে পারি, তবে এটি আমার প্রশ্নের উত্তর দেয় না। কম্পিউটার প্রোগ্রামটি কিছু বাস্তব-জগতের ঘটনা বা প্রক্রিয়ার একটি মডেল মনে রেখে, আপনি যদি নিজের মানগুলি পরিবর্তন করতে না পারেন তবে আপনি কীভাবে পরিবর্তিত কিছুকে মডেল করবেন?
ম্যাসন হুইলারের

ভাল, আপনি অবশ্যই পূর্ণসংখ্যার এবং স্ট্রিং ক্লাসগুলির সাথে দরকারী জিনিসগুলি করতে পারেন। এটি তাদের অপরিবর্তনীয়তার মতো নয় যার অর্থ আপনার পরিবর্তনীয় অবস্থা থাকতে পারে না।
এডি

@ ম্যাসন হুইলার - একটি জিনিস এবং এটির অবস্থা দুটি পৃথক "জিনিস" বুঝতে পেরে। প্যাকম্যান যা হয় তা সময়ে সময়ে পরিবর্তিত হয় না। যেখানে প্যাকম্যান হয় তা পরিবর্তন হয়। আপনি যখন সময় A থেকে সময়ে বি তে চলে যান, আপনি প্যাকম্যান + স্টেটের একটি নতুন সংমিশ্রণ পাবেন ... যা একই প্যাকম্যান, আলাদা রাষ্ট্র। রাষ্ট্র পরিবর্তন হয়নি ... ভিন্ন রাষ্ট্র।
RHSeeger

4

গেমস হিসাবে অত্যন্ত ইন্টারেক্টিভ অ্যাপ্লিকেশনগুলির জন্য, ফাংশনাল রিঅ্যাকটিভ প্রোগ্রামিং আপনার বন্ধু: যদি আপনি আপনার গেমের বিশ্বের বৈশিষ্ট্যগুলি সময়ের সাথে বিভিন্ন মান (এবং / বা ইভেন্ট স্ট্রিম) হিসাবে তৈরি করতে পারেন তবে আপনি প্রস্তুত! এই সূত্রগুলি কখনও কখনও কোনও রাজ্যের পরিবর্তনের চেয়ে আরও প্রাকৃতিক এবং উদ্দীপনা প্রকাশ করে, যেমন চলমান বলের জন্য, আপনি সরাসরি সুপরিচিত আইন x = v * t ব্যবহার করতে পারেন । এবং সর্বোত্তম, গেমের নিয়মগুলি এই জাতীয় লিখিত বিষয়গুলি অবজেক্ট-ভিত্তিক বিমূর্ততাগুলির চেয়ে ভাল রচনা করে । উদাহরণস্বরূপ, এক্ষেত্রে বলের গতিও সময়ের পরিবর্তিত মান হতে পারে যা বলের সংঘর্ষগুলি নিয়ে ইভেন্ট স্ট্রিমের উপর নির্ভর করে। আরও কংক্রিট ডিজাইন বিবেচনার জন্য, এলমে গেমস তৈরি করা দেখুন ।


4

3

COMON ব্লক ছাড়াই ফোরট্রান এইভাবে কাজ করবে: আপনি এমন পদ্ধতিগুলি লিখতে চাইবেন যেখানে আপনি যে মান এবং স্থানীয় ভেরিয়েবলগুলি পাশ করেছেন সেগুলি লিখতেন। এটাই.

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং আমাদের একসাথে রাষ্ট্র এবং আচরণ এনেছিল, কিন্তু 1994 সালে আমি যখন প্রথম C ++ থেকে প্রথম মুখোমুখি হয়েছিলাম তখন এটি একটি নতুন ধারণা ছিল।

গীজ, আমি যখন একজন যান্ত্রিক প্রকৌশলী ছিলাম তখন আমি একটি ক্রিয়ামূলক প্রোগ্রামার ছিলাম এবং আমি এটি জানতাম না!


2
আমি অসম্মতি জানাতে চাই যে এটি এমন কিছু যা আপনি ওও তে পিন করতে পারেন। ওওর আগে ভাষাগুলি সংযোজন অবস্থা এবং অ্যালগরিদমগুলিকে উত্সাহিত করে। ওও এটি পরিচালনা করার জন্য আরও ভাল উপায় সরবরাহ করেছে।
জেসন বেকার

"উত্সাহিত" - সম্ভবত। ওও এটিকে ভাষার একটি স্পষ্ট অংশে পরিণত করুন। আপনি সি তে লুকিয়ে থাকা এনক্যাপসুলেশন এবং তথ্য করতে পারেন, তবে আমি বলব যে ওও ভাষাগুলি এটিকে অনেক সহজ করে তোলে।
duffymo

2

মনে রাখবেন: কার্যকরী ভাষাগুলি ট্যুরিং সম্পূর্ণ। অতএব, আপনি কোন নিষ্ঠাবান ভাষায় যে কার্যকর কাজ সম্পাদন করবেন তা কার্যকরী ভাষায় করা যেতে পারে। দিনের শেষে যদিও, আমি মনে করি একটি হাইব্রিড পদ্ধতির বিষয়ে কিছু বলার আছে। এফ # এবং ক্লোজার (এবং আমি নিশ্চিত অন্যরা) এর মতো ভাষাও রাষ্ট্রবিহীন নকশাকে উত্সাহ দেয়, তবে প্রয়োজনের সময় পরিবর্তনের অনুমতি দিন।


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

2
অবশ্যই এটি পারে। সি হিসাবে হার্ডওয়ারে একই অ্যাক্সেস দেওয়া হয়েছে, এটি পারে। এর অর্থ এই নয় যে এটি ব্যবহারিক হবে, তবে সম্ভাবনা রয়েছে।
জেসন বেকার 0

2

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

আপনি ব্যবহার করেন এমন অন্য একটি সরঞ্জাম হিসাবে ক্রিয়ামূলক ভাষাগুলি ভাবেন। এটি নির্দিষ্ট কিছু জিনিসের জন্য ভাল তবে অন্যদের জন্য নয়। আপনি যে গেমের উদাহরণ দিয়েছেন সেটি কার্যকরী ভাষা ব্যবহারের সর্বোত্তম উপায় নাও হতে পারে, কমপক্ষে স্ক্রিনটির এমন এক পরিবর্তনীয় অবস্থা থাকবে যা আপনি এফপি দিয়ে কিছু করতে পারবেন না। আপনি যেভাবে সমস্যার কথা ভাবেন এবং এফপি দিয়ে আপনি যে ধরণের সমস্যার সমাধান করবেন সেগুলি আপনার অত্যাবশ্যক প্রোগ্রামিংয়ের সাথে অভ্যস্ত from


1

প্রচুর পুনরাবৃত্তি ব্যবহার করে।

এফ # তে টিকিট টো (একটি কার্যকরী ভাষা))


অবশ্যই, লেজ-পুনরাবৃত্তি খুব দক্ষতার সাথে প্রয়োগ করা যেতে পারে, যেহেতু সংকলকরা এটিকে একটি লুপে রূপান্তর করতে পারে।
এডি

-3

এটি খুব সহজ। ফাংশনাল প্রোগ্রামিংয়ে আপনি যতগুলি ভেরিয়েবল চান তা ব্যবহার করতে পারেন ... তবে কেবলমাত্র যদি সেগুলি স্থানীয় ভেরিয়েবল হয় (অভ্যন্তরীণ ফাংশনগুলিতে থাকে)। সুতরাং কেবলমাত্র আপনার কোডগুলিকে ফাংশনগুলিতে মুড়িয়ে দিন, সেই ফাংশনগুলির মধ্যে পিছনে পিছনে মানগুলি পাস করুন (উত্তরণিত প্যারামিটার এবং প্রত্যাবর্তিত মান হিসাবে) ... এবং এটি এতদূর আছে!

এখানে একটি উদাহরণ:

function ReadDataFromKeyboard() {
    $input_values = $_POST[];
    return $input_values;
}
function ProcessInformation($input_values) {
    if ($input_values['a'] > 10)
        return ($input_values['a'] + $input_values['b'] + 3);
    else if ($input_values['a'] > 5)
        return ($input_values['b'] * 3);
    else
        return ($input_values['b'] - $input_values['a'] - 7);
}
function DisplayToPage($data) {
    print "Based your input, the answer is: ";
    print $data;
    print "\n";
}

/* begin: */
DisplayToPage (
    ProcessInformation (
        GetDataFromKeyboard()
    )
);

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