স্কালার ফলন কী?


উত্তর:


205

এটি ক্রম বোঝার জন্য ব্যবহৃত হয় (পাইথনের তালিকা-বোঝার এবং জেনারেটরের মতো, যেখানে yieldআপনিও ব্যবহার করতে পারেন )।

এটি forএকত্রিত হয়ে প্রয়োগ করা হয় এবং ফলাফলের ক্রমটিতে একটি নতুন উপাদান লেখেন।

সাধারণ উদাহরণ ( স্কেলা-ল্যাং থেকে )

/** Turn command line arguments to uppercase */
object Main {
  def main(args: Array[String]) {
    val res = for (a <- args) yield a.toUpperCase
    println("Arguments: " + res.toString)
  }
}

F # এ সম্পর্কিত অভিব্যক্তিটি হবে

[ for a in args -> a.toUpperCase ]

অথবা

from a in args select a.toUpperCase 

লিঙ্কে

রুবির এর yieldআলাদা প্রভাব রয়েছে।


57
তাহলে কেন আমি মানচিত্রের পরিবর্তে ফলন ব্যবহার করব? এই মানচিত্রের কোডটি সমমানের ভ্যালি রেস = আরগস.ম্যাপ (_। টুঅপারকেস), তাই না?
জিও

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

22
ঠিক। আপনার যদি কেবল একটি সাধারণ মানচিত্র থাকে - একটি জেনারেটর নেই তবে - আমি অবশ্যই বলব যে ম্যাপিং কলিংটি আরও পাঠযোগ্য। যদি একে অপরের উপর নির্ভর করে আপনার বেশ কয়েকটি জেনারেটর এবং / অথবা ফিল্টার থাকে তবে আপনি ভাব প্রকাশের পক্ষে পছন্দ করতে পারেন।
আলেক্সি রোমানভ

13
দয়া করে নোট করুন যে প্রদত্ত উদাহরণটি মানচিত্রের অভিব্যক্তির সমতুল্য নয়: এটি একই। বোঝার জন্য একটি মানচিত্র, ফ্ল্যাটম্যাপ এবং ফিল্টার কলগুলিতে অনুবাদ করা হয়।
ড্যানিয়েল সি সোব্রাল

9
উত্তরটি এর আগে শুরু হয়: "এটি ক্রম বোঝার জন্য ব্যবহৃত হয় (পাইথনের তালিকা-বোঝার এবং জেনারেটরের মতো, যেখানে আপনি ফলনও ব্যবহার করতে পারেন)"। এটি ভুল করে একজনকে ভাবতে পরিচালিত করে যে স্কালায় ফলন পাইথনের ফলনের অনুরূপ। এই ক্ষেত্রে না হয়. পাইথনে, ফলন করোটাইনগুলির (বা ধারাবাহিকতা) প্রসঙ্গে ব্যবহৃত হয় যদিও স্কালায় এটি হয় না। আরও স্পষ্টতার জন্য, দয়া করে এই থ্রেডটি দেখুন: স্ট্যাকওভারফ্লো.com
রিচার্ড গমেস

817

আমি মনে করি গ্রহণযোগ্য উত্তরটি দুর্দান্ত, তবে মনে হচ্ছে অনেক লোক কিছু মৌলিক বিষয়গুলি বুঝতে ব্যর্থ হয়েছে।

প্রথমত, স্কালার forবোধগম্যতা হ্যাস্কেলের doস্বীকৃতির সমতুল্য এবং এটি একাধিক monadic ক্রিয়াকলাপের রচনার জন্য সিনট্যাকটিক চিনির চেয়ে বেশি কিছু নয়। যেহেতু এই বিবৃতিটি সম্ভবত সহায়তার প্রয়োজন এমন কাউকে সাহায্য করবে না, আসুন আবার চেষ্টা করুন ... :-)

