স্কালার লুকানো বৈশিষ্ট্য


149

স্কালার লুকানো বৈশিষ্ট্যগুলি কী কী যা প্রতিটি স্কালার বিকাশকারীকে জানা উচিত?

দয়া করে উত্তর প্রতি একটি লুকানো বৈশিষ্ট্য, দয়া করে।


6
হ্যাঁ, এই প্রশ্নটি অন্যান্য লুকানো বৈশিষ্ট্য পোস্টগুলির লিঙ্কগুলির জন্য যেমন প্রশ্ন হিসাবে ততটাই দরকারী। চিয়ার্স!
জনমেটা

1
@ মেটাডোর শুধু ডানদিকে সম্পর্কিত লিঙ্কগুলি দেখুন ।
ড্যানিয়েল সি। সোব্রাল

2
@ জনমেটা: বা ট্যাগটি ব্যবহার করুন ।

উত্তর:


85

ঠিক আছে, আমাকে আরও একটি যোগ করতে হয়েছিল। 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]উপাদানগুলি ক্রম অনুসারে নির্ধারিত হয় চলক বছর, মাস এবং দিন।


1
এই পোস্ট করার জন্য Thx! এফওয়াইআই এটি প্রথম সংস্করণের 503 পৃষ্ঠায় এবং দ্বিতীয় সংস্করণের 611 পৃষ্ঠায় "স্ক্যালারিং ইন স্ক্যাল" বইয়ের "নিয়মিত অভিব্যক্তি নিয়ে এক্সট্রাক্টিং" অধ্যায়টিতে উল্লেখ করেছে।
আর্থিং পল

51

কাঠামোগত ধরণের সংজ্ঞা - অর্থ কোনও পদ্ধতি যা সমর্থন করে তা দ্বারা বর্ণিত। উদাহরণ স্বরূপ:

object Closer {
    def using(closeable: { def close(): Unit }, f: => Unit) {
      try { 
        f
      } finally { closeable.close }
    }
}

লক্ষ করুন যে, টাইপ প্যারামিটারের closeableএটা ছাড়া অন্য সংজ্ঞায়িত করা হয় না একটি আছে closeপদ্ধতি


1
এমনকি "স্কালায় প্রোগ্রামিং" তে স্ট্রাকচারাল ধরণের উল্লেখ নেই। এগুলি পাস করার ধরণের অন্যান্য কৌশলগুলির তুলনায় কিছুটা ধীরে ধীরে হলেও তারা সঠিক পদ্ধতিগুলি কল করার জন্য প্রতিবিম্ব ব্যবহার করে। (আশা করি তারা গতি বাড়ানোর একটি উপায় নিয়ে আসবে))
কেন ব্লুম

1
এবং তাদের জন্য উপন্যাস তৈরি করাও সম্ভব, বাহ্যিকভাবে নির্ধারিত ইন্টারফেসের মতো (যা খুব ধীর এক) কাজ করে: টাইপ করুন ক্লোজেবল = {ডিফ ক্লোজ (): ইউনিট}
আলেক্সি

45

টাইপ-কনস্ট্রাক্টর পলিমারফিজম (ওরফে উচ্চ ধরণের ধরণের)

এই বৈশিষ্ট্যটি ব্যতীত আপনি উদাহরণস্বরূপ, অন্য তালিকার প্রত্যাবর্তনের জন্য কোনও তালিকার উপরে কোনও ফাংশন ম্যাপিংয়ের ধারণাটি প্রকাশ করতে পারেন, বা গাছের উপরে কোনও ফাংশন ম্যাপিংয়ের জন্য অন্য গাছটি ফিরিয়ে আনতে পারেন। তবে আপনি সাধারণত উচ্চতর ধরণের ছাড়াই এই ধারণাটি প্রকাশ করতে পারবেন না ।

উচ্চতর ধরণের সাথে, আপনি অন্য ধরণের সাথে প্যারামিটারাইজড যে কোনও ধরণের ধারণাটি ক্যাপচার করতে পারেন । এক ধরণের কনস্ট্রাক্টর যা একটি প্যারামিটার নেয় তা ধরণের বলে (*->*)। উদাহরণস্বরূপ List,। একটি টাইপ কনস্ট্রাক্টর যা অন্য টাইপ কনস্ট্রাক্টরকে রিটার্ন দেয় তা ধরণের বলে (*->*->*)। উদাহরণস্বরূপ Function1,। তবে স্কালায় আমাদের আরও ধরণের রয়েছে, তাই আমাদের কাছে টাইপ কনস্ট্রাক্টর থাকতে পারে যা অন্যান্য ধরণের কনস্ট্রাক্টরের সাথে পরামিতিযুক্ত। সুতরাং তারা মত ধরণের ((*->*)->*)

