स्काला की ऐसी कौन सी छुपी हुई विशेषताएँ हैं जिनके बारे में प्रत्येक स्काला डेवलपर को पता होना चाहिए?
कृपया प्रति उत्तर एक छिपी हुई सुविधा।
स्काला की ऐसी कौन सी छुपी हुई विशेषताएँ हैं जिनके बारे में प्रत्येक स्काला डेवलपर को पता होना चाहिए?
कृपया प्रति उत्तर एक छिपी हुई सुविधा।
जवाबों:
ठीक है, मुझे एक और जोड़ना था। Regex
स्काला की प्रत्येक वस्तु में एक एक्सट्रैक्टर होता है (ऊपर दिए गए ऑक्सबॉक्स_लक्स से उत्तर देखें) जो आपको मैच समूहों तक पहुंच प्रदान करता है। तो आप कुछ ऐसा कर सकते हैं:
// Regex to split a date in the format Y/M/D.
val regex = "(\\d+)/(\\d+)/(\\d+)".r
val regex(year, month, day) = "2010/1/13"
यदि आप पैटर्न मिलान और एक्सट्रैक्टर्स का उपयोग करने के लिए उपयोग नहीं किए जाते हैं तो दूसरी पंक्ति भ्रामक दिखती है। जब भी आप एक परिभाषित करते हैं val
या var
, कीवर्ड के बाद जो आता है वह केवल एक पहचानकर्ता नहीं है, बल्कि एक पैटर्न है। इसलिए यह काम करता है:
val (a, b, c) = (1, 3.14159, "Hello, world")
दाहिने हाथ की अभिव्यक्ति Tuple3[Int, Double, String]
पैटर्न का मिलान कर सकती है (a, b, c)
।
अधिकांश समय आपके पैटर्न एक्सट्रैक्टर्स का उपयोग करते हैं जो सिंगलटन ऑब्जेक्ट्स के सदस्य होते हैं। उदाहरण के लिए, यदि आप एक पैटर्न लिखते हैं
Some(value)
तो आप संक्षेप में चिमटा बुला रहे हैं Some.unapply
।
लेकिन आप पैटर्न में वर्ग उदाहरणों का भी उपयोग कर सकते हैं, और यहां वही हो रहा है। वैल रेगेक्स का एक उदाहरण है Regex
, और जब आप इसे एक पैटर्न में उपयोग करते हैं, तो आप संक्षेप में कॉल कर रहे हैं regex.unapplySeq
( unapply
बनाम unapplySeq
इस उत्तर के दायरे से परे), जो मैच समूहों को एक में निकालता है, जिनमें Seq[String]
से तत्वों को क्रम में सौंपा गया है। चर वर्ष, माह और दिन।
संरचनात्मक प्रकार की परिभाषाएँ - अर्थात एक प्रकार जो यह वर्णित करता है कि यह किन विधियों का समर्थन करता है। उदाहरण के लिए:
object Closer {
def using(closeable: { def close(): Unit }, f: => Unit) {
try {
f
} finally { closeable.close }
}
}
ध्यान दें कि पैरामीटर का प्रकारcloseable
एक close
विधि के अलावा अन्य परिभाषित नहीं है
इस सुविधा के बिना, आप उदाहरण के लिए, किसी सूची पर एक फ़ंक्शन को मैप करने का विचार किसी अन्य सूची को वापस करने के लिए, या किसी अन्य पेड़ को वापस करने के लिए एक पेड़ पर एक फ़ंक्शन को मैप करने के विचार को व्यक्त कर सकते हैं। लेकिन आप इस विचार को आम तौर पर उच्च प्रकारों के बिना व्यक्त नहीं कर सकते ।
उच्च प्रकार के साथ, आप किसी भी प्रकार के विचार को कैप्चर कर सकते हैं जो दूसरे प्रकार के साथ पैरामीटर किया गया है। एक प्रकार का कंस्ट्रक्टर जो एक पैरामीटर लेता है, उसे प्रकार का कहा जाता है (*->*)
। उदाहरण के लिए, List
। एक प्रकार का कंस्ट्रक्टर जो किसी अन्य प्रकार के कन्स्ट्रक्टर को लौटाता है, उसे दयालु कहा जाता है (*->*->*)
। उदाहरण के लिए, Function1
। लेकिन स्काला में, हमारे पास उच्च प्रकार हैं, इसलिए हमारे पास ऐसे प्रकार के निर्माता हो सकते हैं जो अन्य प्रकार के निर्माणकर्ताओं के साथ पैरामीटर किए जाते हैं। तो वे प्रकार के हैं ((*->*)->*)
।
उदाहरण के लिए:
trait Functor[F[_]] {
def fmap[A, B](f: A => B, fa: F[A]): F[B]
}
अब, यदि आपके पास एक है Functor[List]
, तो आप सूचियों पर मैप कर सकते हैं। यदि आपके पास एक है Functor[Tree]
, तो आप पेड़ों पर मैप कर सकते हैं। लेकिन इससे भी महत्वपूर्ण बात, अगर आपके पास Functor[A]
किसी भी प्रकार का कोई भी है(*->*)
, तो आप एक फ़ंक्शन को मैप कर सकते हैं A
।
एक्सट्रैक्टर्स जो आपको गंदे if-elseif-else
स्टाइल कोड को पैटर्न के साथ बदलने की अनुमति देते हैं । मुझे पता है कि ये बिल्कुल छिपी नहीं हैं, लेकिन मैं स्कैला का उपयोग कुछ महीनों से कर रहा हूं, वास्तव में उनकी शक्ति को समझे बिना। (लंबे) उदाहरण के लिए मैं प्रतिस्थापित कर सकता हूं:
val code: String = ...
val ps: ProductService = ...
var p: Product = null
if (code.endsWith("=")) {
p = ps.findCash(code.substring(0, 3)) //e.g. USD=, GBP= etc
}
else if (code.endsWith(".FWD")) {
//e.g. GBP20090625.FWD
p = ps.findForward(code.substring(0,3), code.substring(3, 9))
}
else {
p = ps.lookupProductByRic(code)
}
इसके साथ, जो मेरी राय में बहुत स्पष्ट है
implicit val ps: ProductService = ...
val p = code match {
case SyntheticCodes.Cash(c) => c
case SyntheticCodes.Forward(f) => f
case _ => ps.lookupProductByRic(code)
}
मुझे पृष्ठभूमि में थोड़ा सा काम करना होगा ...
object SyntheticCodes {
// Synthetic Code for a CashProduct
object Cash extends (CashProduct => String) {
def apply(p: CashProduct) = p.currency.name + "="
//EXTRACTOR
def unapply(s: String)(implicit ps: ProductService): Option[CashProduct] = {
if (s.endsWith("=")
Some(ps.findCash(s.substring(0,3)))
else None
}
}
//Synthetic Code for a ForwardProduct
object Forward extends (ForwardProduct => String) {
def apply(p: ForwardProduct) = p.currency.name + p.date.toString + ".FWD"
//EXTRACTOR
def unapply(s: String)(implicit ps: ProductService): Option[ForwardProduct] = {
if (s.endsWith(".FWD")
Some(ps.findForward(s.substring(0,3), s.substring(3, 9))
else None
}
}
लेकिन किंवदंती इस तथ्य के लिए इसके लायक है कि यह व्यापार तर्क के एक टुकड़े को एक समझदार जगह में अलग करती है। मैं अपने Product.getCode
तरीकों को इस प्रकार लागू कर सकता हूं ।
class CashProduct {
def getCode = SyntheticCodes.Cash(this)
}
class ForwardProduct {
def getCode = SyntheticCodes.Forward(this)
}
मैनिफेस्ट जो कि रनटाइम पर टाइप जानकारी प्राप्त करने का एक प्रकार है, जैसे कि स्काला ने प्रकारों को संशोधित किया था।
स्कैला 2.8 में आप पैकेज scala.util.control.TailCalls (वास्तव में यह trampolining है) का उपयोग करके पूंछ-पुनरावर्ती तरीके हो सकते हैं।
एक उदाहरण:
def u(n:Int):TailRec[Int] = {
if (n==0) done(1)
else tailcall(v(n/2))
}
def v(n:Int):TailRec[Int] = {
if (n==0) done(5)
else tailcall(u(n-1))
}
val l=for(n<-0 to 5) yield (n,u(n).result,v(n).result)
println(l)
मामले की कक्षाएं स्वचालित रूप से उत्पाद विशेषता को मिलाती हैं, बिना किसी प्रतिबिंब के बिना खेतों में अनुक्रमित पहुंच प्रदान करती हैं:
case class Person(name: String, age: Int)
val p = Person("Aaron", 28)
val name = p.productElement(0) // name = "Aaron": Any
val age = p.productElement(1) // age = 28: Any
val fields = p.productIterator.toList // fields = List[Any]("Aaron", 28)
यह सुविधा toString
विधि के आउटपुट को बदलने के लिए एक सरल तरीका भी प्रदान करती है :
case class Person(name: String, age: Int) {
override def productPrefix = "person: "
}
// prints "person: (Aaron,28)" instead of "Person(Aaron, 28)"
println(Person("Aaron", 28))
यह बिल्कुल छिपा नहीं है, लेकिन निश्चित रूप से एक विज्ञापित विशेषता के तहत है: स्केलैक -एक्सप्रिंट ।
उपयोग के दृष्टांत के रूप में निम्नलिखित स्रोत पर विचार करें:
class A { "xx".r }
इसे स्केल-एक्सप्रिंट के साथ संकलित करना: टाइपर आउटपुट:
package <empty> {
class A extends java.lang.Object with ScalaObject {
def this(): A = {
A.super.this();
()
};
scala.this.Predef.augmentString("xx").r
}
}
ध्यान दें scala.this.Predef.augmentString("xx").r
, जो कि implicit def augmentString
पूर्वनिर्धारित का एक आवेदन है ।
scalac -Xprint: <चरण> कुछ संकलक चरण के बाद सिंटैक्स ट्री प्रिंट करेगा। उपलब्ध चरणों को देखने के लिए स्केल -Xshow- चरणों का उपयोग करें ।
यह सीखने का एक शानदार तरीका है कि पर्दे के पीछे क्या चल रहा है।
के साथ प्रयास करें
case class X(a:Int,b:String)
टाइपर चरण का उपयोग वास्तव में यह महसूस करने के लिए कि यह कितना उपयोगी है।
आप अपनी खुद की नियंत्रण संरचनाओं को परिभाषित कर सकते हैं। यह वास्तव में सिर्फ फ़ंक्शंस और ऑब्जेक्ट्स और कुछ सिंटैक्टिक चीनी है, लेकिन वे वास्तविक चीज़ की तरह दिखते हैं और व्यवहार करते हैं।
उदाहरण के लिए, निम्नलिखित कोड परिभाषित करता है dont {...} unless (cond)
और dont {...} until (cond)
:
def dont(code: => Unit) = new DontCommand(code)
class DontCommand(code: => Unit) {
def unless(condition: => Boolean) =
if (condition) code
def until(condition: => Boolean) = {
while (!condition) {}
code
}
}
अब आप निम्नलिखित कर सकते हैं:
/* This will only get executed if the condition is true */
dont {
println("Yep, 2 really is greater than 1.")
} unless (2 > 1)
/* Just a helper function */
var number = 0;
def nextNumber() = {
number += 1
println(number)
number
}
/* This will not be printed until the condition is met. */
dont {
println("Done counting to 5!")
} until (nextNumber() == 5)
zif[A : Zero](cond: => Boolean)(t: => A): A = if(cond) t else mzero
। स्कलाज़ की आवश्यकता है।
@switch
स्काला 2.8 में एनोटेशन:
एक मिलान अभिव्यक्ति पर लागू होने वाला एनोटेशन। यदि मौजूद है, तो संकलक यह सत्यापित करेगा कि मैच टेबलवॉच या लुकअप में संकलित किया गया है, और अगर यह सशर्त अभिव्यक्तियों की एक श्रृंखला में संकलित करता है, तो एक त्रुटि जारी करता है।
उदाहरण:
scala> val n = 3
n: Int = 3
scala> import annotation.switch
import annotation.switch
scala> val s = (n: @switch) match {
| case 3 => "Three"
| case _ => "NoThree"
| }
<console>:6: error: could not emit switch for @switch annotated match
val s = (n: @switch) match {
डनो अगर यह वास्तव में छिपा हुआ है, लेकिन मुझे यह काफी अच्छा लगता है।
टाइपकोस्ट्रक्टर्स जो 2 प्रकार के पैरामीटर लेते हैं, उन्हें इन्फिक्स नोटेशन में लिखा जा सकता है
object Main {
class FooBar[A, B]
def main(args: Array[String]): Unit = {
var x: FooBar[Int, BigInt] = null
var y: Int FooBar BigInt = null
}
}
var foo2barConverter: Foo ConvertTo Bar
, प्रकार के मापदंडों का क्रम स्वयं स्पष्ट होगा।
स्काला 2.8 ने डिफ़ॉल्ट और नामित तर्कों को पेश किया, जिसने केसला कक्षाओं में एक नई "कॉपी" विधि को जोड़ना संभव बनाया। यदि आप इसे परिभाषित करते हैं:
case class Foo(a: Int, b: Int, c: Int, ... z:Int)
और आप एक नया फू बनाना चाहते हैं जो मौजूदा फू की तरह है, केवल एक अलग "एन" मूल्य के साथ, तो आप बस कह सकते हैं:
foo.copy(n = 3)
scala 2.8 में आप अपने सामान्य वर्ग / विधियों में @ विशिष्टीकृत कर सकते हैं। यह आदिम प्रकार (AnyVal का विस्तार) के लिए वर्ग के विशेष संस्करण बनाएगा और गैर-आवश्यक बॉक्सिंग / बॉक्सिंग की लागत को बचाएगा:
class Foo[@specialized T]...
आप AnyVals के सबसेट का चयन कर सकते हैं:
class Foo[@specialized(Int,Boolean) T]...
भाषा का विस्तार। मैं हमेशा से जावा (नहीं) में ऐसा कुछ करना चाहता था। लेकिन स्काला में मेरे पास हो सकता है:
def timed[T](thunk: => T) = {
val t1 = System.nanoTime
val ret = thunk
val time = System.nanoTime - t1
println("Executed in: " + time/1000000.0 + " millisec")
ret
}
और फिर लिखें:
val numbers = List(12, 42, 3, 11, 6, 3, 77, 44)
val sorted = timed { // "timed" is a new "keyword"!
numbers.sortWith(_<_)
}
println(sorted)
और पाओ
Executed in: 6.410311 millisec
List(3, 3, 6, 11, 12, 42, 44, 77)
आप एक कॉल-बाय-नाम पैरामीटर (EDITED: यह एक फ़ंक्शन के लिए एक आलसी पैरामीटर है!) अलग है और फ़ंक्शन द्वारा उपयोग किए जाने तक इसका मूल्यांकन नहीं किया जाएगा (EDIT: वास्तव में, यह हर बार इसे फिर से मूल्यांकन किया जाएगा। उपयोग किया गया)। विवरण के लिए यह देखें
class Bar(i:Int) {
println("constructing bar " + i)
override def toString():String = {
"bar with value: " + i
}
}
// NOTE the => in the method declaration. It indicates a lazy paramter
def foo(x: => Bar) = {
println("foo called")
println("bar: " + x)
}
foo(new Bar(22))
/*
prints the following:
foo called
constructing bar 22
bar with value: 22
*/
lazy val xx: Bar = x
अपनी पद्धति में कुछ ऐसा करते हैं और उस क्षण से केवल आप ही उपयोग करते हैं xx
।
आप locally
सेमीकोलन इंजेक्शन मुद्दों के कारण के बिना एक स्थानीय ब्लॉक शुरू करने के लिए उपयोग कर सकते हैं।
उपयोग:
scala> case class Dog(name: String) {
| def bark() {
| println("Bow Vow")
| }
| }
defined class Dog
scala> val d = Dog("Barnie")
d: Dog = Dog(Barnie)
scala> locally {
| import d._
| bark()
| bark()
| }
Bow Vow
Bow Vow
locally
इस रूप में परिभाषित किया गया है:
@inline def locally[T](x: T): T = x
इनलाइन होने के कारण, यह कोई अतिरिक्त ओवरहेड नहीं लगाता है।
trait AbstractT2 {
println("In AbstractT2:")
val value: Int
val inverse = 1.0/value
println("AbstractT2: value = "+value+", inverse = "+inverse)
}
val c2c = new {
// Only initializations are allowed in pre-init. blocks.
// println("In c2c:")
val value = 10
} with AbstractT2
println("c2c.value = "+c2c.value+", inverse = "+c2c.inverse)
आउटपुट:
In AbstractT2:
AbstractT2: value = 10, inverse = 0.1
c2c.value = 10, inverse = 0.1
हम खंड
value
से पहले ब्लॉक में क्षेत्र को इनिशियलाइज़ करते हुए एक अनाम आंतरिक वर्ग को इंस्टेंट करते हैंwith AbstractT2
। यह गारंटी देता है किvalue
निकायAbstractT2
निष्पादित होने से पहले आरंभीकृत किया गया है, जैसा कि आप स्क्रिप्ट चलाते समय दिखाया गया है।
आप 'के साथ' कीवर्ड के साथ संरचनात्मक प्रकारों की रचना कर सकते हैं
object Main {
type A = {def foo: Unit}
type B = {def bar: Unit}
type C = A with B
class myA {
def foo: Unit = println("myA.foo")
}
class myB {
def bar: Unit = println("myB.bar")
}
class myC extends myB {
def foo: Unit = println("myC.foo")
}
def main(args: Array[String]): Unit = {
val a: A = new myA
a.foo
val b: C = new myC
b.bar
b.foo
}
}
अनाम कार्यों के लिए प्लेसहोल्डर सिंटैक्स
स्काला भाषा विशिष्टता से:
SimpleExpr1 ::= '_'
एक अभिव्यक्ति (वाक्य श्रेणी में
Expr
) उन_
स्थानों पर एम्बेडेड अंडरस्कोर प्रतीकों को शामिल कर सकती है जहां पहचानकर्ता कानूनी हैं। इस तरह की अभिव्यक्ति एक अनाम फ़ंक्शन का प्रतिनिधित्व करती है जहां बाद में अंडरस्कोर की घटनाएं क्रमिक मापदंडों को दर्शाती हैं।
से स्काला भाषा परिवर्तन :
_ + 1 x => x + 1
_ * _ (x1, x2) => x1 * x2
(_: Int) * 2 (x: Int) => x * 2
if (_) x else y z => if (z) x else y
_.map(f) x => x.map(f)
_.map(_ + 1) x => x.map(y => y + 1)
इसके प्रयोग से आप कुछ ऐसा कर सकते हैं:
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
विशिष्ट परिभाषाएँ, विशेष रूप से रूपांतरण।
उदाहरण के लिए, एक फ़ंक्शन मानें जो एक इनपुट स्ट्रिंग को एक आकार में फिट करने के लिए प्रारूपित करेगा, इसके बीच के स्थान को "..." के साथ बदलकर
def sizeBoundedString(s: String, n: Int): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
आप किसी भी स्ट्रिंग के साथ उपयोग कर सकते हैं, और, ज़ाहिर है, कुछ भी परिवर्तित करने के लिए स्ट्रीटिंग विधि का उपयोग करें। लेकिन आप इसे इस तरह भी लिख सकते हैं:
def sizeBoundedString[T](s: T, n: Int)(implicit toStr: T => String): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
और फिर, आप ऐसा करके अन्य प्रकार की कक्षाएं पास कर सकते हैं:
implicit def double2String(d: Double) = d.toString
अब आप उस फ़ंक्शन को डबल पास कर सकते हैं:
sizeBoundedString(12345.12345D, 8)
अंतिम तर्क निहित है, और निहित डे घोषणा के कारण स्वचालित रूप से पारित किया जा रहा है। इसके अलावा, "एस" का आकार के अंदर स्ट्रिंग की तरह व्यवहार किया जा रहा हैबाउंडेडस्ट्रिंग क्योंकि इसमें स्ट्रिंग से एक अंतर्निहित रूपांतरण है।
अप्रत्याशित रूपांतरणों से बचने के लिए असामान्य प्रकारों के लिए इस प्रकार के इम्प्लाइक बेहतर परिभाषित हैं। आप एक रूपांतरण को भी आसानी से पास कर सकते हैं, और यह अभी भी आकार के अंदर उपयोग किया जाएगा।
sizeBoundedString(1234567890L, 8)((l : Long) => l.toString)
आपके पास कई निहित तर्क भी हो सकते हैं, लेकिन फिर आपको या तो उन सभी को पारित करना होगा, या उनमें से किसी को भी पारित नहीं करना होगा। निहित रूपांतरण के लिए एक शॉर्टकट सिंटैक्स भी है:
def sizeBoundedString[T <% String](s: T, n: Int): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
यह बिल्कुल उसी तरह उपयोग किया जाता है।
Implicits का कोई भी मूल्य हो सकता है। उदाहरण के लिए, लाइब्रेरी जानकारी को छिपाने के लिए उनका उपयोग किया जा सकता है। उदाहरण के लिए, निम्नलिखित उदाहरण लें:
case class Daemon(name: String) {
def log(msg: String) = println(name+": "+msg)
}
object DefaultDaemon extends Daemon("Default")
trait Logger {
private var logd: Option[Daemon] = None
implicit def daemon: Daemon = logd getOrElse DefaultDaemon
def logTo(daemon: Daemon) =
if (logd == None) logd = Some(daemon)
else throw new IllegalArgumentException
def log(msg: String)(implicit daemon: Daemon) = daemon.log(msg)
}
class X extends Logger {
logTo(Daemon("X Daemon"))
def f = {
log("f called")
println("Stuff")
}
def g = {
log("g called")(DefaultDaemon)
}
}
class Y extends Logger {
def f = {
log("f called")
println("Stuff")
}
}
इस उदाहरण में, वाई ऑब्जेक्ट में "एफ" कॉल करने पर लॉग को डिफ़ॉल्ट डेमॉन में भेज दिया जाएगा, और एक्स के डेमन एक्स डेमन को इंस्टेंस पर। लेकिन एक्स के एक उदाहरण पर जी कॉल करने से लॉग को स्पष्ट रूप से दिए गए डिफाल्डमन में भेज दिया जाएगा।
हालांकि इस सरल उदाहरण को अधिभार और निजी राज्य के साथ फिर से लिखा जा सकता है, लेकिन इंपीटिस को निजी राज्य की आवश्यकता नहीं है, और आयात के संदर्भ में लाया जा सकता है।
शायद बहुत छिपा हुआ नहीं है, लेकिन मुझे लगता है कि यह उपयोगी है:
@scala.reflect.BeanProperty
var firstName:String = _
यह स्वचालित रूप से बीन सम्मेलन से मेल खाने वाले क्षेत्र के लिए एक गेट्टर और सेटर उत्पन्न करेगा।
पर इसके अलावा वर्णन डेवलपर
बंद में तर्क वितर्क।
एक फ़ंक्शन तर्क को केवल विधियों के साथ अंतर्निहित के रूप में चिह्नित किया जा सकता है। फ़ंक्शन के मुख्य भाग के दायरे में निहित पैरामीटर दिखाई देता है और निहित संकल्प के लिए योग्य है:
trait Foo { def bar }
trait Base {
def callBar(implicit foo: Foo) = foo.bar
}
object Test extends Base {
val f: Foo => Unit = { implicit foo =>
callBar
}
def test = f(new Foo {
def bar = println("Hello")
})
}
स्काला के साथ अनंत डेटा संरचनाएँ बनाएँ Stream
:
http://www.codecommit.com/blog/scala/infinite-lists-for-the-finitely-patient
परिणाम प्रकार निहित संकल्प पर निर्भर हैं। यह आपको कई प्रेषण का रूप दे सकता है:
scala> trait PerformFunc[A,B] { def perform(a : A) : B }
defined trait PerformFunc
scala> implicit val stringToInt = new PerformFunc[String,Int] {
def perform(a : String) = 5
}
stringToInt: java.lang.Object with PerformFunc[String,Int] = $anon$1@13ccf137
scala> implicit val intToDouble = new PerformFunc[Int,Double] {
def perform(a : Int) = 1.0
}
intToDouble: java.lang.Object with PerformFunc[Int,Double] = $anon$1@74e551a4
scala> def foo[A, B](x : A)(implicit z : PerformFunc[A,B]) : B = z.perform(x)
foo: [A,B](x: A)(implicit z: PerformFunc[A,B])B
scala> foo("HAI")
res16: Int = 5
scala> foo(1)
res17: Double = 1.0
foo
उपयोग की परिभाषा a
जो इन आदेशों के निष्पादन से पहले पर्यावरण में मौजूद रही होगी। मुझे लगता है तुम मतलब है z.perform(x)
।
स्काला आपको उस वर्ग के उदाहरण को आरंभीकृत करने के लिए बयानों वाले वर्ग (कंस्ट्रक्टर) के साथ एक अनाम उपवर्ग बनाने की अनुमति देता है।
घटक-आधारित उपयोगकर्ता इंटरफ़ेस (उदाहरण के लिए स्विंग, वाडिन) का निर्माण करते समय यह पैटर्न बहुत उपयोगी है क्योंकि यह यूआई घटकों को बनाने और उनके गुणों को अधिक स्पष्ट रूप से घोषित करने की अनुमति देता है।
अधिक जानकारी के लिए http://spot.colorado.edu/~reids/papers/how-scala-experience-improved-our-java-development-reid-2011.pdf देखें ।
यहां वाडिन बटन बनाने का एक उदाहरण दिया गया है:
val button = new Button("Click me"){
setWidth("20px")
setDescription("Click on this")
setIcon(new ThemeResource("icons/ok.png"))
}
import
बयानों से सदस्यों को छोड़करमान लें कि आप एक का उपयोग करना चाहते हैं Logger
जिसमें एक विधि println
और एक printerr
विधि है, लेकिन आप केवल त्रुटि संदेशों के लिए उपयोग करना चाहते हैं, और Predef.println
मानक आउटपुट के लिए अच्छे पुराने को बनाए रखें । आप ऐसा कर सकते हैं:
val logger = new Logger(...)
import logger.printerr
लेकिन अगर आपके पास logger
एक और बारह विधियां हैं, जिन्हें आप आयात और उपयोग करना चाहते हैं, तो उन्हें सूचीबद्ध करना असुविधाजनक हो जाता है। आप इसके बजाय कोशिश कर सकते हैं:
import logger.{println => donotuseprintlnt, _}
लेकिन यह अभी भी आयातित सदस्यों की सूची को "प्रदूषित" करता है। Über-शक्तिशाली वाइल्डकार्ड दर्ज करें:
import logger.{println => _, _}
और वह सिर्फ सही काम करेगा ™।
require
पद्धति (परिभाषित Predef
) जो आपको अतिरिक्त फ़ंक्शन बाधाओं को परिभाषित करने की अनुमति देती है जो रन-टाइम के दौरान जाँच की जाएगी। कल्पना कीजिए कि आप अभी तक एक और ट्विटर क्लाइंट विकसित कर रहे हैं और आपको ट्वीट की लंबाई 140 प्रतीकों तक सीमित करने की आवश्यकता है। इसके अलावा आप खाली ट्वीट पोस्ट नहीं कर सकते।
def post(tweet: String) = {
require(tweet.length < 140 && tweet.length > 0)
println(tweet)
}
अनुचित लंबाई तर्क के साथ अब कॉलिंग पोस्ट एक अपवाद का कारण होगा:
scala> post("that's ok")
that's ok
scala> post("")
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:145)
at .post(<console>:8)
scala> post("way to looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong tweet")
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:145)
at .post(<console>:8)
आप कई आवश्यकताएँ लिख सकते हैं या प्रत्येक में विवरण भी जोड़ सकते हैं:
def post(tweet: String) = {
require(tweet.length > 0, "too short message")
require(tweet.length < 140, "too long message")
println(tweet)
}
अब अपवाद हैं:
scala> post("")
java.lang.IllegalArgumentException: requirement failed: too short message
at scala.Predef$.require(Predef.scala:157)
at .post(<console>:8)
एक और उदाहरण यहाँ है ।
आप हर बार आवश्यकता विफल होने पर कार्रवाई कर सकते हैं:
scala> var errorcount = 0
errorcount: Int = 0
def post(tweet: String) = {
require(tweet.length > 0, {errorcount+=1})
println(tweet)
}
scala> errorcount
res14: Int = 0
scala> post("")
java.lang.IllegalArgumentException: requirement failed: ()
at scala.Predef$.require(Predef.scala:157)
at .post(<console>:9)
...
scala> errorcount
res16: Int = 1
require
एक आरक्षित शब्द नहीं है। यह एक विधि है, लेकिन इसमें परिभाषित है Predef
।
abstract override
विधियों के साथ लक्षण स्काला में एक विशेषता है जो कई अन्य लोगों के रूप में व्यापक रूप से विज्ञापित नहीं है। abstract override
संशोधक के साथ तरीकों का इरादा कुछ संचालन करना और कॉल को डेलिगेट करना है super
। फिर इन लक्षणों को अपने abstract override
तरीकों के ठोस कार्यान्वयन के साथ मिश्रित करना होगा ।
trait A {
def a(s : String) : String
}
trait TimingA extends A {
abstract override def a(s : String) = {
val start = System.currentTimeMillis
val result = super.a(s)
val dur = System.currentTimeMillis-start
println("Executed a in %s ms".format(dur))
result
}
}
trait ParameterPrintingA extends A {
abstract override def a(s : String) = {
println("Called a with s=%s".format(s))
super.a(s)
}
}
trait ImplementingA extends A {
def a(s: String) = s.reverse
}
scala> val a = new ImplementingA with TimingA with ParameterPrintingA
scala> a.a("a lotta as")
Called a with s=a lotta as
Executed a in 0 ms
res4: String = sa attol a
जबकि मेरा उदाहरण वास्तव में एक गरीब आदमी AOP से ज्यादा नहीं है, मैंने इन स्टैकेबल ट्रेट्स का इस्तेमाल किया, जो कि पूर्वनिर्धारित आयात, कस्टम बाइंडिंग और क्लासपैथ के साथ स्काला दुभाषिया उदाहरणों का निर्माण करना पसंद करते हैं। Stackable लक्षण यह संभव की तर्ज पर मेरा कारखाना बनाने के लिए किया जाता new InterpreterFactory with JsonLibs with LuceneLibs
है और फिर उपयोगी आयात किया है और क्षेत्र के लिए उन लिपियों varibles।