forমানচিত্র সহ একাধিক ক্রিয়াকলাপের সংমিশ্রণের জন্য স্কালার উপলব্ধিগুলি সিনট্যাকটিক চিনি flatMapএবং filter। বা foreach। স্কালা আসলে forসেই পদ্ধতিগুলিতে কলগুলিতে একটি এক্সপ্রেশনকে অনুবাদ করে, সুতরাং যে কোনও শ্রেণি তাদের সরবরাহ করে, বা সেগুলির একটি উপসর্গ বোঝার জন্য ব্যবহার করা যেতে পারে।

প্রথমে অনুবাদগুলি সম্পর্কে কথা বলি। খুব সহজ নিয়ম আছে:

  1. এই

    for(x <- c1; y <- c2; z <-c3) {...}

    অনুবাদ করা হয়

    c1.foreach(x => c2.foreach(y => c3.foreach(z => {...})))
  2. এই

    for(x <- c1; y <- c2; z <- c3) yield {...}

    অনুবাদ করা হয়

    c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))
  3. এই

    for(x <- c; if cond) yield {...}

    স্কেলা ২. 2. এ অনুবাদ করা হয়েছে

    c.filter(x => cond).map(x => {...})

    বা, স্কেলা ২.৮-তে, প্রবেশ করুন

    c.withFilter(x => cond).map(x => {...})

    পদ্ধতি withFilterযদি না পাওয়া যায় তবে তা প্রাক্তনটিতে ফ্যালব্যাক সহ filter। এই সম্পর্কে আরও তথ্যের জন্য দয়া করে নীচের বিভাগটি দেখুন।

  4. এই

    for(x <- c; y = ...) yield {...}

    অনুবাদ করা হয়

    c.map(x => (x, ...)).map((x,y) => {...})

আপনি যখন খুব সাধারণ forবোধগম্যতা দেখেন, তখন map/ foreachবিকল্পগুলি প্রকৃতপক্ষে আরও ভাল দেখায়। একবার আপনি তাদের রচনা করা শুরু করলেও, আপনি খুব সহজেই প্রথম বন্ধনী এবং নেস্টিং স্তরে হারিয়ে যেতে পারেন। যখন এটি হয়, forবোধগম্যতা সাধারণত অনেক বেশি পরিষ্কার হয়।

আমি একটি সাধারণ উদাহরণ দেখাব এবং ইচ্ছাকৃতভাবে কোনও ব্যাখ্যা বাদ দেব। কোন সিনট্যাক্সটি বোঝা সহজ ছিল তা আপনি সিদ্ধান্ত নিতে পারেন।

l.flatMap(sl => sl.filter(el => el > 0).map(el => el.toString.length))

অথবা

for {
  sl <- l
  el <- sl
  if el > 0
} yield el.toString.length

withFilter

স্কেলা ২.৮ একটি নামক পদ্ধতি প্রবর্তন করেছিল withFilter, যার মূল পার্থক্য হ'ল নতুন, ফিল্টার করা, সংগ্রহ ফিরিয়ে দেওয়ার পরিবর্তে, এটি অন-ডিমান্ড ফিল্টার করে। filterপদ্ধতি তার আচরণ সংগ্রহ কষাকষি উপর ভিত্তি করে সংজ্ঞায়িত হয়েছে। এটি আরও ভালভাবে বুঝতে, আসুন কয়েকটি List( স্কোর ) এবং Stream(অ-কঠোর) স্কেল ২.7 দেখুন :

scala> var found = false
found: Boolean = false

scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9

scala> found = false
found: Boolean = false

scala> Stream.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3

filterতাত্ক্ষণিক ঘটনা ঘটে কারণ সঙ্গে সঙ্গে প্রয়োগ করা হয় List, প্রতিকূলতার একটি তালিকা ফিরিয়ে দেওয়া foundহয় false। কেবল তখনই foreachমৃত্যুদন্ড কার্যকর করা হয় তবে এই সময়ের মধ্যে পরিবর্তনটি foundঅর্থহীন, যেমন filterইতিমধ্যে সম্পাদিত হয়েছে।

