*विधि:
यह डिफ़ॉल्ट प्रोजेक्शन लौटाता है - जो आप का वर्णन करता है:
'सभी कॉलम (या गणना किए गए मान) मुझे आमतौर पर दिलचस्पी है'।
आपकी तालिका में कई फ़ील्ड हो सकते हैं; आपको केवल अपने डिफ़ॉल्ट प्रक्षेपण के लिए सबसेट की आवश्यकता है। डिफ़ॉल्ट प्रक्षेपण को तालिका के प्रकार के मापदंडों से मेल खाना चाहिए।
आइए इसे एक बार में लें। <>सामान के बिना , बस *:
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)।
val result: List[(String, Int)] = q.list
इस मामले में, आपने उस प्रक्षेपण को परिभाषित किया है जिसे आप समझ के yieldखंड में चाहते हैं for।
अब के बारे में <>और Bar.unapply।
यह प्रदान करता है जिसे मैप्ड प्रोजेक्ट कहा जाता है ।
अब तक हमने देखा है कि स्केला आपको स्केला में प्रश्नों को व्यक्त करने की अनुमति देता है जो स्तंभों (या गणना मूल्यों) का एक प्रक्षेपण लौटाते हैं ; इसलिए इन प्रश्नों को निष्पादित करते समय आपको एक क्वेरी की परिणाम पंक्ति को स्कूप टपल के रूप में सोचना होगा । टपल का प्रकार उस प्रोजेक्शन से मेल खाएगा जिसे परिभाषित किया गया है ( forडिफ़ॉल्ट उदाहरण के अनुसार, पिछले उदाहरण में आपकी
समझ से *)। यही कारण है कि जहां
का प्रकार है और का प्रकार है, field1 ~ field2का एक प्रक्षेपण देता है ।Projection2[A, B]Afield1Bfield2
q.list.map {
case (name, n) =>
}
Queury(Bars).list.map {
case (id, name) =>
}
यदि हम बहुत अधिक कॉलम रखते हैं, तो हम tuples के साथ काम कर रहे हैं, जो बोझिल हो सकता है। हम परिणामों के बारे में नहीं सोचना चाहते हैं TupleNबल्कि नामित क्षेत्रों के साथ कुछ ऑब्जेक्ट के रूप में ।
(id ~ name)
case class Bar(id: Int, name: String) // For now, using a plain Int instead
(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)ए से जाने के लिए जरूरी जानकारी है 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))
स्लिक में, प्रश्नों monadic हैं - वे के साथ सिर्फ वस्तुओं रहे हैं 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। संग्रह के मामले में ये विधियां वास्तव में संग्रह को पुन: व्यवस्थित और फ़िल्टर करती हैं लेकिन स्लिक में इनका उपयोग SQL उत्पन्न करने के लिए किया जाता है। अधिक जानकारी यहाँ:
कैसे स्लैक स्लैक कोड को जेडडीबीसी में अनुवाद करता है?