সি ++ 11 এর ল্যাম্বডায় ডিফল্টরূপে ক্যাপচার-বাই-ভ্যালুয়ের জন্য কেন "মিউটেবল" কীওয়ার্ডের প্রয়োজন?


256

সংক্ষিপ্ত উদাহরণ:

#include <iostream>

int main()
{
    int n;
    [&](){n = 10;}();             // OK
    [=]() mutable {n = 20;}();    // OK
    // [=](){n = 10;}();          // Error: a by-value capture cannot be modified in a non-mutable lambda
    std::cout << n << "\n";       // "10"
}

প্রশ্ন: কেন আমাদের mutableকীওয়ার্ডের প্রয়োজন ? নামযুক্ত ফাংশনগুলিতে প্রথাগত প্যারামিটারটি পাস করা থেকে এটি বেশ আলাদা। পিছনে যুক্তি কি?

আমি এই ধারণার মধ্যে ছিলাম যে ক্যাপচার-বাই-ভ্যালুটির পুরো বিন্দুটি ব্যবহারকারীকে অস্থায়ী পরিবর্তন করতে দেয় - অন্যথায় আমি ক্যাপচার-বাই-রেফারেন্স ব্যবহার করে প্রায় সবসময়ই ভাল, আমি না?

কোন আলোকিতকরণ?

(আমি এমএসভিসি ২০০-এর ব্যবহার করছি AF এএফএইকি এটি স্ট্যান্ডার্ড হওয়া উচিত)


101
ভাল প্রশ্ন; যদিও আমি আনন্দিত কিছু অবশেষে constডিফল্ট!
xtofl

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

8
@xtofl: নিশ্চিত না যে এটি ভাল, যখন সমস্ত কিছু constডিফল্টরূপে না থাকে।
kizzx2

8
@ ট্যামস সেজেলি: যুক্তি শুরু করার জন্য নয়, তবে আইএমএইচও "শেখা সহজ" ধারণাটি বিশেষত আধুনিক সময়ে সি ++ ভাষায় নেই place যাইহোক: পি
কিজক্স 2

3
"ক্যাপচার-বাই-মানটির পুরো পয়েন্টটি ব্যবহারকারীকে অস্থায়ী পরিবর্তন করতে দেয়" - না, পুরো বিষয়টি হ'ল ল্যাম্বডা কোনও বন্দী ভেরিয়েবলের আজীবন পেরিয়ে বৈধ থাকতে পারে। যদি সি ++ ল্যাম্বডাসের কেবল ক্যাপচার-বাই-রেফ থাকে, তবে তারা অনেকগুলি পরিস্থিতিতে অব্যর্থ।
সেবাস্তিয়ান রেডল

উত্তর:


230

এটির প্রয়োজন mutableকারণ ডিফল্টরূপে, যখনই ডাকা হয় তখন কোনও ফাংশন অবজেক্টের একই ফলাফল উত্পন্ন করা উচিত। এটি কার্যকরভাবে কোনও বিশ্বব্যাপী ভেরিয়েবল ব্যবহার করে কোনও অবজেক্ট ওরিয়েন্টেটেড ফাংশন এবং ফাংশনের মধ্যে পার্থক্য।


7
এটি একটি ভালো দিক. আমি সম্পূর্ণভাবে রাজী. যদিও সি ++ 0 এক্সে, আমি ডিফল্ট উপরেরগুলি প্রয়োগ করতে কীভাবে সহায়তা করে তা আমি পুরোপুরি দেখতে পাই না। বিবেচনা করুন আমি ল্যামডা গ্রহণ শেষ am যেমন আমি void f(const std::function<int(int)> g)। আমি কীভাবে গ্যারান্টিযুক্ত যে gআসলে রেফারেন্টালি স্বচ্ছ ? gএর সরবরাহকারী হয়ত mutableযেভাবেই ব্যবহার করতে পারেন । সুতরাং আমি জানি না। অন্যদিকে, তাহলে ডিফল্ট অ- হয় const, এবং মানুষ যোগ করা আবশ্যক constপরিবর্তে mutableফাংশন বস্তু, কম্পাইলার আসলে জোরদার করতে const std::function<int(int)>অংশ এবং এখন fঅনুমান করতে পারেন gহয় const, তাই না?
kizzx2