উদাহরণ স্বরূপ:

trait Functor[F[_]] {
  def fmap[A, B](f: A => B, fa: F[A]): F[B]
}

এখন, আপনার যদি একটি থাকে তবে আপনি Functor[List]তালিকাগুলিতে ম্যাপ করতে পারেন। আপনার যদি একটি থাকে তবে আপনি Functor[Tree]গাছের উপরে মানচিত্র তৈরি করতে পারেন। তবে আরও গুরুত্বপূর্ণ বিষয়, আপনার যদি Functor[A] কোনও এ ধরণের(*->*) থাকে তবে আপনি কোনও ফাংশন ম্যাপ করতে পারেন A


39

এক্সট্র্যাক্টরগুলি যা আপনাকে 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)     
}

এটি কি সুইচের মতো নয়? সম্ভবত এটি আরও রিফ্যাক্টর হতে পারে।
জিও

14
প্যাটার্নগুলি টার্বো-চার্জড সুইচের মতো: আরও বেশি শক্তিশালী এবং স্পষ্ট
অক্সবো_লাক

1
ভাল লাগছে, তবে আমি পছন্দ করি না যে আপনাকে অন্তর্নিহিত ব্যবহার করতে হবে কারণ এর ব্যাপ্তি ম্যাচ than} এর চেয়ে আরও বেশি ছুঁয়েছে} আপনি কেবলমাত্র পণ্যসেবাতে এমন একটি পদ্ধতি যুক্ত করতে পারেন যা কোড অনুসারে একটি পণ্য দেখায়। আপনি যে কোনও উপায়ে এটি ব্যবহার করতে সক্ষম হবেন আপনি কোনও পদ্ধতিতে আপনার রিফ্যাক্টর স্নিপেটটি জড়ান।
মার্টিন কোনিসেক

35

ম্যানিফেষ্টগুলি যা রানটাইমের সময় টাইপের তথ্য পাওয়ার ক্ষেত্রে এক ধরণের উপায়, যেন স্কালাকে পুনরায় সংশোধন করা হয়েছে।


8
আমি মনে করি যে কোনও লিঙ্কের উল্লেখ না করে উত্তরে উত্তরটি ব্যাখ্যা করা ভাল । যাইহোক, হাই আগাই অক্সবো! :-)
ড্যানিয়েল সি সোব্রাল

এটি সত্যই লুকানো বৈশিষ্ট্য ... এমনকি এপিআই ডক্সেও নয়। যদিও খুব দরকারী।
আন্দ্রে লাসল্লো

35

স্কেলা ২.৮-এ আপনার প্যাকেজটি 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)

35

কেস ক্লাসগুলি স্বয়ংক্রিয়ভাবে পণ্যাদির বৈশিষ্ট্যে মিশ্রিত হয়, কোনও প্রতিবিম্ব ছাড়াই ক্ষেত্রগুলিতে টাইপযুক্ত, সূচিকৃত অ্যাক্সেস সরবরাহ করে:

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)) 

32

এটি হুবহু লুকানো নয়, তবে অবশ্যই এটি একটি বিজ্ঞাপনযুক্ত বৈশিষ্ট্যের অধীনে: স্কেল্যাক-এক্সপ্রিন্ট

ব্যবহারের উদাহরণ হিসাবে নিম্নলিখিত উত্সটি বিবেচনা করুন:

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 augmentStringPredef.scala এ বর্তমানের প্রয়োগ।

স্কেল্যাক-এক্সপ্রিন্ট: <ফেজ> কিছু সংকলক পর্যায়ে সিনট্যাক্স ট্রি মুদ্রণ করবে। উপলভ্য পর্যায়গুলি দেখতে স্ক্যাল্যাক-শো-পর্যায়গুলি ব্যবহার করুন ।

পর্দার আড়ালে কী চলছে তা শেখার এটি দুর্দান্ত উপায়।

দিয়ে চেষ্টা করুন

case class X(a:Int,b:String)

এটি টাইপ পর্বটি ব্যবহার করে সত্যিই এটি কতটা দরকারী তা অনুভব করে।


30

