উত্তর:
এটি ক্রম বোঝার জন্য ব্যবহৃত হয় (পাইথনের তালিকা-বোঝার এবং জেনারেটরের মতো, যেখানে 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
আলাদা প্রভাব রয়েছে।
আমি মনে করি গ্রহণযোগ্য উত্তরটি দুর্দান্ত, তবে মনে হচ্ছে অনেক লোক কিছু মৌলিক বিষয়গুলি বুঝতে ব্যর্থ হয়েছে।
প্রথমত, স্কালার for
বোধগম্যতা হ্যাস্কেলের do
স্বীকৃতির সমতুল্য এবং এটি একাধিক monadic ক্রিয়াকলাপের রচনার জন্য সিনট্যাকটিক চিনির চেয়ে বেশি কিছু নয়। যেহেতু এই বিবৃতিটি সম্ভবত সহায়তার প্রয়োজন এমন কাউকে সাহায্য করবে না, আসুন আবার চেষ্টা করুন ... :-)
for
মানচিত্র সহ একাধিক ক্রিয়াকলাপের সংমিশ্রণের জন্য স্কালার উপলব্ধিগুলি সিনট্যাকটিক চিনি flatMap
এবং filter
। বা foreach
। স্কালা আসলে for
সেই পদ্ধতিগুলিতে কলগুলিতে একটি এক্সপ্রেশনকে অনুবাদ করে, সুতরাং যে কোনও শ্রেণি তাদের সরবরাহ করে, বা সেগুলির একটি উপসর্গ বোঝার জন্য ব্যবহার করা যেতে পারে।
প্রথমে অনুবাদগুলি সম্পর্কে কথা বলি। খুব সহজ নিয়ম আছে:
এই
for(x <- c1; y <- c2; z <-c3) {...}
অনুবাদ করা হয়
c1.foreach(x => c2.foreach(y => c3.foreach(z => {...})))
এই
for(x <- c1; y <- c2; z <- c3) yield {...}
অনুবাদ করা হয়
c1.flatMap(x => c2.flatMap(y => c3.map(z => {...})))
এই
for(x <- c; if cond) yield {...}
স্কেলা ২. 2. এ অনুবাদ করা হয়েছে
c.filter(x => cond).map(x => {...})
বা, স্কেলা ২.৮-তে, প্রবেশ করুন
c.withFilter(x => cond).map(x => {...})
পদ্ধতি withFilter
যদি না পাওয়া যায় তবে তা প্রাক্তনটিতে ফ্যালব্যাক সহ filter
। এই সম্পর্কে আরও তথ্যের জন্য দয়া করে নীচের বিভাগটি দেখুন।
এই
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 এবং স্কেলা ২.৮ এর মধ্যে অ-কঠোর থেকে কঠোরতে পরিবর্তন করা হয়েছিল।
withFilter
এমনকি কঠোর সংগ্রহের জন্যও অ-কঠোর বলে মনে করা হয়, যা কিছু ব্যাখ্যা পাওয়ার যোগ্য। আমি এটি বিবেচনা করব ...
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...})
বা আমি কিছু মিস করছি?
হ্যাঁ, আর্উইকার যেমন বলেছেন, এটি লিনকিউ'র সমতুল্য select
এবং রুবির এবং পাইথনের সাথে খুব কম সম্পর্ক রয়েছে yield
। মূলত, যেখানে সি # তে আপনি লিখতেন
from ... select ???
স্ক্যালায় আপনি পরিবর্তে আছে
for ... yield ???
এটি বুঝতেও গুরুত্বপূর্ণ যে- for
মন্তব্যগুলি কেবল সিক্যুয়েন্সগুলির সাথেই কাজ করে না তবে লিনকিউয়ের মতো নির্দিষ্ট পদ্ধতিগুলির সংজ্ঞা দেয় এমন কোনও ধরণের সাথে:
map
অনুমতি দেয় for
।flatMap
পাশাপাশি সংজ্ঞায়িত হয় তবে এটি বেশ কয়েকটি জেনারেটর নিয়ে গঠিত এক্সপ্রেশনগুলিকে map
অনুমতি দেয় for
।foreach
অনুমতি দেয় for
(একক এবং একাধিক জেনারেটর সহ উভয়)।filter
, এটা পারবেন for
একটি দিয়ে শুরু -filter এক্সপ্রেশন if
মধ্যে for
অভিব্যক্তি।আপনি যদি স্কালার ব্যবহারকারীর কাছ থেকে আরও ভাল উত্তর না পান (যা আমি নই) তবে আমার বোঝার বিষয়টি এখানে।
এটি কেবলমাত্র একটি অভিব্যক্তির অংশ হিসাবে প্রদর্শিত হবে for
যা বিদ্যমান তালিকা থেকে নতুন তালিকা তৈরি করতে পারে states
কিছুটা এইরকম:
var doubled = for (n <- original) yield n * 2
সুতরাং প্রতিটি ইনপুট জন্য একটি আউটপুট আইটেম আছে (যদিও আমি বিশ্বাস করি নকল ফেলে দেওয়ার একটি উপায় আছে)।
এটি অন্যান্য ভাষায় উত্পাদনের দ্বারা সক্ষম "অপরিহার্য ধারাবাহিকতা" থেকে একেবারেই আলাদা, যেখানে এটি প্রায় কোনও কাঠামোর সাথে কিছু বাধ্যতামূলক কোড থেকে যে কোনও দৈর্ঘ্যের একটি তালিকা তৈরি করার উপায় সরবরাহ করে।
(আপনি যদি সি # এর সাথে পরিচিত হন তবে এটি লিনকুই-র select
অপারেটরের সাথে তার চেয়ে বেশি নিকটবর্তী yield return
)।
শব্দ yield
Scala মধ্যে কেবল অন্বিত চিনি আছে যেটা দিয়ে সহজেই দ্বারা প্রতিস্থাপিত হতে পারে map
, যেমন দানিয়েল শিক্ষক Sobral ইতিমধ্যে ব্যাখ্যা বিস্তারিতভাবে।
অন্যদিকে, yield
যদি আপনি পাইথনের মতো জেনারেটর (বা ধারাবাহিকতা) সন্ধান করেন তবে একেবারে বিভ্রান্তিকর । আরও তথ্যের জন্য এই এসও থ্রেডটি দেখুন: স্কালায় 'ফলন' বাস্তবায়নের পছন্দের উপায় কী?
নিম্নলিখিত উপলব্ধি বিবেচনা করুন
val A = for (i <- Int.MinValue to Int.MaxValue; if i > 3) yield i
এটি নিম্নে জোরে জোরে পড়তে সহায়ক হতে পারে
" জন্য প্রতিটি পূর্ণসংখ্যা i
, যদি এটা তার চেয়ে অনেক বেশী 3
, তারপর উত্পাদ (উত্পাদন) i
এবং তালিকা থেকে এটি যোগ A
।"
গাণিতিক সেট-বিল্ডার স্বরলিপি হিসাবে , উপরোক্ত বোধগম্য জন্য অনুরূপ
যা হিসাবে পড়া হতে পারে
" জন্য প্রতিটি পূর্ণসংখ্যা , যদি এটা তার চেয়ে অনেক বেশী , তাহলে এটি একজন সদস্য সেটের ।"
অথবা বিকল্প হিসাবে
" সমস্ত পূর্ণসংখ্যার সেট , যেমন প্রতিটি এর চেয়ে বড় " "
ফলন লুপের অনুরূপ যার একটি বাফার রয়েছে যা আমরা দেখতে পাই না এবং প্রতিটি বর্ধনের জন্য এটি বাফারে পরবর্তী আইটেম যুক্ত করে রাখে। লুপটি চলমান শেষ হয়ে গেলে, এটি সমস্ত উত্পন্ন মানের মান সংগ্রহ করে। ফলন সরল পাটিগণিত অপারেটর হিসাবে বা অ্যারের সাথে একত্রে ব্যবহৃত হতে পারে। আপনার আরও ভাল বোঝার জন্য এখানে দুটি সহজ উদাহরণ
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, সি))
আশাকরি এটা সাহায্য করবে!!
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 )
এই দুটি টুকরো কোডও সমান।
মানচিত্র ফলনের মতো নমনীয় এবং তদ্বিপরীত।
ফলন মানচিত্রের চেয়ে আরও নমনীয় (), নীচের উদাহরণ দেখুন
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), যা ভাল
যখন মানচিত্র () এর ফলাফল ফিরে আসবে যেমন: তালিকা (মিথ্যা, মিথ্যা, সত্য, সত্য, সত্য), যা সম্ভবত আপনি চান তা নয়।