স্কেলা 2.8 ব্রেকআউট


225

স্কেলা ২.৮ এ এখানে একটি অবজেক্ট রয়েছে scala.collection.package.scala:

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()
 }

আমাকে বলা হয়েছে যে এর ফলাফলগুলি:

> import scala.collection.breakOut
> val map : Map[Int,String] = List("London", "Paris").map(x => (x.length, x))(breakOut)

map: Map[Int,String] = Map(6 -> London, 5 -> Paris)

এখানে কি হচ্ছে? আমার পক্ষে যুক্তি হিসাবে কেন breakOutডাকা হচ্ছে ?List


13
তুচ্ছ উত্তর হচ্ছে, এটি একটি যুক্তি নয় List, কিন্তু map
ড্যানিয়েল সি সোব্রাল

উত্তর:


325

উত্তরটির সংজ্ঞা পাওয়া যায় 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। ফিটিং কালেকশন ফিরিয়ে দেওয়ার ম্যাজিকটি হ'ল কাজ CanBuildFrommapএটি বুঝতে আবার সংজ্ঞা বিবেচনা করা যাক ।

পদ্ধতিটি 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]]


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

3
@ শেঠ এটি একটি বৈধ উদ্বেগ, তবে আমি নিশ্চিত না যে আমি এই কাজটি করে যাচ্ছি। এর উত্সটি এখানে পাওয়া যাবে: নিবন্ধ . gmane.org/gmane.comp.lang.scala.internals/1812/… । আমি এটি সম্পর্কে চিন্তা করব, তবে, এখনই, আমি এটির উন্নতির কোনও উপায় নিয়ে ভাবতে পারি না।
ড্যানিয়েল সি সোব্রাল

2
মানচিত্রের পুরো ফলাফলের ধরণ [ইন্ট, স্ট্রিং] উল্লেখ না করে এবং এর পরিবর্তে এমন কিছু লিখতে সক্ষম হওয়ার উপায় আছে: 'মানচিত্র = তালিকা ("লন্ডন", "প্যারিস")। মানচিত্র (x => (এক্স)। দৈর্ঘ্য, এক্স)) (ব্রেকআউট [... মানচিত্র]) '
ITayD

9
@ শেঠটিউজ আমার এই ব্যাখ্যাটি পড়তে দেখে মনে হয় আপনার বিল্ডার একটি তালিকা [স্ট্রিং] থেকে যে প্রয়োজনীয়তাটি তৈরি করতে হবে তার প্রয়োজনের "ব্রেকআপ" প্রয়োজন break সংকলকটি একটি ক্যানবিল্ডফর্ম [তালিকা [স্ট্রিং], (ইনট, স্ট্রিং), মানচিত্র [ইনট, স্ট্রিং]] চায় যা আপনি সরবরাহ করতে পারবেন না। ব্রেকআউট ফাংশন এটি কিছুই নাতে সেট করে ক্যানবিল্ডফ্রমে প্রথম ধরণের প্যারামিটার ক্লোবার্ব করে does এখন আপনাকে কেবল একটি ক্যানবিল্ডফ্রম [কিছুই নয়, (ইনট, স্ট্রিং), মানচিত্র [ইনট, স্ট্রিং]] সরবরাহ করতে হবে। এটি সহজ কারণ এটি মানচিত্র শ্রেণি দ্বারা সরবরাহ করা হয়েছে।
চিহ্নিত করুন

2
@ মার্ক যখন আমি ব্রেকআউট পেয়েছি, তখন যে সমস্যাটি আমি এটিকে সম্বোধন করেছি তা হ'ল মোনাডস যেভাবে নিজের ধরণের ম্যাপিংয়ের জন্য (বাইন্ড / ফ্ল্যাটম্যাপের মাধ্যমে) জোর দিয়েছিলেন was এটি একটি মোনডকে বিভিন্ন মনাড ধরণের ব্যবহার করে ম্যাপিং চেইনের "ব্রেকআউট" করতে দেয়। যদিও আদ্রিয়ান মুরস (লেখক) এটি সম্পর্কে কী ভাবছিলেন তা আমার কোনও ধারণা নেই!
এড স্টাব

86

আমি ড্যানিয়েল এর উত্তর উপর ভিত্তি করে করতে চাই। এটি খুব পুঙ্খানুপুঙ্খ ছিল, তবে মন্তব্যে যেমন উল্লেখ করা হয়েছে, ব্রেকআউট কী করে তা ব্যাখ্যা করে না।