আপনি নিজের নিয়ন্ত্রণ কাঠামো নির্ধারণ করতে পারেন। এটি সত্যই কেবল ফাংশন এবং অবজেক্টস এবং কিছু সিনট্যাকটিক চিনি, তবে তারা আসল জিনিসটির মতো দেখতে এবং আচরণ করে।

উদাহরণস্বরূপ, নিম্নলিখিত কোডগুলি সংজ্ঞায়িত করে 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) 


আমি যদি আগ্রহী হয়ে থাকি তবে কেউ যদি thenচ্ছিকরূপে অন্য কোনও ব্লককে সংজ্ঞায়িত করার কোনও উপায় জানে যে প্রমিতের মতো টাইপ-চেক করে।
ফিলিপ

@Philippe: zif[A : Zero](cond: => Boolean)(t: => A): A = if(cond) t else mzero। স্ক্যালজ দরকার।
মিসিংফ্যাক্টর

26

@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 {

26

ডান্নো যদি এটি সত্যিই লুকানো থাকে তবে আমি এটি দেখতে বেশ সুন্দর।

টাইপ কনস্ট্রাক্টর যারা 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
  }
}

1
নিস! আমি কল্পনা করতে পারি যে পাঠযোগ্যতার উন্নতিতে কখনও কখনও দরকারী being উদাহরণস্বরূপ var foo2barConverter: Foo ConvertTo Barটাইপ পরামিতিগুলির স্ব স্ব স্পষ্ট করে তুলবে।
এসকো লুন্তটোলা

4
আমি কখনও কখনও কোডে এটি করি যা কিছু পরিমাণে আংশিক ফাংশন ব্যবহার করে: টাইপ করুন ~> [এ, বি] = আংশিক ফাংশন [এ, বি]
রাইচু

24

স্কেলা ২.৮ ডিফল্ট এবং নামযুক্ত যুক্তি উপস্থাপন করেছিল, যা স্ক্যালার কেস ক্লাসগুলিতে যুক্ত হওয়া একটি নতুন "অনুলিপি" পদ্ধতির সংযোজন সম্ভব করেছিল। আপনি যদি এটি সংজ্ঞায়িত করেন:

case class Foo(a: Int, b: Int, c: Int, ... z:Int)

এবং আপনি একটি নতুন ফু তৈরি করতে চান যা বিদ্যমান ফু এর মতো, কেবল একটি ভিন্ন "n" মান সহ, তবে আপনি কেবল বলতে পারেন:

foo.copy(n = 3)

3
সতর্কতা: আপনি যদি অন্যের থেকে একটি কেস শ্রেণীর উত্তরাধিকারী হন তবে অনুলিপি করা হবে না। সুতরাং আপনাকে এটিকে ম্যানুয়ালি ওভাররাইড করতে হবে
আলেক্সি

সম্পর্কিত: নেস্টেড স্ট্রাকচার আপডেট করার জন্য ক্লিনার উপায় stackoverflow.com/q/3900307/203968
oluies

5
কেস ক্লাস আর নেই (স্কেলা ২.৮) কেস ক্লাস থেকে উত্তরাধিকারী হওয়ার অনুমতি নেই। এই অপরিষ্কার উত্তরাধিকার অবমূল্যায়নের জন্য স্কালার কর্ণধারকে ধন্যবাদ জানাই।
ওলে কুলবার্গ

24

স্কেলা ২.৮ এ আপনি আপনার জেনেরিক ক্লাস / পদ্ধতিতে @ বিশেষায়িত যুক্ত করতে পারেন। এটি আদিম ধরণের (যেকোনও পরিমাণ বাড়ানো) জন্য শ্রেণীর বিশেষ সংস্করণ তৈরি করবে এবং অপ্রয়োজনীয় বক্সিং / আনবক্সিংয়ের ব্যয় সাশ্রয় করবে: class Foo[@specialized T]...

আপনি যেকোনওভ্যালসের একটি উপসেট নির্বাচন করতে পারেন: class Foo[@specialized(Int,Boolean) T]...


1
আপনি কি আমাকে ইঙ্গিত করতে পারে একটি দীর্ঘ ব্যাখ্যা আছে? আমি আরও শিখতে চাই
পাওয়ে প্র্যাক

23

ভাষা প্রসারিত করা। আমি সবসময় জাভাতে এই জাতীয় কিছু করতে চাইতাম (পারিনি)। তবে স্কেলে আমি থাকতে পারি:

  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)

