স্কালার তালিকা কনটেনটেশন, ::: বনাম ++


361

স্কালায় তালিকাবদ্ধকরণের মধ্যে :::এবং এর মধ্যে কি কোনও পার্থক্য রয়েছে ++?

scala> List(1,2,3) ++ List(4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)

scala> List(1,2,3) ::: List(4,5)
res1: List[Int] = List(1, 2, 3, 4, 5)

scala> res0 == res1
res2: Boolean = true

থেকে ডকুমেন্টেশন এটা দেখে মনে হচ্ছে ++আরও সাধারণ যেহেতু হয় :::হয় List-specific। দ্বিতীয়টি কার্যকরী ভাষাগুলিতে ব্যবহৃত হওয়ার কারণে এটি কি সরবরাহ করা হয়?


4
এছাড়াও :::সমস্ত পদ্ধতির মতো একটি উপসর্গ অপারেটর:
বেন জ্যাকসন

3
উত্তরগুলি স্ক্যালায় তালিকাগুলি এবং অপারেটরের অভিন্নতার (বা পরবর্তীকালের অভাব) চারপাশে যেভাবে স্কালালটি বিকশিত হয়েছিল তা চিত্রিত করে। এটি কিছুটা দুর্ভাগ্যজনক যে কোনও সাধারণ স্কুলে শিক্ষার্থীর সময়কে বিভ্রান্ত করতে এবং সময় নষ্ট করার জন্য এত সাধারণ কোনও কিছুর মধ্যে মিনুটিয়ের এত দীর্ঘ লেজ থাকে। আমি আশা করি এটি 2.12-এ সমতল করা হবে।
ম্যাটানস্টার

উত্তর:


320

উত্তরাধিকার। তালিকাটি মূলত কার্যকরী-ভাষা-বর্ণিত হিসাবে সংজ্ঞায়িত করা হয়েছিল:

1 :: 2 :: Nil // a list
list1 ::: list2  // concatenation of two lists

list match {
  case head :: tail => "non-empty"
  case Nil          => "empty"
}

অবশ্যই, স্কালা একটি অন্যান্য বিজ্ঞাপন সংগ্রহ করেছে, এটি একটি বিজ্ঞাপন-পদ্ধতিতে। যখন 2.8 বেরিয়ে আসেন সংগ্রহ সর্বাধিক কোড পুনঃব্যবহারের এবং সুসংগত API- এর জন্য পুনঃডিজাইন করা হয়েছে, যাতে করে আপনি ব্যবহার করতে পারেন ++কনক্যাটেনেট করার কোনো দুই সংগ্রহ - এবং এমনকি iterators। তবে তালিকাটি তার আসল অপারেটরগুলিকে এক বা দুটি বাদ দিয়ে রেখেছিল যা হ্রাস পেয়েছে।


19
তাহলে এখনকার :::পক্ষে এড়ানো কি সেরা অনুশীলন ++? +:পরিবর্তে ব্যবহার করবেন ::?
লুইজি প্লিঞ্জ

37
::প্যাটার্ন মিলের কারণে দরকারী (ড্যানিয়েল দ্বিতীয় উদাহরণ দেখুন)। আপনার সাথে এটা করতে পার না+:
paradigmatic

1
@ লুইগি যদি আপনি এর Listপরিবর্তে ব্যবহার করেন তবে আপনি পাশাপাশি অভিবাদনমূলক পদ্ধতিও ব্যবহার Seqকরতে পারেন List। অন্যদিকে , আপনি যদি কখনও এটি করতে আগ্রহী হন তবে এটি অন্যরকমটিতে পরিবর্তন করা আরও শক্ত করে তুলবে ।
ড্যানিয়েল সি সোব্রাল

2
আমি দেখতে পেয়েছি এটি ভাল লেগেছে যে কারও কাছে তালিকার ইডিয়োম্যাটিক ক্রিয়াকলাপ (যেমন ::এবং :::) এবং আরও সাধারণ ক্রিয়াকলাপ রয়েছে যা অন্যান্য সংগ্রহের জন্য সাধারণ। ভাষা থেকে আমি উভয়ই অপারেশন ছাড়ব না।
জর্জিও

21
@paradigmatic Scala 2.10 এর :+এবং +:অবজেক্ট এক্সট্র্যাক্টর রয়েছে।
0__

96

সর্বদা ব্যবহার :::। দুটি কারণ রয়েছে: দক্ষতা এবং প্রকারের সুরক্ষা।

দক্ষতা

x ::: y ::: zতুলনায় দ্রুত x ++ y ++ z, কারণ :::ডান সহযোগী। x ::: y ::: zপার্স করা হয় x ::: (y ::: z), যা আলগোরিদিমিকভাবে দ্রুত (x ::: y) ::: z(পরবর্তীটির জন্য ও (| x |) আরও পদক্ষেপ প্রয়োজন)।

সুরক্ষা টাইপ করুন

:::আপনি কেবল দুটি Listগুলি সংযুক্ত করতে পারেন সঙ্গে । এর মাধ্যমে ++আপনি যে কোনও সংগ্রহ সংযোজন করতে পারেন List, যা ভয়ানক:

scala> List(1, 2, 3) ++ "ab"
res0: List[AnyVal] = List(1, 2, 3, a, b)

++এর সাথে মেশানোও সহজ +:

scala> List(1, 2, 3) + "ab"
res1: String = List(1, 2, 3)ab

