web-dev-qa-db-ja.com

Scalaの構文糖のすべてのインスタンスは何ですか?

Scalaの構文糖のすべてのインスタンスは何ですか?

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

TODO:

  • 暗黙的な変換
  • _匿名関数の構文
  • 私が忘れている他のもの
64
Jackson Davis

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

  • 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}
19
IttayD

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

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)
_
18
Jackson Davis

エクストラクター:

エクストラクタには、unapplyunapplySeqの2つのメソッドが使用されます。これらは、複数の変数割り当てとパターンマッチングで使用されます。

  • 最初の使用例は、一致しないはずのオブジェクトをunapplyが受け取り、一致するかどうかに基づいて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))
_
14
Jackson Davis

匿名関数:

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

5
vadipp

コンテキストはdesugarを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
  ...
}
5
Erik Allik