23

আপনি কোনও ফাংশনে একটি কল-বাই-নাম প্যারামিটার নির্ধারণ করতে পারেন (সম্পাদনা করুন: এটি আলাদা তখন কোনও অলস প্যারামিটার!) এবং কোনও ফাংশন ব্যবহার না করা পর্যন্ত এটি মূল্যায়ন করা হবে না (সম্পাদনা: বাস্তবে, এটি প্রতিবারই পুনরায় মূল্যায়ন করা হবে ব্যবহৃত হয়)। বিশদ জানতে এই 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
*/

আমি ভেবেছিলাম "x: => বার" এর অর্থ হ'ল x এমন একটি ফাংশন যা কোনও পরামিতি নেয় না এবং একটি বার ফিরিয়ে দেয়। সুতরাং, "নতুন বার (22)" কেবল একটি অনামী ফাংশন, এবং অন্য ফাংশনের মতো একটি ফাংশন হিসাবে মূল্যায়ন করা হয়।
অ্যালেক্স ব্ল্যাক

1
"x: () => বার" xa ফাংশনটি সংজ্ঞায়িত করে যা কোনও পরামিতি নেয় না এবং একটি বার প্রদান করে। x: => বার x নাম দ্বারা কল হিসাবে সংজ্ঞায়িত করে। কটাক্ষপাত scala.sygneca.com/faqs/... আরো বিস্তারিত জানার জন্য
agilefall

3
আপনি যা দেখান তা হ'ল কল-বাই নাম পরামিতি। অলস প্যারামিটারগুলি এখনও কার্যকর করা হয়নি: lampsvn.epfl.ch/trac/scala/ticket/240
আর্টেম জিআর

আমি মনে করি যে আপনি যদি lazy val xx: Bar = xআপনার পদ্ধতিতে এবং সেই মুহূর্ত থেকে আপনি কেবল ব্যবহার করেন তবে আপনি অলস পরম হিসাবে এটি ব্যবহার করতে পারেন xx
ক্রিশ্চিয়ান ভ্রাবী

20

আপনি 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

ইনলাইন হওয়ার কারণে এটি কোনও অতিরিক্ত ওভারহেড চাপায় না।


3
এটা উত্তম; এ ব্যাখ্যা করা হয় stackoverflow.com/questions/3237727/...
Esko Luontola

17

প্রাথমিক সূচনা:

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কার্যকর করার আগে এটির সূচনা হয়েছিল ।


1
কনস্ট্রাক্টটিকে "আর্লি ইনিশিয়ালাইজেশন" বলা হয়।
র‌্যান্ডাল স্কুল্জ

17

আপনি কীওয়ার্ডের সাথে স্ট্রাকচারাল ধরণের রচনা করতে পারেন

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
  }
}

17

বেনাম ফাংশন জন্য স্থানধারক বাক্য গঠন

স্কালা ভাষা নির্দিষ্টকরণ থেকে:

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))

2
এটি 'বেনাম ফাংশনগুলির জন্য স্থানধারক সিনট্যাক্স' হিসাবে উল্লেখ করা উচিত। স্কেলায় ইমপ্লিটের আলাদা অর্থ রয়েছে এবং এটি এর সাথে সম্পর্কিত নয়।
retronym

লিঙ্কটির উত্তরের সাথে একটি স্পষ্ট সম্পর্ক নেই। "অন্তর্নিহিত" এটির জন্য সঠিক শব্দ নয়। উপরে হিসাবে এটি "স্থানধারক" হওয়া উচিত।
আলাইন ও'ডিয়া

2
এটি আসলে "লুকানো" নয়, আমি স্ক্যালার যে সমস্ত টিউটোরিয়াল পড়েছি তার প্রায় সমস্ত টিউটোরিয়ালে আমি এই ব্যবহারটি দেখেছি ... :-) তবে আমি এখনও যে আনুষ্ঠানিক সংজ্ঞাটি দেখি নি তার প্রশংসা করি।
ফিলিহো

@ ফিলোহ, সম্ভবত এটি ২০০৯ সালে কম পরিচিত ছিল i আমি জানি না।
ইউজিন ইয়োকোটা

আমি শেষ তারিখটি মিস করেছি, কেবলমাত্র শেষ সম্পাদনার তারিখটি দেখানো হয়েছে। এবং ভাল, এই থ্রেডে বর্ণিত সমস্ত বৈশিষ্ট্য "লুকানো" নয়। দুর্দান্ত থ্রেড এবং যাইহোক ভাল উত্তর।
ফিলিহো