8
@ কিজএক্সএক্স 2: সি ++ তে কিছুই প্রয়োগ করা হয় না , কেবলমাত্র প্রস্তাবিত। যথারীতি, যদি আপনি বোকা কিছু করেন (রেফারেনশিয়াল স্বচ্ছতার জন্য ডকুমেন্টেড প্রয়োজনীয়তা এবং তারপরে অ-রেফারেন্সালি-স্বচ্ছ ফাংশনটি পাস করেন), আপনার কাছে যা আসে তা আপনি পেয়ে যান।
কুকুরছানা

6
এই উত্তরটি আমার চোখ খুলল। পূর্বে, আমি ভেবেছিলাম যে এই ক্ষেত্রে ল্যাম্বদা কেবল বর্তমান "রান" এর জন্য একটি অনুলিপি পরিবর্তন করে।
Zsolt জাজমারি

4
@ ZsoltSzatmari আপনার মন্তব্যটি আমার চোখ খুলল! : -আমি আপনার মন্তব্যটি না পড়া পর্যন্ত এই উত্তরটির আসল অর্থটি পাইনি।
জেন্ডাস

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

103

আপনার কোডটি প্রায় এটির সমতুল্য:

#include <iostream>

class unnamed1
{
    int& n;
public:
    unnamed1(int& N) : n(N) {}

    /* OK. Your this is const but you don't modify the "n" reference,
    but the value pointed by it. You wouldn't be able to modify a reference
    anyway even if your operator() was mutable. When you assign a reference
    it will always point to the same var.
    */
    void operator()() const {n = 10;}
};

class unnamed2
{
    int n;
public:
    unnamed2(int N) : n(N) {}

    /* OK. Your this pointer is not const (since your operator() is "mutable" instead of const).
    So you can modify the "n" member. */
    void operator()() {n = 20;}
};

class unnamed3
{
    int n;
public:
    unnamed3(int N) : n(N) {}

    /* BAD. Your this is const so you can't modify the "n" member. */
    void operator()() const {n = 10;}
};

int main()
{
    int n;
    unnamed1 u1(n); u1();    // OK
    unnamed2 u2(n); u2();    // OK
    //unnamed3 u3(n); u3();  // Error
    std::cout << n << "\n";  // "10"
}

সুতরাং আপনি লম্বডাসকে অপারেটর () দিয়ে একটি শ্রেণি তৈরির হিসাবে ভাবতে পারেন যা কনস্টে ডিফল্ট হবে যদি না আপনি এটি পরিবর্তনীয় না বলে থাকেন।

আপনি [] ভিতরে স্পষ্টরূপে বা স্পষ্টভাবে অন্তর্ভুক্ত সমস্ত ভেরিয়েবলগুলিও class শ্রেণীর সদস্য হিসাবে ভাবতে পারেন: [=] এর জন্য অবজেক্টের অনুলিপি বা [&] এর জন্য অবজেক্টের রেফারেন্স। আপনি যখন আপনার ল্যাম্বডা ঘোষণা করেন তখন এগুলি সূচনা করা হয় যেন কোনও লুকানো কনস্ট্রাক্টর ছিল।


5
সমতুল্য ব্যবহারকারী-সংজ্ঞায়িত প্রকার হিসাবে প্রয়োগ করা হলে একটি বা ল্যাম্বদা দেখতে কেমন হবে তার একটি দুর্দান্ত ব্যাখ্যা করার পরে , প্রশ্নটি (শিরোনামে যেমন রয়েছে এবং মন্তব্যগুলিতে ওপি দ্বারা ব্যাখ্যা করেছেন) কেন ডিফল্ট, তাই এটি এর উত্তর দেয় না। constmutable const
আন্ডারস্কোর_ড

