উত্তরটির সংজ্ঞা পাওয়া যায় map:
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That
উল্লেখ্য এটির দুটি পরামিতি রয়েছে। প্রথমটি আপনার ফাংশন এবং দ্বিতীয়টি অন্তর্নিহিত। আপনি যদি এই অন্তর্নিহিত সরবরাহ না করেন, স্কালা উপলব্ধ সর্বাধিক নির্দিষ্ট একটি চয়ন করবে ।
সম্পর্কিত breakOut
তো, এর উদ্দেশ্য কী breakOut? প্রশ্নের জন্য প্রদত্ত উদাহরণটি বিবেচনা করুন, আপনি স্ট্রিংয়ের একটি তালিকা নেন, প্রতিটি স্ট্রিংকে একটি টিপলে রূপান্তর করেন (Int, String)এবং তারপরে একটি Mapআউট উত্পাদন করেন । এটি করার সর্বাধিক সুস্পষ্ট উপায় হ'ল মধ্যস্থতাকারী List[(Int, String)]সংগ্রহ তৈরি করবে এবং তারপরে এটি রূপান্তর করবে।
প্রদত্ত সংগ্রহটি উত্পাদন করতে mapএকটি ব্যবহার করে Builderএমনটি দেওয়া হয়েছে, মধ্যস্থতাকারী এড়িয়ে যাওয়া Listএবং ফলাফলগুলি সরাসরি একটিতে সংগ্রহ করা কি সম্ভব হবে না Map? স্পষ্টতই, হ্যাঁ, এটি। এটা করার জন্য, যাইহোক, আমরা একটি সঠিক পাস করতে হবে CanBuildFromকরতে map, এবং যে ঠিক কি breakOutনা।
এর সংজ্ঞাটি এখন দেখুন breakOut:
def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b.apply() ; def apply() = b.apply()
}
নোট যেটি breakOutপ্যারামিটারাইজড, এবং এটি একটি উদাহরণ দেয় CanBuildFrom। এটি হ'ল , প্রকারগুলি From, Tএবং Toইতিমধ্যে অনুমান করা হয়েছে, কারণ আমরা জানি যে mapপ্রত্যাশা করা হচ্ছে CanBuildFrom[List[String], (Int, String), Map[Int, String]]। অতএব:
From = List[String]
T = (Int, String)
To = Map[Int, String]
উপসংহারে আসুন আমরা breakOutনিজে থেকে প্রাপ্ত অন্তর্নিহিত পরীক্ষা করি । এটি টাইপ হয় CanBuildFrom[Nothing,T,To]। আমরা ইতিমধ্যে এই সমস্ত প্রকারগুলি জানি, তাই আমরা নির্ধারণ করতে পারি যে আমাদের প্রকারের একটি অন্তর্নিহিত প্রয়োজন CanBuildFrom[Nothing,(Int,String),Map[Int,String]]। তবে এরকম সংজ্ঞা আছে কি?
যাক চেহারা CanBuildFromএর সংজ্ঞা:
trait CanBuildFrom[-From, -Elem, +To]
extends AnyRef
সুতরাং CanBuildFromএটির প্রথম ধরণের প্যারামিটারের ক্ষেত্রে বৈকল্পিক রয়েছে। কারণ Nothingনীচের শ্রেণি (যেমন, এটি সবকিছুর উপক্লাস), এর অর্থ যে কোনও শ্রেণি তার জায়গায় ব্যবহার করা যেতে পারে Nothing।
যেমন একটি নির্মাতা বিদ্যমান, স্কালাল এটিকে পছন্দসই আউটপুট উত্পাদন করতে ব্যবহার করতে পারে।
নির্মাতাদের সম্পর্কে
স্কালার সংগ্রহ লাইব্রেরি থেকে প্রচুর পদ্ধতিতে মূল সংগ্রহটি গ্রহণ, এটি কোনওভাবে প্রক্রিয়াজাতকরণ ( mapপ্রতিটি উপাদানকে রূপান্তরকরণের ক্ষেত্রে ) তৈরি করা এবং ফলাফলগুলি একটি নতুন সংগ্রহের মধ্যে সংরক্ষণ করে থাকে।
কোড পুনরায় ব্যবহারকে সর্বাধিক করে তোলার জন্য, ফলাফলগুলির এই স্টোরিং কোনও বিল্ডার ( scala.collection.mutable.Builder) এর মাধ্যমে সম্পন্ন হয় , যা মূলত দুটি ক্রিয়াকে সমর্থন করে: উপাদান সংযোজন, এবং ফলস্বরূপ সংগ্রহটি ফিরিয়ে দেয়। এই ফলাফলের সংগ্রহের ধরণটি নির্মাতার ধরণের উপর নির্ভর করবে। সুতরাং, একজন Listবিল্ডার একটি ফেরত দেবে List, একজন Mapনির্মাতা একটি Mapইত্যাদি ফিরিয়ে দেবে । mapপদ্ধতির প্রয়োগের ফলে ফলাফলের ধরণের সাথে নিজেকে উদ্বেগ করা উচিত নয়: নির্মাতা এটির যত্ন নেন।
অন্যদিকে, এর অর্থ এই যে mapএই বিল্ডারটিকে কোনওভাবে গ্রহণ করা দরকার। স্কেলা ২.৮ সংগ্রহগুলি ডিজাইন করার সময় যে সমস্যার মুখোমুখি হয়েছিল তা হ'ল কীভাবে সম্ভব সেরা নির্মাতা চয়ন করতে। উদাহরণস্বরূপ, আমি যদি লিখতে Map('a' -> 1).map(_.swap)চাই তবে আমি Map(1 -> 'a')ফিরে পেতে চাই । অন্যদিকে, একটি Map('a' -> 1).map(_._1)ফেরত দিতে পারে না Map(এটি একটি ফেরত দেয় Iterable)।
Builderএক্সপ্রেশনটির পরিচিত ধরণের থেকে সর্বোত্তম সম্ভব উত্পাদন করার CanBuildFromযাদুটি এই অন্তর্নিহিতের মাধ্যমে সঞ্চালিত হয় ।
সম্পর্কিত CanBuildFrom
কী চলছে তা আরও ভালভাবে ব্যাখ্যা করার জন্য, আমি একটি উদাহরণ দেব যেখানে সংগ্রহটি ম্যাপ করা হচ্ছে এটি একটি এর Mapপরিবর্তে List। আমি Listপরে যেতে হবে । আপাতত, এই দুটি অভিব্যক্তি বিবেচনা করুন:
Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
Map(1 -> "one", 2 -> "two") map (_._2)
প্রথমটি একটি Mapএবং দ্বিতীয়টি একটি প্রদান করে Iterable। ফিটিং কালেকশন ফিরিয়ে দেওয়ার ম্যাজিকটি হ'ল কাজ CanBuildFrom। mapএটি বুঝতে আবার সংজ্ঞা বিবেচনা করা যাক ।
পদ্ধতিটি mapউত্তরাধিকার সূত্রে প্রাপ্ত TraversableLike। এটি প্যারামিটারাইজড হয় Bএবং That, এবং ধরণের পরামিতিগুলি ব্যবহার করে Aএবং Repr, যা শ্রেণিকে প্যারামিটারাইজ করে। আসুন উভয় সংজ্ঞা একসাথে দেখুন:
শ্রেণি TraversableLikeহিসাবে সংজ্ঞায়িত করা হয়:
trait TraversableLike[+A, +Repr]
extends HasNewBuilder[A, Repr] with AnyRef
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That
যেখানে বোঝার জন্য Aএবং Reprথেকে আসা, আসুন সংজ্ঞা বিবেচনা Mapনিজেই:
trait Map[A, +B]
extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]]
কারণ TraversableLikeসব বৈশিষ্ট্যগুলো যা প্রসারিত দ্বারা উত্তরাধিকার সুত্রে প্রাপ্ত হয় Map, Aএবং Reprতাদের কাউকে কাছ থেকে উত্তরাধিকারসূত্রে যেতে পারে। যদিও সর্বশেষটি পছন্দটি পায়। সুতরাং, অপরিবর্তনীয় Mapএবং সমস্ত বৈশিষ্ট্যের সংজ্ঞা অনুসরণ করে যা এটির সাথে সংযুক্ত TraversableLikeরয়েছে:
trait Map[A, +B]
extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]]
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
extends MapLike[A, B, This]
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
extends PartialFunction[A, B] with IterableLike[(A, B), This] with Subtractable[A, This]
trait IterableLike[+A, +Repr]
extends Equals with TraversableLike[A, Repr]
trait TraversableLike[+A, +Repr]
extends HasNewBuilder[A, Repr] with AnyRef
আপনি যদি Map[Int, String]শৃঙ্খলে থেকে সমস্ত ধরণের ধরণের প্যারামিটারগুলি পাস করেন তবে আমরা দেখতে পেলাম যে প্রকারগুলি প্রবাহিত হয়েছে TraversableLike, এবং, এইভাবে ব্যবহৃত mapহয়:
A = (Int,String)
Repr = Map[Int, String]
উদাহরণটিতে ফিরে গিয়ে প্রথম মানচিত্রটি টাইপের একটি ফাংশন গ্রহণ করছে ((Int, String)) => (Int, Int)এবং দ্বিতীয় মানচিত্রটি টাইপের একটি ক্রিয়া গ্রহণ করছে ((Int, String)) => String। আমি ডাবল বন্ধনী ব্যবহারের উপর জোর দিয়েছি এটি একটি টিউপল প্রাপ্তি, Aযেমনটি আমরা দেখেছি।
সেই তথ্য সহ, আসুন অন্য ধরণের বিবেচনা করা যাক।
map Function.tupled(_ -> _.length):
B = (Int, Int)
map (_._2):
B = String
আমরা দেখতে পারি যে টাইপ প্রথম দ্বারা ফিরে mapহয় Map[Int,Int], এবং দ্বিতীয় হয় Iterable[String]। এ খুঁজছি map'র সংজ্ঞা, এটা যে এগুলোর মান দেখতে সহজ That। কিন্তু তারা কোথা থেকে আসে?
যদি আমরা জড়িত ক্লাসগুলির সহযোগী বস্তুর ভিতরে নজর রাখি তবে আমরা সেগুলি সরবরাহ করে এমন কিছু জড়িত ঘোষণা দেখতে পাই। বস্তুতে Map:
implicit def canBuildFrom [A, B] : CanBuildFrom[Map, (A, B), Map[A, B]]
এবং অবজেক্টে Iterable, যার ক্লাস দ্বারা প্রসারিত Map:
implicit def canBuildFrom [A] : CanBuildFrom[Iterable, A, Iterable[A]]
এই সংজ্ঞাগুলি পরামিতিগুলির জন্য কারখানাগুলি সরবরাহ করে CanBuildFrom।
স্কেলা সর্বাধিক নির্দিষ্ট অন্তর্নিহিত চয়ন করবে। প্রথম ক্ষেত্রে এটি প্রথম ছিল CanBuildFrom। দ্বিতীয় ক্ষেত্রে, প্রথমটি না মিলায় এটি দ্বিতীয়টিকে বেছে নিয়েছিল CanBuildFrom।
প্রশ্ন ফিরে
প্রকারগুলি কীভাবে অনুমিত করা হয় তা দেখতে আসুন, প্রশ্নের Listএবং mapতার সংজ্ঞা (আবার) কোডের কোডটি দেখুন:
val map : Map[Int,String] = List("London", "Paris").map(x => (x.length, x))(breakOut)
sealed abstract class List[+A]
extends LinearSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqLike[A, List[A]]
trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]]
extends SeqLike[A, Repr]
trait SeqLike[+A, +Repr]
extends IterableLike[A, Repr]
trait IterableLike[+A, +Repr]
extends Equals with TraversableLike[A, Repr]
trait TraversableLike[+A, +Repr]
extends HasNewBuilder[A, Repr] with AnyRef
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That
ধরণ List("London", "Paris")হয় List[String], তাই ধরনের Aএবং Reprসংজ্ঞাসমূহ TraversableLikeআছেন:
A = String
Repr = List[String]
টাইপ জন্য (x => (x.length, x))হয় (String) => (Int, String), তাই ধরণ Bহল:
B = (Int, String)
সর্বশেষ অজানা প্রকার, Thatফলাফলের ধরণ mapএবং আমাদের ইতিমধ্যে এটিও রয়েছে:
val map : Map[Int,String] =
সুতরাং,
That = Map[Int, String]
তার অর্থ breakOutঅবশ্যই প্রয়োজনীয়, একটি প্রকার বা উপ-টাইপ ফিরে আসবে CanBuildFrom[List[String], (Int, String), Map[Int, String]]।
List, কিন্তুmap।