16

অন্তর্নিহিত সংজ্ঞা, বিশেষত রূপান্তর।

উদাহরণস্বরূপ, একটি ফাংশন ধরে নিন যা একটি ইনপুট স্ট্রিংকে "..." দিয়ে এর মাঝখানে প্রতিস্থাপন করে একটি আকারের সাথে মানিয়ে নিতে বিন্যাস করবে:

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" কল করার পরে লগটি ডিফল্ট ডেমনগুলিতে প্রেরণ করা হবে এবং এক্সের উদাহরণে ডেমোন এক্স ডেমনকে প্রেরণ করা হবে। তবে এক্স এর উদাহরণস্বরূপ জি কল করা স্পষ্টভাবে প্রদত্ত ডিফল্টডেমনে লগটি প্রেরণ করবে।

যদিও এই সাধারণ উদাহরণটি ওভারলোড এবং প্রাইভেট স্টেট দিয়ে পুনরায় লেখা যেতে পারে, তবে জড়িতদের ব্যক্তিগত রাষ্ট্রের প্রয়োজন হয় না এবং আমদানির সাথে প্রসঙ্গে আনা যায়।


13

খুব বেশি গোপন নাও থাকতে পারে তবে আমি মনে করি এটি দরকারী:

@scala.reflect.BeanProperty
var firstName:String = _

এটি স্বয়ংক্রিয়ভাবে শিমের সম্মেলনের সাথে মেলে এমন ক্ষেত্রের জন্য একটি গেটর এবং সেটার তৈরি করবে।

বিকাশকারীদের আরও বিবরণ


6
আপনি যদি এটি ব্যবহার করেন তবে আপনি এটির জন্য শর্টকাট তৈরি করতে পারেন, যেমন: scala.reflect আমদানি করুন {বিয়ানপ্রপার্টি => বিপি}
আলেক্সি

13

সমাপ্তিতে জড়িত যুক্তি 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")
  })
}


12

ফলাফলের প্রকারগুলি অন্তর্নিহিত রেজোলিউশনের উপর নির্ভরশীল। এটি আপনাকে একাধিক প্রেরণের একটি ফর্ম দিতে পারে:

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)
ড্যানিয়েল সি। সোব্রাল

4

জাভা ডাবল ব্রেস আরম্ভকারী এর সমতুল্য Sc

স্কালা আপনাকে ক্লাসের বডি (কন্সট্রাক্টর) এর বডির সাথে বেনামে একটি সাবক্লাস তৈরি করার অনুমতি দেয় যাতে ক্লাসের উদাহরণটি সূচনা করতে স্টেটমেন্ট থাকে।

উপাদান-ভিত্তিক ব্যবহারকারীর ইন্টারফেসগুলি তৈরি করার সময় এই প্যাটার্নটি খুব কার্যকর 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"))
}

3

সদস্যদের importবিবৃতি থেকে বাদ দেওয়া

মনে করুন আপনি Loggerএকটি printlnএবং একটি printerrপদ্ধতিযুক্ত এমন একটি ব্যবহার করতে চান তবে আপনি কেবল ত্রুটি বার্তাগুলির জন্য এটি ব্যবহার করতে এবং Predef.printlnস্ট্যান্ডার্ড আউটপুটটির জন্য ভাল রাখতে চান । আপনি এটি করতে পারেন:

val logger = new Logger(...)
import logger.printerr

তবে loggerএছাড়াও যদি আপনি আরও বারোটি পদ্ধতি ব্যবহার করেন যা আপনি আমদানি করতে এবং ব্যবহার করতে চান তবে সেগুলি তালিকাভুক্ত করা অসুবিধাজনক হয়ে ওঠে। পরিবর্তে আপনি চেষ্টা করতে পারেন:

import logger.{println => donotuseprintlnt, _}

তবে এটি আমদানিকৃত সদস্যদের তালিকাটিকে "দূষিত" করে। ওবার-শক্তিশালী ওয়াইল্ডকার্ড প্রবেশ করান:

import logger.{println => _, _}

এবং এটি ঠিক কাজ করবে ™।


2

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

1
requireকোনও সংরক্ষিত শব্দ নয়। এটি কিন্তু একটি পদ্ধতিতে সংজ্ঞায়িত Predef
মিসিংফ্যাক্টর

1

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।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.