36

আমি এই ধারণার মধ্যে ছিলাম যে ক্যাপচার-বাই-ভ্যালুটির পুরো বিন্দুটি ব্যবহারকারীকে অস্থায়ী পরিবর্তন করতে দেয় - অন্যথায় আমি ক্যাপচার-বাই-রেফারেন্স ব্যবহার করে প্রায় সবসময়ই ভাল, আমি না?

প্রশ্নটি হচ্ছে, এটি কি প্রায় "প্রায়"? ঘন ঘন ব্যবহারের ক্ষেত্রে ল্যাম্বডাস ফিরিয়ে দেওয়া বা পাস করা হবে বলে মনে হয়:

void registerCallback(std::function<void()> f) { /* ... */ }

void doSomething() {
  std::string name = receiveName();
  registerCallback([name]{ /* do something with name */ });
}

আমি মনে করি এটি mutable"প্রায়" কেস নয়। আমি "ক্যাপচার-বাই-ভ্যালু" হিসাবে বিবেচনা করি "বন্দী সত্তা মারা যাওয়ার পরে আমাকে এর মানটি ব্যবহার করতে দেয়" "" আমাকে এর অনুলিপি পরিবর্তন করার অনুমতি দিন "না than তবে সম্ভবত এটি যুক্তিযুক্ত হতে পারে।


2
ভালো উদাহরণ. ক্যাপচার-বাই-মান ব্যবহারের জন্য এটি একটি খুব শক্তিশালী ব্যবহারের কেস। তবে কেন এটি ডিফল্ট হয় const? এটি কোন উদ্দেশ্য অর্জন করে? "প্রায়" (: পি) ভাষার অন্যান্য কিছুর মধ্যে mutableযখন ডিফল্ট constহয় না , এখানে এখানে জায়গাটি অজানা মনে হচ্ছে ।
kizzx2

8
@ কিজএক্স 2: আমি আশা করি constডিফল্ট ছিল, কমপক্ষে লোকেরা সংশোধন-সঠিকতা বিবেচনা করতে বাধ্য হবে: /
ম্যাথিউ এম।

1
@ কিজডক্স 2 ল্যাম্বডা কাগজপত্রগুলি সন্ধান করছে, আমার কাছে মনে হয় তারা এটিকে ডিফল্ট করে দেয় constযাতে ল্যাম্বডা অবজেক্টটি কনস্টেট হয় কিনা তা তারা কল করতে পারে। উদাহরণস্বরূপ তারা এটি গ্রহণ করে কোনও কার্যক্রমে এটি পাস করতে পারে std::function<void()> const&। ল্যাম্বদা এর ক্যাপচার কপিগুলিকে পরিবর্তন করার অনুমতি দেওয়ার জন্য, প্রাথমিক কাগজপত্রগুলিতে ক্লোজারটির ডেটা সদস্যরা mutableস্বয়ংক্রিয়ভাবে সংজ্ঞায়িত হয়েছিল । এখন আপনাকে ম্যানুয়ালি mutableল্যাম্বডা এক্সপ্রেশনটি রাখতে হবে। যদিও আমি বিশদ যুক্তি খুঁজে পাই না।
জোহানেস স্কাউব - লিটব


5
এই মুহুর্তে, আমার কাছে, "আসল" উত্তর / যুক্তি বলে মনে হচ্ছে "তারা একটি বাস্তবায়নের
বিশদটি

32

এফডাব্লুআইডাব্লু, সি ++ প্রমিতকরণ কমিটির সুপরিচিত সদস্য, হার্ব সাটার ল্যাম্বডা সঠিকতা এবং ব্যবহারযোগ্যতা ইস্যুতে সেই প্রশ্নের আলাদা উত্তর সরবরাহ করে :

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

int val = 0;
auto x = [=](item e)            // look ma, [=] means explicit copy
            { use(e,++val); };  // error: count is const, need ‘mutable’
