66

Scalaのシンタックスシュガーのすべてのインスタンスは何ですか?

それらのほとんど/すべてが純粋なシンボルであり、したがって概念の名前を知らずに検索するのは難しいため、それらを検索するのは困難です。

TODO:

  • 暗黙の変換
  • _無名関数の構文
  • 私が忘れている他のこと
4

6 に答える 6

62

基本:

  • a bと同等a.bです。
  • a b cで終わるa.b(c)場合を除いて、と同等です。その場合、はと同等です。b:a b cc.b(a)
  • a(b)これはa.apply(b)、無名関数の次の定義が同一である理由です。

    val square1 = (x: Int) => x*x
    val square2 = new Function1[Int,Int] {
        def apply(x: Int) = x*x
    }
    

    を呼び出すときsquare1(y)は、実際に呼び出しsquare1.apply(y)ているのは、トレイト(またはなど)でsquare1指定されている必要があります。Function1Function2

  • a(b) = cと同等a.update(b,c)です。同様に、などa(b,c) = dと同等a.update(b,c,d)です。

  • a.b = cと同等a.b_=(c)です。クラス/オブジェクトにval/を作成すると、Scalaがメソッドを作成します。これらは自分で定義できますが、定義する場合は定義する必要があります。そうしないと、コンパイルされません。次に例を示します。var xxx_=y_=y

    scala> val b = new Object{ def set_=(a: Int) = println(a) }
    b: java.lang.Object{def set_=(Int): Unit} = $anon$1@17e4cec
    
    scala> b.set = 5
    <console>:6: error: value set is not a member of java.lang.Object{def set_=(Int): Unit}
           b.set = 5
             ^
    
    scala> val c = new Object{ def set = 0 ; def set_=(a:Int) = println(a) }
    c: java.lang.Object{def set: Int; def set_=(Int): Unit} = $anon$1@95a253
    
    scala> c.set = 5
    5
    
  • -aに対応しa.unary_-ます。同様に+a、、、~aおよび!a

  • a <operator>= b、ここで、は特殊文字のセットであり、メソッドがない場合にのみ<operator>同等です。次に例を示します。a = a <operator> b a<operator>=

    class test(val x:Int) {
        def %%(y: Int) = new test(x*y)
    }
    
    var a = new test(10)
    a.x // 10
    a %%= 5 // Equivalent to a = a %% 5
    a.x // 50
    
于 2010-04-18T16:36:46.833 に答える
21

特別なクラス:タプルとシンボル

Rahul Gが述べたように、タプルとシンボルは少し特殊な構文になります。

  • 記号:構文'xは次の略語です。Symbol("x")
  • タプル:(p1,p2,..,pn)ケースクラスの略ですTuplen[T1,T2,..,Tn](p1,p2,..,pn)

たとえば、次の2つは同等です。

val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
于 2010-04-19T21:18:00.273 に答える
19

ジャクソンの答えに加えて:

  • type F[A,B]として使用できますA F B

例えば:

type ->[A,B] = (A,B)
def foo(f: String -> String)
  • メソッド定義で使用=> typeすると、コンパイラは関数サンクのメソッド呼び出し内で式をラップします。

例えば

def until(cond: => Boolean)(body: => Unit) = while(!cond) body

var a = 0
until (a > 5) {a += 1}
于 2010-04-19T17:38:09.130 に答える
15

抽出器:

エクストラクタに使用される方法は2つありunapplyますunapplySeq。これらは、複数の変数の割り当てとパターンマッチングで使用されます。

  • 最初のユースケースは、una​​pplyが一致するはずのオブジェクトを取得し、Boolean一致するかどうかに基づいてを返す場合です。たとえば、

    trait Gender
    trait Male extends Gender
    trait Female extends Gender
    object Male extends Male
    object Female extends Female
    class Person(val g: Gender, val age: Int)
    
    object Adult {
        def unapply(p: Person) = p.age >= 18
    }
    
    def check(p: Person) = p match {
        case Adult() => println("An Adult")
        case _ => println("A Child")
    }
    
    //Will print: An Adult since Adult.unapply returns true.
    check(new Person(Female, 18))
    
    //Will print: A Child as it falls through to the _ case.
    check(new Person(Male, 17))
    

case正直なところ、ステートメントにコードを挿入するだけでほぼ同じように簡単に実行できるため、上記の構文の目的は実際にはわかりません。もちろん、もっと良い例があれば、下にコメントを残してください

  • unapplyいくつかの固定数のパラメーターを受け取りOption[T]、単一のパラメーターまたは複数のパラメーターのいずれかを返す一般的なケース。Option[(p1,p2,...)]つまり、上記のコードから継続して、値が一致するタプルを返します。

    object Person {
        def apply(g: Gender, age: Int) = new Person(g, age)
        def unapply(p: Person) = if(p.age < 0) None else Some((p.g, p.age))
    }
    
    //Using Person.apply as described in the Basics section
    val alice = Person(Female, 30)
    val bob = Person(Male, 25)
    
    //This calls Person.unapply(alice), which returns Some((Female, 30)).
    //alice_gender is assigned Female and alice_age 30.
    val Person(alice_gender, alice_age) = alice
    
    bob match {
        //Calls Person.unapply(bob), but sees that g is Male, so no match.
        case Person(Female, _) => println("Hello ma'am")
        //Calls Person.unapply(bob) and assigns age = bob.age, but it doesn't pass
        //the 'if' statement, so it doesn't match here either.
        case Person(Male, age) if age < 18 => println("Hey dude")
        //So bob falls through to here
        case _ => println("Hello Sir")
    }
    
    Person(Male,-1) match {
        //Person.unapply(Person.apply(Male,-1)) returns None because p.age < 0.
        //Therefore this case will not match.
        case Person(_, _) => println("Hello person")
        //Thus it falls through to here.
        case _ => println("Are you Human?")
    }
    

注: ケースクラスは、これらすべてのapply/unapply定義(およびその他のもの)を実行するため、時間を節約し、コードを削減するために、可能な限りそれらを使用してください。

  • unapplySeq。これは、ある種のシーケンスをunapply返す必要があることを除いて、上記と同様に機能します。Option

簡単な例として、

scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))
于 2010-04-19T20:59:12.843 に答える
7

匿名関数:

_ + _の略です(a, b) => a + b

于 2013-10-04T21:47:22.940 に答える
7

コンテキストは、デシュガーをパラメーターにバインドします。たとえば、型クラスimplicitを活用する関数を考えます。Monoid

def suml[T: Monoid](xs: List[T]) = {
  val T = implicitly[Monoid[T]]
  xs.foldLeft(T.mzero)(T.mplus)
}

パーツが: Monoidコンテキストにバインドされている場合、次のように変換されます。

def suml[T](xs: List[T])(implicit evidence$1: Monoid[T]]) = {
  ...
}

したがって、以下もコンパイルされます。

def suml[T: Monoid](xs: List[T]) = {
  val T = evidence$1
  ...
}
于 2014-09-23T13:51:59.127 に答える