*
পদ্ধতি:
এটি ডিফল্ট অভিক্ষেপটি ফিরিয়ে দেয় - যা আপনি বর্ণনা করেন:
'সমস্ত কলাম (বা গণিত মান) আমি সাধারণত আগ্রহী'।
আপনার টেবিলের বিভিন্ন ক্ষেত্র থাকতে পারে; আপনার কেবলমাত্র আপনার ডিফল্ট অভিক্ষেপের জন্য একটি উপসেট প্রয়োজন। ডিফল্ট অভিক্ষেপ অবশ্যই টেবিলের ধরণের পরামিতিগুলির সাথে মেলে।
একবারে এটি এক নেওয়া যাক। <>
স্টাফ ছাড়া , কেবল *
:
object Bars extends Table[(Int, String)]("bar") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = id ~ name
}
এর মতো কেবল একটি সারণী সংজ্ঞা আপনাকে এ জাতীয় প্রশ্ন তৈরি করতে দেয়:
implicit val session: Session =
val result = Query(Bars).list
এর
মতো সাধারণ প্রশ্নের জন্য ডিফল্ট অভিক্ষেপ (Int, String)
বাড়ে List[(Int, String)]
।
val q =
for (b <- Bars if b.id === 42)
yield (b.name ~ 1)
কি ধরণের q
? এটি Query
প্রক্ষেপণের সাথে একটি (String, Int)
। যখন প্রার্থনা, এটি একটি ফেরৎ List
এর (String, Int)
অভিক্ষেপ অনুযায়ী tuples।
val result: List[(String, Int)] = q.list
এই ক্ষেত্রে, আপনি অভিক্ষেপ আপনি চান সংজ্ঞায়িত করেছেন yield
ধারা for
ধী।
এখন সম্পর্কে <>
এবং Bar.unapply
।
এটি ম্যাপেড প্রজেকশনস যাকে বলে তাকে সরবরাহ করে ।
এখনও অবধি আমরা দেখেছি কীভাবে স্লিক আপনাকে স্কালায় ক্যোয়ারী প্রকাশ করতে সহায়তা করে যা কলামগুলির (বা গণিত মান) একটি অভিক্ষেপ দেয় ; যখন এই প্রশ্নের নির্বাহ সুতরাং আপনি ফলাফলের সারির চিন্তা করতে হবে একটি ক্যোয়ারী এর a Scala tuple যেমন । টিপলের ধরণটি সংজ্ঞায়িত প্রজেকশনটির সাথে মিলবে ( for
পূর্ববর্তী উদাহরণের মতো আপনার
বোধগম্যতার সাথে, ডিফল্ট *
অভিক্ষেপ দ্বারা)। এই field1 ~ field2
কারণটি Projection2[A, B]
কোথায়
এবং কী A
প্রকারের একটি প্রক্ষেপণ দেয় ।field1
B
field2
q.list.map {
case (name, n) =>
}
Queury(Bars).list.map {
case (id, name) =>
}
আমরা টিউপলগুলি নিয়ে কাজ করছি, আমাদের খুব বেশি কলাম থাকলে এটি জটিল হতে পারে। আমরা ফলাফলের মতো TupleN
নয় বরং নামযুক্ত ক্ষেত্রগুলির সাথে কিছু বিষয় হিসাবে ভাবতে চাই ।
(id ~ name)
case class Bar(id: Int, name: String)
(id ~ name <> (Bar, Bar.unapply _))
Query(Bars).list.map ( b.name )
কিভাবে কাজ করে? <>
একটি প্রক্ষেপণ নেয় Projection2[Int, String]
এবং প্রকারভেদে একটি ম্যাপযুক্ত প্রজেকশন দেয় Bar
। দুটি যুক্তি Bar, Bar.unapply _
স্লাইকে বলছে কীভাবে এই (Int, String)
প্রজেকশনটি কেস ক্লাসে ম্যাপ করা উচিত।
এটি দ্বিমুখী ম্যাপিং; Bar
কেস শ্রেণীর নির্মাতা, তাই এটি থেকে (id: Int, name: String)
a এ যাওয়ার জন্য প্রয়োজনীয় তথ্য Bar
। এবং unapply
যদি আপনি এটি অনুমান করে থাকেন তবে এটি বিপরীতে।
কোথা unapply
থেকে আসে? এটি কোনও সাধারণ কেস শ্রেণীর জন্য উপলব্ধ একটি স্ট্যান্ডার্ড পদ্ধতি - কেবল সংজ্ঞায়িত করা Bar
আপনাকে Bar.unapply
এমন একটি এক্সট্রাক্টর দেয় যা ফিরে পেতে ব্যবহার করা যেতে পারে id
এবং name
এটি দিয়ে
Bar
নির্মিত হয়েছিল:
val bar1 = Bar(1, "one")
val Bar(id, name) = bar1
val bars: List[Bar] =
val barNames = bars.map {
case Bar(_, name) => name
}
val x = Bar.unapply(bar1)
সুতরাং আপনার ডিফল্ট অভিক্ষেপ কেস ক্লাসে ম্যাপ করা যেতে পারে যা আপনি সবচেয়ে বেশি আশা করছেন:
object Bars extends Table[Bar]("bar") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = id ~ name <>(Bar, Bar.unapply _)
}
অথবা আপনার কাছে প্রতি-ক্যোয়ারী থাকতে পারে:
case class Baz(name: String, num: Int)
val q1 =
for (b <- Bars if b.id === 42)
yield (b.name ~ 1 <> (Baz, Baz.unapply _))
এখানে ধরণ q1
একটি হল Query
একটি সঙ্গে ম্যাপ করার অভিক্ষেপ Baz
। যখন প্রার্থনা, এটি একটি ফেরৎ List
এর Baz
বস্তু:
val result: List[Baz] = q1.list
পরিশেষে, একদিকে যেমন .?
অফার অপশন লিফটিং - মানগুলি না করার স্ক্যালাল উপায়।
(id ~ name)
(id.? ~ name)
মোড়ানো, যা আপনার মূল সংজ্ঞাটির সাথে সুন্দরভাবে কাজ করবে Bar
:
case class Bar(id: Option[Int] = None, name: String)
val q0 =
for (b <- Bars if b.id === 42)
yield (b.id.? ~ b.name <> (Bar, Bar.unapply _))
q0.list
স্লিক কীভাবে বোঝাপড়া ব্যবহার করে তার মন্তব্যের জবাবে for
:
একরকম, মনাদ সবসময় দেখাতে পরিচালনা করে এবং ব্যাখ্যাটির অংশ হওয়ার দাবি করে ...
বোধগম্যতা কেবল সংগ্রহের জন্য নির্দিষ্ট নয়। এগুলি যে কোনও ধরণের মোনাডে ব্যবহৃত হতে পারে এবং সংগ্রহগুলি স্কালায় পাওয়া বিভিন্ন ধরণের মোনাদ ধরণের মধ্যে একটি মাত্র।
তবে সংগ্রহগুলি পরিচিত হিসাবে, তারা ব্যাখ্যাটির জন্য একটি ভাল সূচনা পয়েন্ট তৈরি করে:
val ns = 1 to 100 toList;
val result =
for { i <- ns if i*i % 2 == 0 }
yield (i*i)
স্কালায়, বোঝার জন্য একটি পদ্ধতিটি (সম্ভবত নেস্টেড) পদ্ধতির কলগুলির জন্য সিনট্যাকটিক চিনি: উপরের কোডটি (কম বেশি) সমান:
ns.filter(i => i*i % 2 == 0).map(i => i*i)
মূলত, সাথে কাউকে filter
, map
, flatMap
পদ্ধতি (অন্য কথায়, একটি একসংখ্যা ) একটি ব্যবহার করা যেতে পারে
for
ধী স্থানে ns
। একটি ভাল উদাহরণ অপশন মোনাড । এখানে আগের উদাহরণটি যেখানে একই for
বিবৃতি List
পাশাপাশি উভয়
Option
মনদেজে কাজ করে:
val result =
for {
i <- ns
i2 <- Some(i*i)
if i2 % 2 == 0
} yield i2
def evenSqr(n: Int) = {
val sqr = n*n
if (sqr % 2 == 0) Some (sqr)
else None
}
result =
for {
i <- ns
i2 <- evenSqr(i)
} yield i2
শেষ উদাহরণে, রূপান্তরটি সম্ভবত এর মতো দেখাবে:
val result =
ns.flatMap(i => Some(i*i)).filter(i2 => i2 %2 ==0)
result =
ns.flatMap(i => evenSqr(i))
বাক্পটুতাপূর্ণ সালে প্রশ্নের পরমাণুসদৃশ্য - তারা কেবল বস্তু map
, flatMap
এবং filter
পদ্ধতি। সুতরাং for
বোধগম্যতা ( *
পদ্ধতির ব্যাখ্যাতে প্রদর্শিত ) কেবল অনুবাদ করে:
val q =
Query(Bars).filter(b => b.id === 42).map(b => b.name ~ 1)
val r: List[(String, Int)] = q.list
যেহেতু আপনি দেখতে পারেন, flatMap
, map
এবং filter
একটি জেনারেট করতে ব্যবহার করা হয় Query
বারংবার রূপান্তর দ্বারা Query(Bars)
প্রতিটি আবাহন সঙ্গে filter
এবং map
। সংগ্রহের ক্ষেত্রে এই পদ্ধতিগুলি আসলে সংগ্রহটি পুনরাবৃত্তি করে এবং ফিল্টার করে তবে স্লিক এ সেগুলি এসকিউএল উত্পন্ন করতে ব্যবহৃত হয়। এখানে আরও বিশদ:
স্কালা স্লিক কীভাবে জেডিবিসিতে স্কাল কোডটি অনুবাদ করে?