টাইপ প্যারামিটারের টাইপ আর্গুমেন্টের জন্য কৌশলটির নাম?


9

সেটআপ: ধরে নেওয়া যাক আমাদের নামে Iteratorএকটি প্রকার রয়েছে যার একটি টাইপ প্যারামিটার রয়েছে Element:

interface Iterator<Element> {}

তারপরে আমাদের একটি ইন্টারফেস রয়েছে Iterableযার একটি পদ্ধতি রয়েছে যা একটি ফিরে আসবে Iterator

// T has an upper bound of Iterator
interface Iterable<T: Iterator> {
    getIterator(): T
}

Iteratorজেনেরিক হওয়ার বিষয়টি হ'ল আমাদের এটিকে প্রকারের যুক্তি দিয়ে সরবরাহ করতে হবে।

এটি সমাধান করার জন্য একটি ধারণা হ'ল পুনরুক্তির ধরণটি "অনুমান করা"। নিম্নলিখিত সিউডো কোডটি ধারণাটি প্রকাশ করে যে এখানে একটি ধরণের ভেরিয়েবল রয়েছে Elementযা অনুমান করা হয় যে এটির জন্য প্রকারের যুক্তি হতে পারে Iterator:

interface <Element> Iterable<T: Iterator<Element>> {
    getIterator(): T
}

এবং তারপরে আমরা এটিকে কোথাও ব্যবহার করি:

class Vec<Element> implements Iterable<VecIterator<Element>> {/*...*/}

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


প্রশ্নাবলী:

  • এই inferred ধরণের ভেরিয়েবলের জন্য কি কোনও প্রতিষ্ঠিত নাম রয়েছে? সামগ্রিকভাবে কৌশল সম্পর্কে কী? নির্দিষ্ট নামকরণ না জেনে বুনোতে এই উদাহরণগুলির সন্ধান করা বা ভাষার নির্দিষ্ট বৈশিষ্ট্যগুলি সম্পর্কে জানতে অসুবিধা হয়েছে।
  • জেনেরিক সহ সমস্ত ভাষায় এই কৌশলটি নেই; এই ভাষাগুলিতে কি একই জাতীয় প্রযুক্তির নাম রয়েছে ?

1
আপনি কি এমন কিছু কোড প্রদর্শন করতে পারেন যা সংকলন করতে চান তা সংকলন করে না? আমি মনে করি এটি প্রশ্নকে আরও পরিষ্কার করে দেবে।
সুইপার

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

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

উত্তর:


2

আমি জানিনা এই সমস্যার জন্য একটি নির্দিষ্ট শব্দ আছে কিনা, তবে এখানে তিনটি সাধারণ শ্রেণির সমাধান রয়েছে:

  • গতিশীল প্রেরণের পক্ষে কংক্রিটের প্রকারগুলি এড়িয়ে চলুন
  • টাইপ সীমাবদ্ধতায় স্থানধারক ধরণের পরামিতিগুলিকে অনুমতি দিন
  • সম্পর্কিত ধরণের / ধরণের পরিবারগুলি ব্যবহার করে প্রকারের পরামিতিগুলি এড়ান

এবং অবশ্যই ডিফল্ট সমাধান: এই সমস্ত পরামিতিগুলি বানান রাখুন।

কংক্রিটের ধরণগুলি এড়িয়ে চলুন।

আপনি একটি Iterableইন্টারফেস হিসাবে এটি সংজ্ঞায়িত করেছেন:

interface <Element> Iterable<T: Iterator<Element>> {
    getIterator(): T
}

এটি ইন্টারফেসের ব্যবহারকারীদের সর্বাধিক শক্তি দেয় কারণ তারা Tপুনরুক্তির সঠিক কংক্রিট ধরণের পায়। এটি একটি সংকলককে ইনলাইনিংয়ের মতো আরও অনুকূলিতকরণ প্রয়োগ করতেও সহায়তা করে।

তবে, যদি Iterator<E>গতিশীলভাবে প্রেরণ করা ইন্টারফেস হয় তবে কংক্রিটের ধরণটি জানা জরুরী নয়। এটি উদাহরণস্বরূপ জাভা ব্যবহার করে এমন সমাধান। ইন্টারফেসটি তখন লেখা হবে:

interface Iterable<Element> {
    getIterator(): Iterator<Element>
}

এর একটি আকর্ষণীয় প্রকরণটি হ'ল রাস্টের impl Traitসিনট্যাক্স যা আপনাকে একটি বিমূর্ত রিটার্ন টাইপের সাহায্যে ফাংশনটি ঘোষণা করতে দেয় তবে কংক্রিটের ধরণটি কল সাইটে জানা যাবে (এইভাবে অপ্টিমাইজেশনের অনুমতি দেয়)। এটি একটি অন্তর্নিহিত ধরণের পরামিতিগুলির অনুরূপ আচরণ করে।

