নালগুলির পরিবর্তে প্রকারের শর্তগুলির পরিবর্তে কীভাবে ভাষা রয়েছে?


53

এরিক লিপার্ট তার আলোচনায়nullMaybe<T> খুব আকর্ষণীয় বিষয় তুলে ধরেছিলেন যে কেন সি # টাইপের পরিবর্তে ব্যবহার করে :

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

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


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

1
@ পাঞ্জি: সিলোন ফ্লো-সংবেদনশীল টাইপিং ব্যবহার করে Type?(সম্ভবত) এবং Type(নাল নয়)
লুকাস এদার

1
@ রবার্টহারভে ইতিমধ্যে স্ট্যাক এক্সচেঞ্জে একটি "সুন্দর প্রশ্ন" বোতামটি নেই?
ব্যবহারকারী 253751

2
@ পাঞ্জি এটি একটি দুর্দান্ত এবং বৈধ অপ্টিমাইজেশন, তবে এটি এই সমস্যার সাথে সহায়তা করে না: যখন কোনও কিছু হয় না তখন Maybe Tতা হওয়া উচিত নয় Noneএবং তাই আপনি তার সঞ্চয় স্থানটি নাল পয়েন্টারে আরম্ভ করতে পারবেন না।

@ ইমিবিস: আমি ইতিমধ্যে এটি ঠেলে দিয়েছি। আমরা মূল্যবান কয়েকটি ভাল প্রশ্ন এখানে পাই; আমি ভাবলাম এটির একটি মন্তব্য প্রাপ্য।
রবার্ট হার্ভে

উত্তর:


45

এই উদ্ধৃতিটি এমন কোনও সমস্যার দিকে নির্দেশ করে যা সনাক্তকারীদের ঘোষণা এবং কার্যনির্বাহীকরণ (এখানে: উদাহরণস্বরূপ সদস্য) একে অপরের থেকে পৃথক থাকে। দ্রুত সিউডোকোড স্কেচ হিসাবে:

class Broken {
    val foo: Foo  // where Foo and Bar are non-nullable reference types
    val bar: Bar

    Broken() {
        foo = new Foo()
        throw new Exception()
        // this code is never reached, so "bar" is not assigned
        bar = new Bar()
    }

    ~Broken() {
        foo.cleanup()
        bar.cleanup()
    }
}

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

নালগুলির সাহায্যে, ডেস্ট্রাক্টর পরীক্ষা করতে পারত যে কোনও ভেরিয়েবলের মতো নির্ধারিত হয়েছে কিনা if (foo != null) foo.cleanup()। নালাগুলি ছাড়াই, অবজেক্টটি এখন একটি অনির্ধারিত অবস্থায় রয়েছে - এর মান কী bar?

তবে তিনটি দিকের সংমিশ্রণের কারণে এই সমস্যাটি বিদ্যমান :

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

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

// the body of the class *is* the constructor
class Working() {
    val foo: Foo = new Foo()
    FINALIZE { foo.cleanup() }  // block is registered to run when object is destroyed

    throw new Exception()

    // the below code is never reached, so
    //  1. the "bar" variable never enters the scope
    //  2. the second finalizer block is never registered.
    val bar: Bar = new Bar()
    FINALIZE { bar.cleanup() }  // block is registered to run when object is destroyed
}

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

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


চূড়ান্তকরণকারীর সাথে মোকাবেলা করার আরও একটি কারণও রয়েছে null: রেফারেন্স চক্রের সম্ভাবনার কারণে চূড়ান্তকরণের আদেশের নিশ্চয়তা নেই। তবে আমার ধারণা আপনার FINALIZEনকশাটিও এটি সমাধান করে: যদি fooইতিমধ্যে চূড়ান্ত হয়ে যায় তবে এর FINALIZEবিভাগটি কেবল চলবে না।
সুইভ

14

আপনি যে কোনও উপায়ে গ্যারান্টি দেওয়ার একই পদ্ধতিগুলি বৈধ অবস্থায় রয়েছে।

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

উদাহরণস্বরূপ, মরিচায় আপনি Point { x: 1, y: 2 }কন্সট্রাক্টর লেখার পরিবর্তে স্ট্রাক টাইপের একটি অবজেক্ট তৈরি করেন self.x = 1; self.y = 2;। অবশ্যই, এটি আপনার মনে থাকা ভাষার স্টাইলের সাথে সংঘর্ষ হতে পারে।

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

