উত্তরটির সংজ্ঞা পাওয়া যায় 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
।