auto y = [val](item e)          // darnit, I really can’t get more explicit
            { use(e,++val); };  // same error: count is const, need ‘mutable’

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

কেন তার C ++ 14 এ পরিবর্তন করা উচিত সে সম্পর্কে তার কাগজ। আপনি যদি এই বিশেষ বৈশিষ্ট্যটির জন্য "[কমিটির সদস্যদের মনে] কী আছে" জানতে চান তবে এটি সংক্ষিপ্ত, ভাল লিখিত, পড়ার মতো।


16

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


14

5.1.2 এর অধীনে এই খসড়াটি দেখুন [expr.prim.lambda], subclause 5:

ল্যাম্বডা-এক্সপ্রেশনটির ক্লোজার টাইপের একটি পাবলিক ইনলাইন ফাংশন কল অপারেটর রয়েছে (১৩.৫.৪) যার প্যারামিটার এবং রিটার্ন টাইপ যথাক্রমে ল্যাম্বডা-এক্সপ্রেশনটির প্যারামিটার-ডিক্লেয়ারেশন-ক্লজ এবং ট্রেলিংরেটান টাইপ দ্বারা বর্ণিত। এই ফাংশন কল অপারেটরটিকে কনস্ট (9.3.1) হিসাবে ঘোষণা করা হয় এবং যদি কেবল ল্যাম্বডেক্সএক্সপ্রেসনের প্যারামিটার-ডিক্লেয়ারেশন-ক্লজটি পরিবর্তনীয় অনুসরণ না করে।

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

কিজএক্সএক্স 2 এর মন্তব্যে সম্পাদনা করুন: বেশিরভাগ সময় যখন একটি ল্যাম্বডা ব্যবহার করা হয় তখন তা অ্যালগরিদমের ফান্টার হিসাবে হয়। ডিফল্ট constনেস এটিকে একটি ধ্রুবক পরিবেশে ব্যবহার করতে দেয়, ঠিক constতেমন সাধারণ- যোগ্য ফাংশনগুলিও সেখানে ব্যবহার করা যেতে পারে, তবে constঅব্যক্ত নয় can't হতে পারে তারা কেবল তাদের ক্ষেত্রে এটি আরও স্বজ্ঞাগত করার চিন্তা করেছিল, যারা জানে যে তাদের মনে কী চলছে। :)


এটি স্ট্যান্ডার্ড, তবে কেন তারা এইভাবে লিখেছে?
kizzx2

@ কিজএক্সএক্স 2: আমার ব্যাখ্যাটি সরাসরি সেই উক্তির অধীনে। :) এটি লিটব ক্যাপচারযুক্ত বস্তুর জীবদ্দশায় যা বলে তার সাথে কিছুটা সম্পর্কিত, তবে আরও খানিকটা এগিয়ে যায় goes
জিও

@ শিও: ওহ হ্যাঁ, আমি এটি মিস করেছি: পি ক্যাপচার বাই মানটির ভাল ব্যবহারের জন্য এটি আরও একটি ভাল ব্যাখ্যা । তবে কেন এটি constডিফল্ট হওয়া উচিত ? আমি ইতিমধ্যে একটি নতুন অনুলিপি পেয়েছি, এটি পরিবর্তন করতে না দেওয়া আমার কাছে অদ্ভুত বলে মনে হচ্ছে - বিশেষত এটির সাথে এটি মূলত কোনও ভুল নয় - তারা কেবল আমাকে যুক্ত করতে চায় mutable
kizzx2

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

2
@ কিজেক্স 2 - যদি আমরা আবারও শুরু করতে পারি তবে আমাদের সম্ভবত varএকটি কীওয়ার্ড হিসাবে পরিবর্তন এবং ধ্রুবককে অন্য কিছুর জন্য ডিফল্ট হিসাবে থাকতে দেওয়া হবে। এখন আমরা করি না, তাই আমাদের সাথে বাঁচতে হবে। আইএমও, সি ++ ২০১১ সবকিছু বিবেচনা করে বেশ ভালভাবে বেরিয়ে এসেছিল।
বো পারসন