ক্ষেত্রে Stream, শর্তটি অবিলম্বে প্রয়োগ করা হয় না। পরিবর্তে, প্রতিটি উপাদান দ্বারা অনুরোধ করা হয় foreach, filterশর্তটি পরীক্ষা করে, যা এর foreachমাধ্যমে প্রভাবিত করতে সক্ষম করে found। কেবল এটি পরিষ্কার করার জন্য, এখানে সমঝোতা কোডের সমতুল্য:

for (x <- List.range(1, 10); if x % 2 == 1 && !found) 
  if (x == 5) found = true else println(x)

for (x <- Stream.range(1, 10); if x % 2 == 1 && !found) 
  if (x == 5) found = true else println(x)

এটি অনেকগুলি সমস্যা সৃষ্টি করেছিল, কারণ লোকেরা ifপূর্বেই পুরো সংগ্রহটিতে প্রয়োগ করার পরিবর্তে অন-চাহিদা বিবেচিত হবে বলে আশা করেছিল ।

সংগ্রহের কঠোরতা নির্বিশেষে স্কেলা ২.৮ চালু করা হয়েছে withFilter, যা সর্বদা অ-কঠোর। নীচের উদাহরণটি Listস্কেলা ২.৮ এ দুটি পদ্ধতিতে দেখায় :

scala> var found = false
found: Boolean = false

scala> List.range(1,10).filter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3
7
9

scala> found = false
found: Boolean = false

scala> List.range(1,10).withFilter(_ % 2 == 1 && !found).foreach(x => if (x == 5) found = true else println(x))
1
3

এটি বেশিরভাগ লোকেরা কীভাবে filterআচরণ করে তা পরিবর্তন না করে ফলাফল প্রত্যাশা করে। পার্শ্ব নোট হিসাবে, Rangeস্কেলা ২.7 এবং স্কেলা ২.৮ এর মধ্যে অ-কঠোর থেকে কঠোরতে পরিবর্তন করা হয়েছিল।


2
স্কেল ২.৮-এ ফিল্টার সহ একটি নতুন পদ্ধতি রয়েছে। (x <- c; যদি কনড) ফলন {...} কে স্কলা 2.8 তে সি.উইথফিল্টার (x => কনড)। ম্যাপ (x => {...}) তে অনুবাদ করা হবে।
ইস্টসুন

2
@ ইস্টসন যথেষ্ট সত্য, যদিও স্বয়ংক্রিয় ফলব্যাকও রয়েছে। withFilterএমনকি কঠোর সংগ্রহের জন্যও অ-কঠোর বলে মনে করা হয়, যা কিছু ব্যাখ্যা পাওয়ার যোগ্য। আমি এটি বিবেচনা করব ...
ড্যানিয়েল সি সোব্রাল

2
@ ড্যানিয়েল: ওডারস্কি, এট আল দ্বারা "প্রোগ্রামিং ইন স্কালায়" এই বিষয়টির একটি দুর্দান্ত চিকিত্সা রয়েছে। (আমি নিশ্চিত যে আপনি এটি ইতিমধ্যে জানেন)। এটি দেখানোর জন্য +1।
রাল্ফ

প্রথম 2 পয়েন্ট দিয়ে সঠিক: 1. for(x <- c; y <- x; z <-y) {...}অনুদিত হয় c.foreach(x => x.foreach(y => y.foreach(z => {...}))) 2. for(x <- c; y <- x; z <- y) yield {...}অনুদিত হয়c.flatMap(x => x.flatMap(y => y.map(z => {...})))
ডমিনিক

এটি কি for(x <- c; y = ...) yield {...}সত্যই অনুবাদ করা হয়েছে c.map(x => (x, ...)).map((x,y) => {...})? আমি মনে করি এটি অনুবাদ হয়েছে c.map(x => (x, ...)).map(x => { ...use x._1 and x._2 here...})বা আমি কিছু মিস করছি?
প্রস্টিনিক

23