Object o;
try {
    call_can_throw();
    o = new Object();
} catch {}
use(o);

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


7

এখানে হাস্কেল কীভাবে তা করেন তা এখানে রয়েছে: (হাস্পেল কোনও বস্তু-ওরিয়েন্টেড ভাষা না হওয়ায় লিপার্টের বক্তব্যের ঠিক পাল্টা নয়)।

সতর্কতা: সামনে একটি গুরুতর হাস্কেল ফ্যানবয়ের কাছ থেকে দীর্ঘ বায়ুযুক্ত উত্তর।

টি এল; ডিআর

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

অতএব:

আমরা কি সর্বদা জানতে পারি যে একটি অ-অযোগ্য রেফারেন্স কখনই অবৈধ হিসাবে পরিলক্ষিত হয় না?

হ্যাঁ. Intএবং Maybe Intদুটি সম্পূর্ণ পৃথক ধরনের। খোঁজা Nothingএকটি প্লেইন মধ্যে Intএকটি ইন STRING "মাছ" খোঁজার তুলনীয় হবে Int32

রেফারেন্স প্রকারের একটি অ-অযোগ্য ক্ষেত্রের সাথে কোনও অবজেক্টের কনস্ট্রাক্টর সম্পর্কে কী বলা যায়?

কোনও সমস্যা নয়: হাস্কেলের মান নির্মাতারা তাদের প্রদত্ত মানগুলি গ্রহণ করতে এবং সেগুলি একত্রে রেখে কিছু করতে পারে না। কনস্ট্রাক্টর ডাকা হওয়ার আগে সমস্ত সূচনা যুক্তি ঘটে।

এই জাতীয় অবজেক্টের চূড়ান্তকরণের বিষয়ে কী, যেখানে রেফারেন্সটি পূরণ করার কথা বলে এমন কোডটি ব্যতিক্রম ছুঁড়েছিল বলে এই বিষয়টিকে চূড়ান্ত করা হয়েছে?

হাস্কেলে কোনও চূড়ান্তকরণকারী নেই, তাই আমি সত্যিই এটির সমাধান করতে পারি না। আমার প্রথম প্রতিক্রিয়াটি এখনও রয়েছে।

পূর্ণ উত্তর :

হাস্কেলের কোনও নাল নেই এবং Maybeনলগুলি উপস্থাপন করতে ডেটা টাইপ ব্যবহার করে । হতে পারে এটির মতো সংজ্ঞায়িত একটি আলগ্যাব্রিক ডেটা টাইপ :

data Maybe a = Just a | Nothing

আপনারা যারা হাস্কেলের সাথে অপরিচিত, তাদের জন্য এটি "এ Maybeহয় হয় হয় Nothingবা একটি Just a" হিসাবে পড়ুন। বিশেষ করে:

  • Maybeএটি টাইপ কনস্ট্রাক্টর : এটিকে জেনেরিক ক্লাস হিসাবে (ভুলভাবে) ভাবা যায় (যেখানে aটাইপ ভেরিয়েবল হয়)। সি # উপমাটি হ'ল class Maybe<a>{}
  • Justএকটি মান নির্মাতা : এটি এমন একটি ফাংশন যা প্রকারের একটি আর্গুমেন্ট নেয় aএবং Maybe aএমন ধরণের মান প্রদান করে যা মান থাকে। কোডটি x = Just 17সাদৃশ্যপূর্ণ int? x = 17;
  • Nothingঅন্য মান নির্মাতা, তবে এটি কোনও আর্গুমেন্ট নেয় না এবং Maybeপ্রত্যাবর্তনের "কিছুই না" ব্যতীত অন্য কোনও মান থাকে না। x = Nothingঅনুরূপ int? x = null;(অভিমানী আমরা আমাদের সীমাবদ্ধ aমধ্যে Haskell হতে Intলেখা দ্বারা সম্পন্ন করা যেতে পারে x = Nothing :: Maybe Int)।

এখন যে Maybeধরণের বেসিকগুলি বাইরে চলে গেছে, হাসেল কীভাবে ওপির প্রশ্নে আলোচিত বিষয়গুলি এড়াতে পারে?

ওয়েল, Haskell, হয় সত্যিই ভাষায় এতদূর আলোচনা বেশীর ভাগের থেকেই আলাদা, তাই আমি কয়েকটি সাধারণ ভাষা নীতির ব্যাখ্যা দ্বারা আরম্ভ করব।