11

আমি এই ধারণার মধ্যে ছিলাম যে ক্যাপচার-বাই-ভ্যালুটির পুরো বিন্দুটি ব্যবহারকারীকে অস্থায়ী পরিবর্তন করতে দেয় - অন্যথায় আমি ক্যাপচার-বাই-রেফারেন্স ব্যবহার করে প্রায় সবসময়ই ভাল, আমি না?

nহয় না একটি অস্থায়ী। n ল্যাম্বদা-ফাংশন-অবজেক্টের একটি সদস্য যা আপনি ল্যাম্বডা এক্সপ্রেশন দিয়ে তৈরি করেন। ডিফল্ট প্রত্যাশাটি হ'ল আপনার ল্যাম্বদা কল করা তার স্থিতি পরিবর্তন করে না, সুতরাং দুর্ঘটনাক্রমে আপনাকে সংশোধন করা থেকে বিরত রাখা উচিত n


1
পুরো ল্যাম্বডা বস্তুটি একটি অস্থায়ী, এর সদস্যদেরও অস্থায়ী জীবনকাল থাকে।
বেন ভয়েগট

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

6

আপনি বুঝতে হবে ক্যাপচার মানে কি! এটা ক্যাপচারিং তর্ক না পাস! আসুন কিছু কোড নমুনা দেখুন:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() {return x + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //output 10,20

}

যেমন আপনি দেখতে পাচ্ছেন যদিও ল্যাম্বডায় xপরিবর্তিত হয়েছে 20এখনও 10 টি ফিরে আসছে ( xএখনও 5ল্যাম্বদার xভিতরে রয়েছে ) ল্যাম্বদার ভিতরে পরিবর্তন মানে প্রতিটি কলটিতে ল্যাম্বডা নিজেই পরিবর্তন করা হয় (প্রতিটি কলটিতে ল্যাম্বডা পরিবর্তিত হয়)। নির্ভুলতা প্রয়োগের জন্য মানটি mutableকীওয়ার্ডটি চালু করেছিল । কোনও ল্যাম্বডাকে পরিবর্তনীয় হিসাবে উল্লেখ করে আপনি বলছেন যে ল্যাম্বডায় প্রতিটি কল ল্যাম্বডায় নিজেই পরিবর্তনের কারণ হতে পারে। আরেকটি উদাহরণ দেখতে দিন:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() mutable {return x++ + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //outputs 11,20

}

উপরের উদাহরণটি দেখায় যে ল্যাম্বডাকে পরিবর্তনীয় করে ল্যাম্বদার xঅভ্যন্তরে পরিবর্তন করে লম্বাটির প্রতিটি কলে ল্যাম্বডাকে একটি নতুন মান দিয়ে মূল ফাংশনটির xআসল মানটির সাথে কোনও সম্পর্ক নেই showsx


4

লাম্বদাmutable ঘোষণাপত্রের প্রয়োজনীয়তা হ্রাস করার জন্য এখন একটি প্রস্তাব রয়েছে : n3424


এর মধ্যে কোন তথ্য এসেছে? আমি ব্যক্তিগতভাবে মনে করি এটি একটি খারাপ ধারণা, যেহেতু নতুন "নির্বিচারে অভিব্যক্তি ক্যাপচার" ব্যথার বেশিরভাগ ক্ষেত্রেই মসৃণ করে।
বেন ভয়েগট

1
@ বেনভয়েগ হ্যাঁ এটিকে পরিবর্তনের স্বার্থে পরিবর্তন বলে মনে হচ্ছে।
মাইলস রাউট

3
@ বেনভয়েগট যদিও ন্যায্য হলেও আমি আশা করি অনেকগুলি সি ++ বিকাশকারী সম্ভবত আছেন যা জানেন না যে mutableএটি সি ++ এর একটি কীওয়ার্ডও।
মাইলস রাউট

1

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

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

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

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