সি তে ক্রিয়ামূলক প্রোগ্রামিংয়ের জন্য কোন সরঞ্জামগুলি রয়েছে?


153

আমি সি (ইন কার্যকরী প্রোগ্রামিং কাজ সম্পর্কে যেতে হবে সে সম্পর্কে ইদানীং অনেক ভেবে দেখেছি না সি ++)। স্পষ্টতই, সি একটি প্রক্রিয়াগত ভাষা এবং প্রকৃতপক্ষে স্থানীয়ভাবে কার্যকরী প্রোগ্রামিং সমর্থন করে না।

এমন কি কোনও সংকলক / ভাষার এক্সটেনশান রয়েছে যা ভাষার সাথে কিছু কার্যকরী প্রোগ্রামিং কনস্ট্রাক্ট যুক্ত করে? জিসিসি ভাষা বর্ধনের হিসাবে নেস্টেড ফাংশন সরবরাহ করে ; নেস্টেড ফাংশনগুলি প্যারেন্ট স্ট্যাক ফ্রেম থেকে ভেরিয়েবল অ্যাক্সেস করতে পারে তবে এটি পরিপক্ক বন্ধ হওয়া থেকে এখনও অনেক দূরে।

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

[সম্পাদনা] স্পষ্ট করার জন্য, আমি সি তে একটি নির্দিষ্ট সমস্যা সমাধানের চেষ্টা করছি না যা কার্যকরী প্রোগ্রামিংয়ের পক্ষে আরও উপযুক্ত হবে; আমি যদি জানতে চাইতাম তবে কী কী সরঞ্জাম রয়েছে তা সম্পর্কে আমি কেবল কৌতূহলী।


1
হ্যাক এবং অ-বহনযোগ্য এক্সটেনশানগুলির পরিবর্তে সিটিকে এমন কিছুতে পরিণত করার চেষ্টা করার পরিবর্তে আপনি কেবল এমন ভাষা ব্যবহার করেন না যা আপনি সন্ধান করছেন এমন কার্যকারিতা সরবরাহ করে?
রবার্ট গাম্বল

সম্পর্কিত সম্পর্কিত প্রশ্নও দেখুন: < স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি / 24995/… >
অ্যান্ডি ব্রাইস

@AndyBrice যে প্রশ্ন একটি ভিন্ন ভাষা সম্পর্কে এবং আসলে জানার জন্য প্রদর্শিত হবে না (সি ++ একটি "বাস্তু" হিসাবে একই অর্থে নেই।
কাইলি স্ট্র্যান্ড

উত্তর:


40

এফএফএএলএল আপনাকে সিতে ক্লোজারগুলি তৈরি করতে দেয় - callback = alloc_callback(&function, data)একটি ফাংশন পয়েন্টার দেয় যা callback(arg1, ...)কল করার সমতুল্য function(data, arg1, ...)। যদিও আপনাকে ম্যানুয়ালি ময়লা আবদ্ধ করতে হবে।

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


89

লাম্বদা এক্সপ্রেশন অনুকরণ করতে আপনি জিসিসির নেস্টেড ফাংশনগুলি ব্যবহার করতে পারেন, আসলে আমার কাছে এটি করার জন্য আমার কাছে একটি ম্যাক্রো রয়েছে:

#define lambda(return_type, function_body) \
  ({ \
    return_type anon_func_name_ function_body \
    anon_func_name_; \
  })

এটি ব্যবহার করুন:

int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });

12
এটা সত্যিই দুর্দান্ত। মনে __fn__হচ্ছে কেবলমাত্র ব্লকের মধ্যে সংজ্ঞায়িত ফাংশনের স্বেচ্ছাসেবী নাম ({... }), কিছু জিসিসি এক্সটেনশন বা পূর্বনির্ধারিত ম্যাক্রো নয়? __fn__(জিসিসির সংজ্ঞার মতো দেখতে অনেকটা) জন্য নামের পছন্দটি আমাকে সত্যিই আমার মাথা আঁচড়ান এবং কোনও ভাল প্রভাবের জন্য জিসিসি ডকুমেন্টেশন অনুসন্ধান করে।
FooF

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

এটি দূর থেকে কার্যকর নয়, তবে এটি মজাদার। এজন্য অন্য উত্তরটি গ্রহণ করা হয়েছে।
জো ডি

65