স্থানধারক ধরণের পরামিতিগুলির অনুমতি দিন।

Iterableইন্টারফেস, উপাদান টাইপ সম্পর্কে জানতে তাই এটি এই লিখতে সম্ভব হতে পারে প্রয়োজন নেই:

interface Iterable<T: Iterator<_>> {
    getIterator(): T
}

যেখানে T: Iterator<_>উপাদানটির ধরন নির্বিশেষে “টি কোনও পুনরুক্তি হয়” বাধাটি প্রকাশ করে। আরও কঠোরভাবে, আমরা এটিকে প্রকাশ করতে পারি: "কোনও ধরণের উপস্থিত রয়েছে Elementতাই এটি Tএকটি Iterator<Element>", এর জন্য কোনও কংক্রিটের প্রকারভেদ না জেনে Element। এর অর্থ হ'ল টাইপ-এক্সপ্রেশনটি Iterator<_>প্রকৃত ধরণের বর্ণনা দেয় না এবং কেবল টাইপ সীমাবদ্ধতা হিসাবে ব্যবহার করা যেতে পারে।

প্রকারের পরিবার / সম্পর্কিত ধরণের ব্যবহার করুন।

সি ++ তে যেমন কোনও টাইপের সদস্য থাকতে পারে। এটি সাধারণত স্ট্যান্ডার্ড লাইব্রেরি জুড়ে ব্যবহৃত হয়, যেমন std::vector::value_type। এটি সত্যই সমস্ত পরিস্থিতিতে প্যারামিটার ধরণের সমস্যাটি সমাধান করে না, তবে যেহেতু একটি প্রকার অন্য ধরণের ক্ষেত্রে উল্লেখ করতে পারে তাই একক প্রকারের প্যারামিটার সম্পর্কিত ধরণের পুরো পরিবারকে বর্ণনা করতে পারে।

আসুন সংজ্ঞা দিন:

interface Iterator {
  type ElementType
  fn next(): ElementType
}

interface Iterable {
  type IteratorType: Iterator
  fn getIterator(): IteratorType
}

তারপর:

class Vec<Element> implement Iterable {
  type IteratorType = VecIterator<Element>
  fn getIterator(): IteratorType { ... }
}

class VecIterator<T> implements Iterator {
  type ElementType = T
  fn next(): ElementType { ... }
}

এটি দেখতে খুব নমনীয় মনে হচ্ছে তবে নোট করুন যে এটি ধরণের প্রতিবন্ধকতা প্রকাশ করা আরও কঠিন করে তুলতে পারে। যেমন লিখিত হিসাবে Iterableকোনও পুনরাবৃত্ত উপাদান উপাদান প্রকার প্রয়োগ করে না এবং আমরা এর interface Iterator<T>পরিবর্তে ঘোষণা করতে চাই । এবং আপনি এখন মোটামুটি জটিল ধরণের ক্যালকুলাস নিয়ে কাজ করছেন। দুর্ঘটনাক্রমে এ জাতীয় ধরণের সিস্টেমটিকে অনির্বাণযোগ্য করে তোলা খুব সহজ (বা এটি ইতিমধ্যে ইতিমধ্যে?)।

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

interface Iterable<T: Iterator<_>, Element = T::Element> {
  ...
}

তবে এটি কেবল একটি ভাষা এরগনমিক্স বৈশিষ্ট্য এবং ভাষাটিকে আরও শক্তিশালী করে না।


প্রকার সিস্টেমগুলি কঠিন, তাই অন্যান্য ভাষায় কী করে এবং কী করে না সে সম্পর্কে একবার নজর দেওয়া ভাল।

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

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

সাধারণত কোন নিদর্শনগুলি ব্যবহৃত হয় তা দেখার জন্য এই ভাষার স্ট্যান্ডার্ড লাইব্রেরিগুলি (বিশেষত স্ট্যান্ডার্ড লাইব্রেরি সংগ্রহগুলি তালিকাগুলি বা হ্যাশ টেবিলগুলি) দেখার জন্য এটিও মূল্যবান। উদাহরণস্বরূপ, সি ++ এর বিভিন্ন পুনরুক্তিযোগ্য ক্ষমতাগুলির একটি জটিল সিস্টেম রয়েছে এবং স্কালা বৈশিষ্ট্য হিসাবে সূক্ষ্ম-দানা সংগ্রহের ক্ষমতা এনকোড করে। জাভা স্ট্যান্ডার্ড লাইব্রেরি ইন্টারফেসগুলি কখনও কখনও উদ্বুদ্ধ হয় না, যেমন Iterator#remove(), তবে একজাতীয় ধরণের (যেমন Map.Entry) হিসাবে নেস্টেড ক্লাস ব্যবহার করতে পারে ।

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