হ্যাঁ, আর্উইকার যেমন বলেছেন, এটি লিনকিউ'র সমতুল্য selectএবং রুবির এবং পাইথনের সাথে খুব কম সম্পর্ক রয়েছে yield। মূলত, যেখানে সি # তে আপনি লিখতেন

from ... select ??? 

স্ক্যালায় আপনি পরিবর্তে আছে

for ... yield ???

এটি বুঝতেও গুরুত্বপূর্ণ যে- forমন্তব্যগুলি কেবল সিক্যুয়েন্সগুলির সাথেই কাজ করে না তবে লিনকিউয়ের মতো নির্দিষ্ট পদ্ধতিগুলির সংজ্ঞা দেয় এমন কোনও ধরণের সাথে:

  • যদি আপনার প্রকারটি কেবলমাত্র সংজ্ঞায়িত করে তবে এটি একক জেনারেটর নিয়ে গঠিত এক্সপ্রেশনগুলিকে mapঅনুমতি দেয় for
  • যদি এটি flatMapপাশাপাশি সংজ্ঞায়িত হয় তবে এটি বেশ কয়েকটি জেনারেটর নিয়ে গঠিত এক্সপ্রেশনগুলিকে mapঅনুমতি দেয় for
  • যদি এটি সংজ্ঞায়িত করা হয় তবে এটি ফলন ছাড়াই লুপগুলিকে foreachঅনুমতি দেয় for(একক এবং একাধিক জেনারেটর সহ উভয়)।
  • যদি সংজ্ঞায়িত filter, এটা পারবেন forএকটি দিয়ে শুরু -filter এক্সপ্রেশন if মধ্যে forঅভিব্যক্তি।

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

13

আপনি যদি স্কালার ব্যবহারকারীর কাছ থেকে আরও ভাল উত্তর না পান (যা আমি নই) তবে আমার বোঝার বিষয়টি এখানে।

এটি কেবলমাত্র একটি অভিব্যক্তির অংশ হিসাবে প্রদর্শিত হবে forযা বিদ্যমান তালিকা থেকে নতুন তালিকা তৈরি করতে পারে states

কিছুটা এইরকম:

var doubled = for (n <- original) yield n * 2

সুতরাং প্রতিটি ইনপুট জন্য একটি আউটপুট আইটেম আছে (যদিও আমি বিশ্বাস করি নকল ফেলে দেওয়ার একটি উপায় আছে)।

এটি অন্যান্য ভাষায় উত্পাদনের দ্বারা সক্ষম "অপরিহার্য ধারাবাহিকতা" থেকে একেবারেই আলাদা, যেখানে এটি প্রায় কোনও কাঠামোর সাথে কিছু বাধ্যতামূলক কোড থেকে যে কোনও দৈর্ঘ্যের একটি তালিকা তৈরি করার উপায় সরবরাহ করে।