ফাংশনাল প্রোগ্রামিং ল্যাম্বডাস সম্পর্কে নয়, এটি খাঁটি ফাংশন সম্পর্কে। সুতরাং নিম্নলিখিতগুলি কার্যকরভাবে কার্যকরী শৈলীর প্রচার করে:

  1. শুধুমাত্র ফাংশন আর্গুমেন্ট ব্যবহার করুন, গ্লোবাল স্টেট ব্যবহার করবেন না।

  2. পার্শ্ব প্রতিক্রিয়া হ্রাস করুন যেমন প্রিন্টফ, বা কোনও আইও। আইও বর্ণনাকারী ডেটা ফেরত দিন যা সমস্ত কার্যক্রমে সরাসরি পার্শ্ব প্রতিক্রিয়া সৃষ্টি করার পরিবর্তে কার্যকর করা যেতে পারে।

এটি প্লেইন সিতে অর্জন করা যায়, যাদুবিদ্যার দরকার নেই।


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

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

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

পিএস পূর্ববর্তী মন্তব্যটি মোবাইল থেকে ছিল - অনিয়মিত ব্যাকরণ উদ্দেশ্যমূলক ছিল না।
জোনাথন লিওনার্ড

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

17

হার্টেল অ্যান্ড মুলারের বই, ফাংশনাল সি , আজকাল (২০১২-০১-২০) পাওয়া যাবে: http://eprints.eemcs.utwente.nl/1077/ (পিডিএফ সংস্করণে একটি লিঙ্ক আছে)।


2
এই বইটিতে কার্যকরী কোনও কিছুর চেষ্টা নেই (যেমন প্রশ্নের সাথে সম্পর্কিত)।
ইউজিন টোলমাচেভ

4
দেখে মনে হচ্ছে আপনি বেশ ঠিক আছেন। প্রকৃতপক্ষে, প্রবন্ধটি বলেছে যে শিক্ষার্থীরা ইতিমধ্যে নিজেকে কার্যকরী প্রোগ্রামিংয়ের সাথে পরিচিত করার পরে বইটির উদ্দেশ্য হ'ল প্রয়োজনীয় প্রোগ্রামিং শেখানো teach এফওয়াইআই, এটি আমার প্রথম উত্তর ছিল এবং এটি উত্তর হিসাবে লেখা হয়েছিল কারণ আমার পচা লিঙ্কের সাথে পূর্ববর্তী উত্তরটির মন্তব্য করার খ্যাতি ছিল না। আমি সবসময় ভাবছি কেন লোকেরা এই উত্তর +1 রাখে ... দয়া করে এটি করবেন না! :-)
4

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

এবং এটি একটি সদৃশ উত্তর
ফিল্ট

8

ক্রিয়ামূলক প্রোগ্রামিং শৈলীর পূর্বশর্ত প্রথম শ্রেণির ফাংশন। আপনি পরবর্তী সহ্য করতে পারলে এটি পোর্টেবল সি তে অনুকরণ করা যেতে পারে:

  • লেক্সিক স্কোপ বাইন্ডিংস, ওরফে ক্লোজার ম্যানুয়াল ম্যানেজমেন্ট।
  • ফাংশন ভেরিয়েবল আজীবন ম্যানুয়াল পরিচালনা।
  • ফাংশন অ্যাপ্লিকেশন / কল বিকল্প সিনট্যাক্স।
/* 
 * with constraints desribed above we could have
 * good approximation of FP style in plain C
 */

int increment_int(int x) {
  return x + 1;
}

WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS(increment, increment_int);

map(increment, list(number(0), number(1)); // --> list(1, 2)


/* composition of first class function is also possible */

function_t* computation = compose(
  increment,
  increment,
  increment
);

*(int*) call(computation, number(1)) == 4;

এই জাতীয় কোডের জন্য রানটাইম নীচের চেয়ে ছোট হতে পারে

struct list_t {
  void* head;
  struct list_t* tail;
};

struct function_t {
   void* (*thunk)(list_t*);
   struct list_t* arguments;
}

void* apply(struct function_t* fn, struct list_t* arguments) {
  return fn->thunk(concat(fn->arguments, arguments));
}

/* expansion of WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS */
void* increment_thunk(struct list_t* arguments) {
  int x_arg = *(int*) arguments->head;
  int value = increment_int(x_arg);
  int* number = malloc(sizeof *number);

  return number ? (*number = value, number) : NULL;
}

struct function_t* increment = &(struct function_t) {
  increment_thunk,
  NULL
};

/* call(increment, number(1)) expands to */
apply(increment, &(struct list_t) { number(1), NULL });

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


7

মূল জিনিস যা মনে আসে তা হ'ল কোড জেনারেটর ব্যবহার। আপনি কি কোনও ভিন্ন ভাষায় প্রোগ্রাম করতে ইচ্ছুক যা কার্যকরী প্রোগ্রামিং সরবরাহ করে এবং সেখান থেকে সি কোড তৈরি করে?

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

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


এটি সবচেয়ে সৎ উত্তর। কার্যকরী পদ্ধতিতে সি লেখার চেষ্টা করা হচ্ছে ভাষা নকশা এবং কাঠামোর বিরুদ্ধে লড়াই করা।
জোসিয়াহ

5

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

আপনি কীভাবে সি তে বেনাম ফাংশন পরিচালনা করবেন তা নিশ্চিত নন একটি ভন নিউমন মেশিনে, আপনি asm এ বেনাম ফাংশন করতে পারেন।



2

ফেলিক্স ভাষা সি ++ করার প্রনয়ন। আপনি যদি সি ++ না মানেন তবে এটি একটি পদক্ষেপ পাথর হতে পারে।


9
⁻¹ কারণ α) লেখক স্পষ্ট করে উল্লেখ করেছেন C সি ++ «নয়, β) সংকলক দ্বারা উত্পাদিত সি ++ কোনও read মানব পাঠযোগ্য সি ++ be হবে না» γ) সি ++ স্ট্যান্ডার্ড একটি কার্যকরী প্রোগ্রামিং সমর্থন করে, একটি ভাষা থেকে অন্য ভাষায় সংকলক ব্যবহার করার দরকার নেই।
হাই-অ্যাঞ্জেল

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

