Jakie są wszystkie instancje cukru składniowego w Scali?

Jakie są wszystkie instancje cukru składniowego w Scali?

Trudno ich szukać, ponieważ większość / wszystkie z nich są czysto symbolami i dlatego trudno ich szukać bez znajomości nazwy pojęcia.

TODO:

  • Implicit conversions
  • _ składnia funkcji anonimowych
  • inne rzeczy, o których zapominam
Author: Peter Mortensen, 2010-04-18

6 answers

Podstawy:

  • a b jest równoważne a.b
  • {[4] } jest równoważne a.b(c), z wyjątkiem sytuacji, gdy b Kończy się na :. W takim przypadku a b c jest równoważne c.b(a)
  • a(b) jest równoważne a.apply(b) dlatego następujące definicje funkcji anonimowych są identyczne: val square1 = (X: Int) = > x x val square2 = new function 1[Int, Int] { def apply(x: Int) = x x }

    Kiedy dzwonisz square1(y), jesteś wywołanie square1.apply(y) które square1 musi mieć określone przez Function1 trait (or Function2, itd...)

  • a(b) = c jest równoważne a.update(b,c) podobnie, {[19] } jest równoważne a.update(b,c,d) i tak dalej.

  • a.b = c jest równoważne a.b_=(c). Podczas tworzenia val/var x w klasie/obiekcie Scala tworzy dla Ciebie metody x i x_=. Możesz je zdefiniować samodzielnie, ale jeśli zdefiniujesz y_= musisz zdefiniować zdefiniować y, inaczej nie będzie kompilowany, dla przykład,

    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 odpowiada a.unary_- podobnie dla +a,~a, oraz !a

  • a <operator>= b, gdzie <operator> jest pewnym zbiorem znaków specjalnych, jest odpowiednikiem a = a <operator> b tylko jeśli a nie ma metody <operator>=, na przykład

    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
    
 56
Author: Jackson Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-28 15:05:57

Oprócz odpowiedzi Jaxksona:

  • type F[A,B] może być używany jako A F B.

Na przykład:

type ->[A,B] = (A,B)
def foo(f: String -> String)
  • użycie => type w definicji metody powoduje, że kompilator zawija wyrażenia wewnątrz wywołania metody w funkcję thunk.

Na przykład

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

var a = 0
until (a > 5) {a += 1}
 19
Author: IttayD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-19 17:38:09

Klasy specjalne: krotki i symbole

Jak wspomniano przez Rahul g , krotki i symbole mają nieco specjalną składnię.

  • Symbole: składnia {[1] } jest skrótem od Symbol("x")
  • krotki: (p1,p2,..,pn) to skrót od klasy case Tuplen[T1,T2,..,Tn](p1,p2,..,pn)

Na przykład następujące dwa są równoważne.

val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
 18
Author: Jackson Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:59

Ekstraktory:

Istnieją dwie metody stosowane dla ekstraktorów, unapply i unapplySeq. Są one używane w wielu przypisaniach zmiennych i dopasowywaniu wzorców.

  • Pierwszy przypadek użycia polega na tym, że unaply pobiera obiekt, do którego ma pasować i zwraca Boolean na podstawie tego, czy pasuje, czy nie, na przykład

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

Szczerze mówiąc, nie rozumiem celu powyższej składni, ponieważ można to zrobić prawie tak samo łatwo, umieszczając kod w oświadczeniach case. Oczywiście, jeśli masz lepszy przykład, zostaw komentarz poniżej

  • Ogólny przypadek, w którym unapply pobiera pewną stałą liczbę parametrów i zwraca {[8] } dla pojedynczego parametru lub Option[(p1,p2,...)] dla wielokrotności, tj. krotkę z dopasowanymi wartościami, na przykład, kontynuując powyższy kod:

    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?")
    }
    

Uwaga: klasy Case wykonują wszystkie te apply/unapply definicje dla Ciebie (jak i innych rzeczy) więc używaj ich kiedy możliwe, aby zaoszczędzić czas i zmniejszyć kod.

  • unapplySeq. Działa to podobnie do unapply Jak wyżej, z tym że musi zwrócić Option pewnego rodzaju sekwencję.

Jako szybki przykład,

scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))
 14
Author: Jackson Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 16:53:03

Context ogranicza desugar do implicit parametrów, np. rozważmy funkcję wykorzystującą klasę typu Monoid:

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

Gdzie : Monoid część jest związana z kontekstem, zostaje przetłumaczona na:

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

Dlatego też kompiluje się:

def suml[T: Monoid](xs: List[T]) = {
  val T = evidence$1
  ...
}
 5
Author: Erik Allik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-23 13:57:01

Funkcje anonimowe:

_ + _ jest skrótem od (a, b) => a + b

 4
Author: vadipp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-04 22:07:33