প্রথম প্রথম, হাস্কেলগুলিতে, সমস্ত কিছুই অপরিবর্তনীয় । সব। নামগুলি মানগুলি উল্লেখ করে, মেমোরি অবস্থানগুলিতে নয় যেখানে মানগুলি সংরক্ষণ করা যেতে পারে (এটি একা এটি বাগ নির্মূলের এক বিরাট উত্স)। সি #, যেখানে পরিবর্তনশীল ঘোষণা এবং নিয়োগ দুটি পৃথক অভিযান Haskell, মানের মধ্যে তাদের মূল্য নির্ধারক দ্বারা তৈরি করা হয় হয় ভিন্ন (যেমন x = 15, y = "quux", z = Nothing), পরিবর্তন করতে পারে। সুতরাং, কোড যেমন:

ReferenceType x;

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

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

এরপরে, একেবারে কোনও প্রয়োজনীয় স্টাইল কোড নেই। এর মাধ্যমে, আমার অর্থ এই যে বেশিরভাগ ভাষা এই ধরণের কিছু অনুসরণ করে:

do thing 1
add thing 2 to thing 3
do thing 4
if thing 5:
    do thing 6
return thing 7

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

হাস্কেলে, এটি সম্ভব নয়। পরিবর্তে, প্রোগ্রাম ফ্লো পুরোপুরি ফাংশন শৃঙ্খলা দ্বারা নির্ধারিত হয়। এমনকি অপরিহার্য- doসন্ধানকারী - নোটেশনটি >>=অপারেটরের কাছে বেনাম ফাংশনগুলি প্রেরণের জন্য কেবল সিনট্যাকটিক চিনি । সমস্ত ফাংশন এর রূপ নেয়:

<optional explicit type signature>
functionName arg1 arg2 ... argn = body-expression

যেখানে body-expressionকোনও মান যা মূল্যায়ন করে তা হতে পারে। স্পষ্টতই আরও সংশ্লেষের বৈশিষ্ট্য উপলব্ধ রয়েছে তবে মূল বিষয়টি হ'ল বক্তব্যের ক্রমগুলির সম্পূর্ণ অনুপস্থিতি।

শেষ পর্যন্ত এবং সম্ভবত সবচেয়ে গুরুত্বপূর্ণ, হাস্কেলের টাইপ সিস্টেমটি অবিশ্বাস্যভাবে কঠোর। যদি আমাকে হাস্কেলের টাইপ সিস্টেমের কেন্দ্রীয় নকশা দর্শনের সংক্ষিপ্ত বিবরণ জানাতে হয়, তবে আমি বলব: "সংকলনের সময় যতটা সম্ভব সম্ভব ভুল করা যাতে রানটাইমের সময় যতটা সম্ভব ভুল হয়।" সেখানে কোন অন্তর্নিহিত ধর্মান্তর (একটি পদোন্নতি করার বিষয়ে নিশ্চিত Intএকটি করতে Double? ব্যবহার করুন fromIntegralফাংশন)। রানটাইমের সময় কেবলমাত্র একটি অবৈধ মান সংঘটিত হওয়ার জন্য ব্যবহার করা হয় Prelude.undefined(যা সম্ভবত আপাতত উপস্থিত থাকতে হবে এবং অপসারণ করা অসম্ভব )।

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

data NotSoBroken = NotSoBroken {foo :: Foo, bar :: Bar } 

( fooএবং barপ্রকৃত ক্ষেত্রগুলির পরিবর্তে এখানে অনামী ক্ষেত্রগুলিতে সত্যই অ্যাক্সেসর ফাংশন রয়েছে তবে আমরা এই বিশদটি উপেক্ষা করতে পারি)।

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

উদাহরণস্বরূপ, Brokenসর্বদা নির্মাণ ব্যর্থ হয়। NotSoBrokenঅনুরূপ ফ্যাশনে মান কন্সট্রাক্টরকে ভাঙার কোনও উপায় নেই (কোডটি লেখার পক্ষে কোথাও কোথাও নেই), তবে আমরা একটি কারখানা ফাংশন তৈরি করতে পারি যা একইভাবে ত্রুটিযুক্ত।

makeNotSoBroken :: Foo -> Bar -> Maybe NotSoBroken
makeNotSoBroken foo bar = Nothing

