স্কালার লুকানো বৈশিষ্ট্যগুলি কী কী যা প্রতিটি স্কালার বিকাশকারীকে জানা উচিত?
দয়া করে উত্তর প্রতি একটি লুকানো বৈশিষ্ট্য, দয়া করে।
স্কালার লুকানো বৈশিষ্ট্যগুলি কী কী যা প্রতিটি স্কালার বিকাশকারীকে জানা উচিত?
দয়া করে উত্তর প্রতি একটি লুকানো বৈশিষ্ট্য, দয়া করে।
উত্তর:
ঠিক আছে, আমাকে আরও একটি যোগ করতে হয়েছিল। 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)
}
ম্যানিফেষ্টগুলি যা রানটাইমের সময় টাইপের তথ্য পাওয়ার ক্ষেত্রে এক ধরণের উপায়, যেন স্কালাকে পুনরায় সংশোধন করা হয়েছে।
স্কেলা ২.৮-এ আপনার প্যাকেজটি scala.util.control.TailCalls ব্যবহার করে পুচ্ছ-পুনরাবৃত্তির পদ্ধতি থাকতে পারে (আসলে এটি ট্রামোলাইনিং)।
একটি উদাহরণ:
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
Predef.scala এ বর্তমানের প্রয়োগ।
স্কেল্যাক-এক্সপ্রিন্ট: <ফেজ> কিছু সংকলক পর্যায়ে সিনট্যাক্স ট্রি মুদ্রণ করবে। উপলভ্য পর্যায়গুলি দেখতে স্ক্যাল্যাক-শো-পর্যায়গুলি ব্যবহার করুন ।
পর্দার আড়ালে কী চলছে তা শেখার এটি দুর্দান্ত উপায়।
দিয়ে চেষ্টা করুন
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
স্কেলা ২.৮ এ টিকা:
কোনও ম্যাচ এক্সপ্রেশনটিতে প্রয়োগ করতে একটি টিকা। উপস্থিত থাকলে, সংকলকটি যাচাই করবে যে ম্যাচটি একটি টেবিলসুইচ বা লাক্সুউসউইচকে সংকলিত হয়েছে এবং যদি এটি পরিবর্তে শর্তসাপেক্ষ প্রকাশের একটি সিরিজের মধ্যে সংকলন করে তবে একটি ত্রুটি জারি করে।
উদাহরণ:
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
টাইপ পরামিতিগুলির স্ব স্ব স্পষ্ট করে তুলবে।
স্কেলা ২.৮ ডিফল্ট এবং নামযুক্ত যুক্তি উপস্থাপন করেছিল, যা স্ক্যালার কেস ক্লাসগুলিতে যুক্ত হওয়া একটি নতুন "অনুলিপি" পদ্ধতির সংযোজন সম্ভব করেছিল। আপনি যদি এটি সংজ্ঞায়িত করেন:
case class Foo(a: Int, b: Int, c: Int, ... z:Int)
এবং আপনি একটি নতুন ফু তৈরি করতে চান যা বিদ্যমান ফু এর মতো, কেবল একটি ভিন্ন "n" মান সহ, তবে আপনি কেবল বলতে পারেন:
foo.copy(n = 3)
স্কেলা ২.৮ এ আপনি আপনার জেনেরিক ক্লাস / পদ্ধতিতে @ বিশেষায়িত যুক্ত করতে পারেন। এটি আদিম ধরণের (যেকোনও পরিমাণ বাড়ানো) জন্য শ্রেণীর বিশেষ সংস্করণ তৈরি করবে এবং অপ্রয়োজনীয় বক্সিং / আনবক্সিংয়ের ব্যয় সাশ্রয় করবে:
class Foo[@specialized T]...
আপনি যেকোনওভ্যালসের একটি উপসেট নির্বাচন করতে পারেন:
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)
আপনি কোনও ফাংশনে একটি কল-বাই-নাম প্যারামিটার নির্ধারণ করতে পারেন (সম্পাদনা করুন: এটি আলাদা তখন কোনও অলস প্যারামিটার!) এবং কোনও ফাংশন ব্যবহার না করা পর্যন্ত এটি মূল্যায়ন করা হবে না (সম্পাদনা: বাস্তবে, এটি প্রতিবারই পুনরায় মূল্যায়ন করা হবে ব্যবহৃত হয়)। বিশদ জানতে এই FAQ দেখুন
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
"Predef.scala" এ হিসাবে সংজ্ঞায়িত করা হয়েছে:
@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
)_
শনাক্তকারীদের আইনী এমন জায়গায় এম্বেডড আন্ডারস্কোর চিহ্ন থাকতে পারে । এই জাতীয় অভিব্যক্তি একটি বেনামী ফাংশন প্রতিনিধিত্ব করে যেখানে আন্ডারস্কোরগুলির পরবর্তী ঘটনাগুলি ক্রমাগত পরামিতিগুলি বোঝায়।
থেকে Scala ভাষা পরিবর্তনগুলি :
_ + 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
}
এটি ঠিক একইভাবে ব্যবহৃত হয়।
ছদ্মবেশগুলির কোনও মান থাকতে পারে। এগুলি গ্রন্থাগারের তথ্য গোপন করার জন্য ব্যবহার করা যেতে পারে। উদাহরণস্বরূপ নিম্নলিখিত উদাহরণটি ধরুন:
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")
}
}
এই উদাহরণস্বরূপ, ওয়াই অবজেক্টে "f" কল করার পরে লগটি ডিফল্ট ডেমনগুলিতে প্রেরণ করা হবে এবং এক্সের উদাহরণে ডেমোন এক্স ডেমনকে প্রেরণ করা হবে। তবে এক্স এর উদাহরণস্বরূপ জি কল করা স্পষ্টভাবে প্রদত্ত ডিফল্টডেমনে লগটি প্রেরণ করবে।
যদিও এই সাধারণ উদাহরণটি ওভারলোড এবং প্রাইভেট স্টেট দিয়ে পুনরায় লেখা যেতে পারে, তবে জড়িতদের ব্যক্তিগত রাষ্ট্রের প্রয়োজন হয় না এবং আমদানির সাথে প্রসঙ্গে আনা যায়।
খুব বেশি গোপন নাও থাকতে পারে তবে আমি মনে করি এটি দরকারী:
@scala.reflect.BeanProperty
var firstName:String = _
এটি স্বয়ংক্রিয়ভাবে শিমের সম্মেলনের সাথে মেলে এমন ক্ষেত্রের জন্য একটি গেটর এবং সেটার তৈরি করবে।
বিকাশকারীদের আরও বিবরণ
সমাপ্তিতে জড়িত যুক্তি argu
কোনও ফাংশন আর্গুমেন্টকে যেমন পদ্ধতিগুলির সাথে অন্তর্ভুক্ত হিসাবে চিহ্নিত করা যেতে পারে। ফাংশনের মূল অংশের মধ্যে অন্তর্নিহিত পরামিতি দৃশ্যমান এবং অন্তর্নিহিত রেজোলিউশনের জন্য যোগ্য:
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)
।
স্কালা আপনাকে ক্লাসের বডি (কন্সট্রাক্টর) এর বডির সাথে বেনামে একটি সাবক্লাস তৈরি করার অনুমতি দেয় যাতে ক্লাসের উদাহরণটি সূচনা করতে স্টেটমেন্ট থাকে।
উপাদান-ভিত্তিক ব্যবহারকারীর ইন্টারফেসগুলি তৈরি করার সময় এই প্যাটার্নটি খুব কার্যকর for
দেখুন 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, _}
তবে এটি আমদানিকৃত সদস্যদের তালিকাটিকে "দূষিত" করে। ওবার-শক্তিশালী ওয়াইল্ডকার্ড প্রবেশ করান:
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
যদিও আমার উদাহরণটি একজন দরিদ্র ম্যানস এওপি-র তুলনায় আসলে বেশি কিছু নয়, আমি পূর্বনির্ধারিত আমদানি, কাস্টম বাইন্ডিং এবং ক্লাসপাথগুলি দিয়ে স্কালা ইন্টারপ্রেটার উদাহরণগুলি তৈরি করতে আমার পছন্দ অনুসারে এই স্ট্যাকেবল বৈশিষ্ট্যগুলি বেশি ব্যবহার করেছি। Stackable বৈশিষ্ট এটা সম্ভব লাইন বরাবর আমার কারখানা তৈরি করতে তৈরি new InterpreterFactory with JsonLibs with LuceneLibs
এবং তারপর দরকারী আমদানির আছে এবং সুযোগ জন্য ব্যবহারকারীদের স্ক্রিপ্ট varibles।