পুনঃ থেকে নেওয়া : সুস্পষ্ট নির্মাতাদের সমর্থন (২০০৯-১০-২৩), আমি বিশ্বাস করি ব্রেকআউট যা করে:

এটি সংকলককে কোন পরামর্শ দেয় যা নির্মাতাকে সুস্পষ্টভাবে চয়ন করতে পারে (মূলত এটি সংকলকটিকে কোন ফ্যাক্টরি বলে মনে করে পরিস্থিতি সবচেয়ে ভাল ফিট করে তা চয়ন করতে দেয় allows)

উদাহরণস্বরূপ, নিম্নলিখিতটি দেখুন:

scala> import scala.collection.generic._
import scala.collection.generic._

scala> import scala.collection._
import scala.collection._

scala> import scala.collection.mutable._
import scala.collection.mutable._

scala>

scala> 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: [From, T, To]
     |    (implicit b: scala.collection.generic.CanBuildFrom[Nothing,T,To])
     |    java.lang.Object with
     |    scala.collection.generic.CanBuildFrom[From,T,To]

scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)

scala> val imp = l.map(_ + 1)(breakOut)
imp: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 3, 4)

scala> val arr: Array[Int] = l.map(_ + 1)(breakOut)
imp: Array[Int] = Array(2, 3, 4)

scala> val stream: Stream[Int] = l.map(_ + 1)(breakOut)
stream: Stream[Int] = Stream(2, ?)

scala> val seq: Seq[Int] = l.map(_ + 1)(breakOut)
seq: scala.collection.mutable.Seq[Int] = ArrayBuffer(2, 3, 4)

scala> val set: Set[Int] = l.map(_ + 1)(breakOut)
seq: scala.collection.mutable.Set[Int] = Set(2, 4, 3)

scala> val hashSet: HashSet[Int] = l.map(_ + 1)(breakOut)
seq: scala.collection.mutable.HashSet[Int] = Set(2, 4, 3)

আপনি দেখতে পাচ্ছেন প্রত্যাশিত প্রকারের সাথে সর্বোত্তম ম্যাচের জন্য রিটার্নের ধরণটি স্পষ্টভাবে সংকলক দ্বারা বেছে নেওয়া হয়েছে। আপনি কীভাবে গ্রহণযোগ্য পরিবর্তনশীল ঘোষণা করবেন তার উপর নির্ভর করে আপনি বিভিন্ন ফলাফল পাবেন।

নিম্নলিখিতটি কোনও বিল্ডার নির্দিষ্ট করার জন্য একটি সমতুল উপায় হবে। এই ক্ষেত্রে দ্রষ্টব্য, সংকলকটি বিল্ডারের ধরণের ভিত্তিতে প্রত্যাশিত প্রকারটি নির্ধারণ করবে:

scala> def buildWith[From, T, To](b : Builder[T, To]) =
     |    new CanBuildFrom[From, T, To] {
     |      def apply(from: From) = b ; def apply() = b
     |    }
buildWith: [From, T, To]
     |    (b: scala.collection.mutable.Builder[T,To])
     |    java.lang.Object with
     |    scala.collection.generic.CanBuildFrom[From,T,To]

scala> val a = l.map(_ + 1)(buildWith(Array.newBuilder[Int]))
a: Array[Int] = Array(2, 3, 4)

1
আমি ভাবছি কেন এর নাম " breakOut" রাখা হয়েছে? আমি মনে করি এর মতো convertবা buildADifferentTypeOfCollection(তবে সংক্ষিপ্ত) কিছু মনে রাখা আরও সহজ হতে পারে।
কাজম্যাগনুস

8

ড্যানিয়েল সোব্রালের উত্তর দুর্দান্ত, এবং স্কালা সংগ্রহের আর্কিটেকচারের সাথে একসাথে পড়া উচিত (স্কালায় প্রোগ্রামিংয়ের অধ্যায় 25)।

আমি কেবল এটি কেন বলা হয় তা ব্যাখ্যা করতে চেয়েছিলাম breakOut:

কেন বলা হয় breakOut?

কারণ আমরা এক ধরণের থেকে অন্য ধরণের মধ্যে বিচ্ছেদ করতে চাই :

কোন প্রকারে ভেঙে পড়ুন? পড়তে দেয় mapউপর ফাংশন Seqএকটি উদাহরণ হিসাবে:

Seq.map[B, That](f: (A) -> B)(implicit bf: CanBuildFrom[Seq[A], B, That]): That

যদি আমরা কোনও অনুক্রমের উপাদানগুলির উপর ম্যাপিং থেকে সরাসরি একটি মানচিত্র তৈরি করতে চাই যেমন:

val x: Map[String, Int] = Seq("A", "BB", "CCC").map(s => (s, s.length))

সংকলকটি অভিযোগ করবে:

error: type mismatch;
found   : Seq[(String, Int)]
required: Map[String,Int]

সেক শুধুমাত্র অন্য সেক কীভাবে তৈরি করতে জানে তার কারণ (যেমন একটি অন্তর্নিহিত CanBuildFrom[Seq[_], B, Seq[B]]নির্মাতা কারখানা উপলব্ধ, তবে সেক থেকে মানচিত্রের কোনও বিল্ডার কারখানা নেই)।

সংকলনের জন্য, আমাদের কোনও breakOutপ্রকারের প্রয়োজনের প্রয়োজন , এবং কোনও বিল্ডার তৈরি করতে সক্ষম হবেন যা mapফাংশনটি ব্যবহারের জন্য একটি মানচিত্র তৈরি করে ।

ড্যানিয়েল যেমন ব্যাখ্যা করেছেন, ব্রেকআউটের নিম্নলিখিত স্বাক্ষর রয়েছে:

def breakOut[From, T, To](implicit b: CanBuildFrom[Nothing, T, To]): CanBuildFrom[From, T, To] =
    // can't just return b because the argument to apply could be cast to From in b
    new CanBuildFrom[From, T, To] {
      def apply(from: From) = b.apply()
      def apply()           = b.apply()
    }

Nothingসমস্ত শ্রেণীর একটি সাবক্লাস, সুতরাং যে কোনও বিল্ডার কারখানার জায়গায় প্রতিস্থাপন করা যেতে পারে implicit b: CanBuildFrom[Nothing, T, To]। যদি আমরা অন্তর্ভুক্ত প্যারামিটার সরবরাহ করতে ব্রেকআউট ফাংশনটি ব্যবহার করি:

val x: Map[String, Int] = Seq("A", "BB", "CCC").map(s => (s, s.length))(collection.breakOut)

এটি সংকলন করবে, কারণ breakOutপ্রয়োজনীয় ধরণের সরবরাহ করতে সক্ষম CanBuildFrom[Seq[(String, Int)], (String, Int), Map[String, Int]], যখন সংকলক প্রকৃত নির্মাতা তৈরি করতে ব্রেকআউট ব্যবহারের CanBuildFrom[Map[_, _], (A, B), Map[A, B]]জায়গায়, এর জায়গায় একটি প্রকারের অন্তর্নিহিত নির্মাতা কারখানার সন্ধান CanBuildFrom[Nothing, T, To]করতে সক্ষম।

নোটটি CanBuildFrom[Map[_, _], (A, B), Map[A, B]]মানচিত্রে সংজ্ঞায়িত করা হয়েছে এবং MapBuilderএকটি অন্তর্নিহিত মানচিত্র ব্যবহার করে কেবল এমনটি সূচনা করে ।

আশা করি এটি পরিষ্কার হয়ে যাবে।


4

কী breakOutকরে তা বোঝার একটি সাধারণ উদাহরণ :

scala> import collection.breakOut
import collection.breakOut

scala> val set = Set(1, 2, 3, 4)
set: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

scala> set.map(_ % 2)
res0: scala.collection.immutable.Set[Int] = Set(1, 0)

scala> val seq:Seq[Int] = set.map(_ % 2)(breakOut)
seq: Seq[Int] = Vector(1, 0, 1, 0) // map created a Seq[Int] instead of the default Set[Int]

উদাহরণের জন্য ধন্যবাদ! এছাড়াও val seq:Seq[Int] = set.map(_ % 2).toVectorএটি আপনাকে পুনরাবৃত্ত মান দেয় না কারণ Setএটির জন্য সংরক্ষণ করা হয়েছিল map
ম্যাথু পিকিং

@ ম্যাথু পিকিং সঠিক! set.map(_ % 2)একটি Set(1, 0)প্রথম তৈরি করে , যা পরে ক এ রূপান্তরিত হয় Vector(1, 0)
fdietze
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.