(প্রথম লাইনটি একটি ধরণের স্বাক্ষর ঘোষণা: makeNotSoBrokenএকটি Fooএবং একটি Barআর্গুমেন্ট হিসাবে গ্রহণ করে এবং উত্পাদন করে Maybe NotSoBroken)।

রিটার্নের ধরণটি অবশ্যই হতে হবে Maybe NotSoBrokenএবং তা নয় NotSoBrokenকারণ আমরা এটিকে মূল্যায়ন করতে বলেছিলাম, এটির জন্য Nothingএকটি মান নির্মাতা Maybe। আমরা আলাদা কিছু লিখলে প্রকারগুলি সহজেই লাইন হয় না।

একেবারে নিরর্থক হওয়া ছাড়াও, এই ফাংশনটি তার আসল উদ্দেশ্যটিও পূরণ করে না, যেমনটি আমরা এটি ব্যবহার করার চেষ্টা করব যখন আমরা দেখতে পাব। আসুন একটি ফাংশন তৈরি করি useNotSoBrokenযা NotSoBrokenএকটি আর্গুমেন্ট হিসাবে প্রত্যাশা করে :

useNotSoBroken :: NotSoBroken -> Whatever

( একটি আর্গুমেন্ট হিসাবে একটি useNotSoBrokenগ্রহণ NotSoBrokenকরে এবং উত্পাদন করে Whatever)।

এবং এটি এর মতো ব্যবহার করুন:

useNotSoBroken (makeNotSoBroken)

বেশিরভাগ ভাষায়, এই ধরণের আচরণের ফলে নাল পয়েন্টার ব্যতিক্রম হতে পারে। হাসকেলে, প্রকারগুলি মেলে না: makeNotSoBrokenএকটি প্রদান করে Maybe NotSoBroken, তবে useNotSoBrokenএকটি প্রত্যাশা করে NotSoBroken। এই ধরণেরগুলি বিনিময়যোগ্য নয় এবং কোডটি সংকলনে ব্যর্থ হয়।

এটি পেতে, আমরা মানের caseকাঠামোর উপর ভিত্তি করে শাখায় একটি বিবৃতি ব্যবহার করতে পারি Maybe( প্যাটার্ন ম্যাচিং নামে পরিচিত একটি বৈশিষ্ট্য ব্যবহার করে ):

case makeNotSoBroken of
    Nothing  -> --handle situation here
    (Just x) -> useNotSoBroken x

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

  • প্রথমত, makeNotSoBrokenমূল্যায়ন করা হয়, যা ধরণের মান উত্পন্ন করার গ্যারান্টিযুক্ত Maybe NotSoBroken
  • caseবিবৃতি এই মান কাঠামো inspects।
  • মানটি Nothingহলে, "হ্যান্ডেল পরিস্থিতি এখানে" কোডটি মূল্যায়ন করা হয়।
  • পরিবর্তে মানটি যদি কোনও মানের সাথে মেলে Just, তবে অন্য শাখাটি কার্যকর করা হবে। নোট করুন কীভাবে এক সাথে মিলনের ধারাটি Justনির্মাণ হিসাবে মানটিকে শনাক্ত করে এবং এর অভ্যন্তরীণ NotSoBrokenক্ষেত্রটিকে একটি নামের সাথে আবদ্ধ করে (এই ক্ষেত্রে, x)। xএরপরে ব্যবহার করা যেতে পারে যা সাধারণ NotSoBrokenমানের।

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

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


টিএল; ডিআর শীর্ষে থাকা উচিত :)
অ্যান্ড্রু.ফক্স

@ অ্যান্ড্রু ডটফক্স ভাল পয়েন্ট। আমি সম্পাদনা করব।
ApproachingDarknessFish

0

আমি মনে করি আপনার উক্তিটি স্ট্রো ম্যান যুক্তি।