9
মাত্র 2 টি তালিকার সাথে যুক্ত করার সময়, কোনও পার্থক্য নেই, তবে 3 বা ততোধিকের ক্ষেত্রে আপনার ভাল বক্তব্য রয়েছে এবং আমি এটি দ্রুত বেঞ্চমার্ক দিয়ে নিশ্চিত করেছি। তবে, যদি আপনি দক্ষতা সম্পর্কে চিন্তিত হন তবে x ::: y ::: zএটি প্রতিস্থাপন করা উচিত List(x, y, z).flattenপেস্টবিন.
com/gkx7Hpad

3
দয়া করে ব্যাখ্যা করুন, কেন বাম সহযোগী সংমিশ্রণে আরও ও (এক্স) পদক্ষেপ প্রয়োজন। আমি ভেবেছিলাম যে তারা দু'জনেই ও (1) এর জন্য কাজ করে।
প্যাকম্যান

6
@ প্যাকম্যান তালিকাগুলি এককভাবে লিঙ্কযুক্ত, একটি তালিকা অন্যটিতে যুক্ত করতে আপনাকে প্রথম তালিকার একটি অনুলিপি তৈরি করতে হবে যা শেষে দ্বিতীয়টির সাথে সংযুক্ত থাকে। প্রতিযোগিতা তাই O (n) প্রথম তালিকার উপাদানের সংখ্যার সাথে সম্মতিযুক্ত। দ্বিতীয় তালিকার দৈর্ঘ্য রানটাইমকে প্রভাবিত করে না তাই একটি দীর্ঘ তালিকাতে সংক্ষিপ্ত তালিকা সংযোজন না করে সংক্ষিপ্ত তালিকায় দীর্ঘ তালিকা যুক্ত করা ভাল।
পুহলেন

1
@ প্যাকম্যান স্কালার তালিকা অপরিবর্তনীয় । একারণে আমরা যখন শেষ লিঙ্কটি প্রতিস্থাপন করতে পারি না তখনই। আমাদের অবশ্যই স্ক্র্যাচ থেকে একটি নতুন তালিকা তৈরি করতে হবে।
heেকা কোজলভ

4
@pacman জটিলতা দৈর্ঘ্য wrt রৈখিক সর্বদা xএবং y( zকোনো ক্ষেত্রে iterated না হয় তাই রান টাইম উপর কোনো প্রভাব নেই, এই কারণে এটি ভালো একটি সংক্ষিপ্ত এক একটি দীর্ঘ তালিকা সংযোজন করতে, অন্য উপায় কাছাকাছি তুলনায়) কিন্তু অ্যাসিপটোটিক জটিলতা পুরো গল্পটি বলে না। x ::: (y ::: z)পুনরাবৃত্তি yএবং সংযোজন z, তারপরে পুনরাবৃত্ত হয় xএবং এর ফলাফল সংযোজন করে y ::: zxএবং yউভয়ই একবার পুনরাবৃত্তি হয়। (x ::: y) ::: zপুনরাবৃত্তি xএবং সংযোজন y, তারপরে পুনরাবৃত্তি x ::: yএবং সংযোজন ফলাফল zyএখনও একবারে xপুনরাবৃত্তি হয় তবে এই ক্ষেত্রে দু'বার পুনরাবৃত্তি করা হয়।
puhlen

84

:::কেবল তালিকাগুলির সাথে কাজ করে, যখন ++কোনও ট্র্যাভারেবলের সাথে ব্যবহার করা যায়। বর্তমান বাস্তবায়নে (২.৯.০), যুক্তিটিও যদি একটি ++হয় :::তবে পিছনে পড়ে List


4
সুতরাং ::: এবং ++ তালিকার সাথে কাজ করা উভয়ই ব্যবহার করা খুব সহজ। এটি সম্ভবত কোড / শৈলীতে একটি বিশৃঙ্খলা রাখতে পারে।
ses

24

একটি ভিন্ন বিষয় হ'ল প্রথম বাক্যটি এইরূপে পার্স করা হয়েছে:

scala> List(1,2,3).++(List(4,5))
res0: List[Int] = List(1, 2, 3, 4, 5)

যেখানে দ্বিতীয় উদাহরণটি বিশ্লেষণ করা হয়েছে:

scala> List(4,5).:::(List(1,2,3))
res1: List[Int] = List(1, 2, 3, 4, 5)

সুতরাং আপনি যদি ম্যাক্রো ব্যবহার করছেন তবে আপনার যত্ন নেওয়া উচিত।

পাশাপাশি ++দুটি তালিকার জন্য কল করা হচ্ছে::: তবে আরও ওভারহেড রয়েছে কারণ এটি তালিকা থেকে তালিকাতে কোনও বিল্ডারকে অন্তর্নিহিত মানের জন্য জিজ্ঞাসা করছে। তবে মাইক্রোব্যাঙ্কমার্কস সেই অর্থে কার্যকর কিছু প্রমাণ করতে পারেনি, আমি অনুমান করি যে সংকলক এই জাতীয় কলগুলি অনুকূল করে izes

উষ্ণায়নের পরে মাইক্রো-বেঞ্চমার্কগুলি।

scala>def time(a: => Unit): Long = { val t = System.currentTimeMillis; a; System.currentTimeMillis - t}
scala>def average(a: () => Long) = (for(i<-1 to 100) yield a()).sum/100

scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ++ List(e) } })
res1: Long = 46
scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ::: List(e ) } })
res2: Long = 46

ড্যানিয়েল সি। সোব্রাই যেমন বলেছিলেন, আপনি যে কোনও সংগ্রহের বিষয়বস্তু ব্যবহার করে কোনও তালিকায় যুক্ত করতে পারেন ++, তবে আপনার সাথে :::কেবল তালিকাগুলিই সংগৃহীত করতে পারে।


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