(আপনি যদি সি # এর সাথে পরিচিত হন তবে এটি লিনকুই-র select অপারেটরের সাথে তার চেয়ে বেশি নিকটবর্তী yield return)।


1
এটি "বার দ্বিগুণ = = (এন <- আসল) উত্পাদ n * 2" হওয়া উচিত।
রাসেল ইয়াং 21

12

শব্দ yieldScala মধ্যে কেবল অন্বিত চিনি আছে যেটা দিয়ে সহজেই দ্বারা প্রতিস্থাপিত হতে পারে map, যেমন দানিয়েল শিক্ষক Sobral ইতিমধ্যে ব্যাখ্যা বিস্তারিতভাবে।

অন্যদিকে, yieldযদি আপনি পাইথনের মতো জেনারেটর (বা ধারাবাহিকতা) সন্ধান করেন তবে একেবারে বিভ্রান্তিকর । আরও তথ্যের জন্য এই এসও থ্রেডটি দেখুন: স্কালায় 'ফলন' বাস্তবায়নের পছন্দের উপায় কী?


11

নিম্নলিখিত উপলব্ধি বিবেচনা করুন

val A = for (i <- Int.MinValue to Int.MaxValue; if i > 3) yield i

এটি নিম্নে জোরে জোরে পড়তে সহায়ক হতে পারে

" জন্য প্রতিটি পূর্ণসংখ্যা i, যদি এটা তার চেয়ে অনেক বেশী 3, তারপর উত্পাদ (উত্পাদন) iএবং তালিকা থেকে এটি যোগ A।"

গাণিতিক সেট-বিল্ডার স্বরলিপি হিসাবে , উপরোক্ত বোধগম্য জন্য অনুরূপ

সেট স্বরলিপি

যা হিসাবে পড়া হতে পারে

" জন্য প্রতিটি পূর্ণসংখ্যা আমি, যদি এটা তার চেয়ে অনেক বেশী 3, তাহলে এটি একজন সদস্য সেটের একজন।"

অথবা বিকল্প হিসাবে

" একজনসমস্ত পূর্ণসংখ্যার সেট আমি, যেমন প্রতিটি এর আমিচেয়ে বড় 3" "


2

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

scala>for (i <- 1 to 5) yield i * 3

res: scala.collection.immutable.IndexedSeq [Int] = ভেক্টর (3, 6, 9, 12, 15)

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

scala> val letters = Seq('a', 'b', 'c')
letters: Seq[Char] = List(a, b, c)

scala> val res = for {
     |     n <- nums
     |     c <- letters
     | } yield (n, c)

পুনরায়: সিক [(অন্তঃ, চর)] = তালিকা ((1, ক), (1, খ), (1, গ)) (2, ক), (2, খ), (2, গ), ( 3, ক), (3, খ), (3, সি))

আশাকরি এটা সাহায্য করবে!!


এই পুরানো কোনও প্রশ্নের উত্তর দেওয়ার সময় (9 বছর পূর্বে) ইতিমধ্যে জমা দেওয়া অন্য সমস্ত উত্তরগুলির চেয়ে আপনার উত্তর কীভাবে আলাদা তা উল্লেখ করা সহায়ক।
jwvh

আমি ভেবেছিলাম সন্দেহের স্পষ্ট করা গুরুত্বপূর্ণ এবং ভিন্ন উত্তর না দেওয়া, এমনকি আমি এই শিক্ষাগ্রহণকারী একজন শিক্ষানবিসও। পরামর্শের জন্য ধন্যবাদ.
মনসা চদা

0
val aList = List( 1,2,3,4,5 )

val res3 = for ( al <- aList if al > 3 ) yield al + 1
val res4 = aList.filter(_ > 3).map(_ + 1)

println( res3 )
println( res4 )

এই দুটি টুকরো কোড সমান।

val res3 = for (al <- aList) yield al + 1 > 3
val res4 = aList.map( _+ 1 > 3 )

println( res3 ) 
println( res4 )

এই দুটি টুকরো কোডও সমান।

মানচিত্র ফলনের মতো নমনীয় এবং তদ্বিপরীত।


-3

ফলন মানচিত্রের চেয়ে আরও নমনীয় (), নীচের উদাহরণ দেখুন

val aList = List( 1,2,3,4,5 )

val res3 = for ( al <- aList if al > 3 ) yield al + 1 
val res4 = aList.map( _+ 1 > 3 ) 

println( res3 )
println( res4 )

ফলন যেমন ফলাফল মুদ্রণ করবে: তালিকা (5, 6), যা ভাল

যখন মানচিত্র () এর ফলাফল ফিরে আসবে যেমন: তালিকা (মিথ্যা, মিথ্যা, সত্য, সত্য, সত্য), যা সম্ভবত আপনি চান তা নয়।


4
সেই তুলনা ভুল। আপনি দুটি ভিন্ন জিনিস তুলনা করছেন। ফলন হিসাবে প্রকাশ কোনওভাবেই মানচিত্রে প্রকাশের মত একই কাজটি করে না। এছাড়াও, মানচিত্রের তুলনায় এটি ফলনের "নমনীয়তা" দেখায় না।
dotnetN00b
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.