1

বেশ কয়েকটি প্রোগ্রামিং ল্যাঙ্গুয়েজ সি তে লেখা আছে এবং এর মধ্যে কয়েকটি প্রথম শ্রেণির নাগরিক হিসাবে ফাংশন সমর্থন করে, সে অঞ্চলে ভাষাগুলি হল ecl (এম্বেডাব্বল সাধারণ লিস্প আইআইআরসি), জ্ঞু স্মলটালক (জিএসটি) (ছোট্টালকের ব্লক রয়েছে), তারপরে গ্রন্থাগার রয়েছে "ক্লোজারগুলি" উদাহরণস্বরূপ গ্লিব 2 http://library.gnome.org/devel/gobject/unstable/chapter-signal.html# সমাপ্তিতে যা অন্তত কার্যকরী প্রোগ্রামিংয়ের কাছাকাছি এসেছিল। তাই সম্ভবত কার্যকরী প্রোগ্রামিং করতে implement কিছু বাস্তবায়ন ব্যবহার করা একটি বিকল্প হতে পারে।

ভাল বা আপনি ওকামল, হাস্কেল, মোজার্ট / ওজ বা এর মতো ;-) শিখতে পারেন

শুভেচ্ছা সহ


আপনি কমপক্ষে প্রোগ্রামিং এর এফপি স্টাইল সমর্থন করে যে লাইব্রেরি ব্যবহার করে এত ভয়াবহ ভুল কি আমাকে বলতে আপত্তি করবেন?
ফ্রিডরিচ ২

1

সি তে যেভাবে ফাংশনাল প্রোগ্রামিং করতে গিয়েছিলাম তা হ'ল সিতে একটি ফাংশনাল ল্যাঙ্গুয়েজ ইন্টারপ্রেটার লেখার জন্য আমি এটিকে ফেক্সল নাম দিয়েছি, যা "ফাংশন এক্সপ্রেসন ল্যাঙ্গুয়েজ" এর পক্ষে সংক্ষিপ্ত।

দোভাষী খুব ছোট, আমার সিস্টেমে -O3 সক্ষম করে 68K তে সংকলন করে। এটি কোনও খেলনা নয় - আমি আমার ব্যবসায়ের জন্য যে সমস্ত নতুন প্রোডাকশন কোড লিখি তার জন্য এটি ব্যবহার করছি (বিনিয়োগের অংশীদারিত্বের জন্য ওয়েব-ভিত্তিক অ্যাকাউন্টিং।)

এখন আমি সি কোডটি লিখি কেবল (1) একটি বিল্ট-ইন ফাংশন যুক্ত করুন যা একটি সিস্টেম রুটিনকে কল করে (যেমন কাঁটাচামচ, এক্সিকিউট, সেট্রিমিট ইত্যাদি), বা (2) কোনও ফাংশন অনুকূলিত করুন যা অন্যথায় ফেক্সল-এ লিখিত হতে পারে (যেমন অনুসন্ধান) একটি স্ট্রস্ট্রিং জন্য)।

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

http://fexl.com


-3

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

সেই ভাষাগুলির সরাসরি বাক্যবিন্যাস শিখতে সময়টির আরও ভাল ব্যবহার হবে যা সরাসরি শব্দার্থকে সমর্থন করে।


-3

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

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