আধুনিক ভাষাগুলি আজ (সি # সহ), আপনাকে গ্যারান্টি দেয় যে কনস্ট্রাক্টর সম্পূর্ণরূপে সম্পূর্ণ করেছে বা এটি সম্পন্ন করে না।

যদি কন্সট্রাক্টরের কোনও ব্যতিক্রম থাকে এবং অবজেক্টটি আংশিকভাবে অবিচ্ছিন্ন করে ফেলে রাখা হয়, অবিচ্ছিন্ন অবস্থায় থাকার কারণে nullবা Maybe::noneডিস্ট্রাক্টর কোডে কোনও বাস্তব পার্থক্য আসে না।

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

বিটিডব্লিউ: সি # তে nullমানটি অনেকটা সমান Maybe::none। আপনি ধার্য করতে পারেন nullশুধুমাত্র ভেরিয়েবল এবং বস্তুর সদস্যরা একটি টাইপ স্তরের উপর হিসেবে ঘোষণা করছেন nullable :

String? nullableString = getOptionalString();
Nullable<String> maybe = nullableString; // This is equivalent

এটি কোনওভাবেই নিম্নলিখিত স্নিপেটের চেয়ে আলাদা নয়:

Maybe<String> optionalString = getOptionalString();

সুতরাং উপসংহারে, আমি দেখতে পাই না যে কোনওভাবে Maybeধরণের বিপরীতে ন্যূনযোগ্যতা কীভাবে হয় । এমনকি আমি এটিও পরামর্শ দেব যে সি # নিজের Maybeধরণের ছিদ্রযুক্ত এবং এটি কল করেছে Nullable<T>

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

Resource? resource = initializationThatMayFail();
...
resource.ifExists( Resource r -> r.cleanup() );

2
এর অর্থ কী, "নির্মাণকারী সম্পূর্ণরূপে সম্পূর্ণ হয় বা এটি হয় না"? জাভাতে উদাহরণস্বরূপ, কনস্ট্রাক্টরের (অ-চূড়ান্ত) ক্ষেত্রের সূচনাটি ডেটা রেস থেকে সুরক্ষিত নয় - এটি কি সম্পূর্ণরূপে সম্পূর্ণ হয় বা না?
gnat

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

nullপ্রতিটি প্রকারের অন্তর্নিহিত সদস্য হিসাবে বড় পার্থক্য এবং Maybe<T>এটি হ'ল আপনারও Maybe<T>ঠিক থাকতে পারে T, যার কোনও ডিফল্ট মান নেই।
সুইভ

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

@ এসভিক: সি # তে (যা ওপি কর্তৃক প্রশ্নকৃত ভাষা ছিল), nullপ্রতিটি ধরণের অন্তর্নিহিত সদস্য নয়। জন্য nulllebal মান হতে, আপনি টাইপ স্পষ্টভাবে nullable হতে, যা একটি তোলে সংজ্ঞায়িত করতে প্রয়োজন T?(জন্য সিনট্যাক্স চিনি Nullable<T>) মূলত সমতুল্য Maybe<T>
রোল্যান্ড টেপ

-3

সি ++ এটি আরম্ভকারীটিতে অ্যাক্সেস করে যা কনস্ট্রাক্টর বডির আগে ঘটে। সি # কনস্ট্রাক্টর বডির আগে ডিফল্ট ইনিশিয়ালাইজার চালায়, এটি মোটামুটিভাবে 0 কে 0 হিসাবে নির্ধারিত করে, floats0.0 boolsহয়ে যায়, মিথ্যা হয়ে যায়, রেফারেন্সগুলি নাল হয়ে যায় ইত্যাদি। ।

class Foo { Foo(int i) { throw new Exception("Never finishes"); }
class Bar { Bar(string s) { } }

class Broken
{
    val foo: Foo  // where Foo and Bar are non-nullable reference types
    val bar: Bar

    Broken() :
        foo = new Foo(123),// roughly causes a "goto destroy_foo;"
        bar = new Bar("never executes") { }

    // This destructory-function never runs because the constructor never completed
    ~Broken() 
    // This is made-up syntax:
    // : 
    // destroy_bar:
    // bar.~Bar();
    // destroy_foo:
    // foo.~Foo();
    {
    }
}

2
প্রশ্নটি সম্ভবত প্রকারের ভাষাগুলির সাথে ছিল
জিএনটি

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

যদিও সি ++ স্থানীয়ভাবে সম্ভবত স্পষ্টভাবে প্রকারভেদ না থাকে তবে এসটিডি :: শেয়ার্ড_পিটার <টি> এর মতো বিষয়গুলি যথেষ্ট পরিমাণে আমার কাছে মনে হয় যে এটি এখনও প্রাসঙ্গিক যে সি ++ কেসটি পরিচালনা করে যেখানে ভেরিয়েবলের সূচনাটি কনস্ট্রাক্টরের "সুযোগের বাইরে" ঘটতে পারে, এবং প্রকৃতপক্ষে রেফারেন্স প্রকারের জন্য প্রয়োজন (এবং), যেহেতু এগুলি নਾਲ হতে পারে না।
ফ্রাইগ্যু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.