2010-04-18 20 views
61

¿Cuáles son todas las instancias de azúcar sintáctico en Scala?¿Cuáles son todas las instancias de azúcar sintáctico en Scala?

Son difíciles de buscar ya que la mayoría de ellos son puramente símbolos y, por lo tanto, difíciles de buscar sin conocer el nombre del concepto.

TODO:

  • conversiones implícitas
  • _ sintaxis para funciones anónimas
  • Otras cosas que estoy olvidando
+1

Más HORARIOS: Tuplas, Símbolos, Literales XML. – missingfaktor

+0

No creo que XML encaje porque no es realmente azúcar en el sentido de taquigrafía de otra cosa. Aunque estoy de acuerdo en Tuplas y Símbolos. –

+2

Si vio el código ejecutado para construir las instancias XML DOM correspondientes a los literales XML, creo que tendría que aceptar que los literales son una abreviatura. –

Respuesta

55

básico:

  • a b es equivalente a 01.236.
  • a b c es equivalente a a.b(c), excepto cuando b termina en :. En ese caso, a b c es equivalente a c.b(a)
  • a(b) es equivalente a a.apply(b) Esta es la razón por las siguientes definiciones para un funciones anónimas son idénticos: val square1 = (x: Int) => x x val square2 = new function1 [Int, Int] { aplica def (x: int) = x x }

    al llamar square1(y), en realidad se está llamando square1.apply(y)square1 cual debe tener como especifica el Function1 rasgo (o Function2, etc. ...)

  • a(b) = c es equivalente a a.update(b,c) Del mismo modo, a(b,c) = d es equivalente a a.update(b,c,d) y así sucesivamente.

  • a.b = c es equivalente a a.b_=(c). Cuando crea un val/varx en una Clase/Objeto, Scala crea los métodos x y x_= por usted.Puede definir estos usted mismo, pero si se define y_= que debe definir y o no va a compilar, por ejemplo,

    scala> val b = new Object{ def set_=(a: Int) = println(a) } 
    b: java.lang.Object{def set_=(Int): Unit} = [email protected] 
    
    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} = [email protected] 
    
    scala> c.set = 5 
    5 
    
  • -a corresponde a a.unary_- Asimismo para +a, ~a y !a

  • a <operator>= b, donde <operator> es un conjunto de caracteres especiales, es equivalente a a = a <operator> bsolo si a no tiene el método de <operator>=, por ejemplo,

    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 
    
+0

así que si 'foo (bar)' es equivalente a 'foo.apply (bar)' entonces 'foo.apply (bar)' debe ser equivalente a 'foo.apply.apply (bar)', y así sucesivamente. –

+0

Qué bonito buscar 'x y' y descubrir que es simplemente como' x.y'. Cómo es que esto hace las cosas más prácticas, es algo que realmente no entiendo. Gracias por tu ayuda. – Dacav

+0

Gracias por la advertencia de que se requiere un campo 'y' para un campo' y_ = ' – radke

19

Además de la respuesta de Jaxkson:

  • type F[A,B] se puede utilizar como A F B.

Por ejemplo:

type ->[A,B] = (A,B) 
def foo(f: String -> String) 
  • Usando => type en una definición del método hace que las expresiones de envoltura compilador dentro de la llamada a un método en un golpe seco función.

Por ejemplo

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

var a = 0 
until (a > 5) {a += 1} 
+1

No sabía realmente acerca de esa primera sintaxis, interesante. Es por eso que necesitamos una página consolidada como esta. –

+0

¿Puedes dar un ejemplo para la primera sintaxis?Será una gran ayuda – asyncwait

14

Extractores:

Hay dos métodos utilizados para extractores, unapply y unapplySeq. Estos se utilizan en asignaciones de variables múltiples y coincidencia de patrones.

  • El caso del primer uso es donde cancelar la aplicación toma el objeto que se supone que coincidir y devuelve un Boolean en función de si es o no coincide, por ejemplo,

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

Honestamente, realmente no entiendo el propósito de la sintaxis anterior ya que se puede hacer casi igual de fácil simplemente poniendo el código en las declaraciones case. Por supuesto, si usted tiene un mejor ejemplo, dejar un comentario más abajo

  • El caso general en unapply toma algún número fijo de parámetros y devuelve o una Option[T] para un solo parámetro o una Option[(p1,p2,...)] para múltiples, es decir, una tupla con los valores coincidentes, por ejemplo, continuando desde el código anterior:

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

Nota:Case classes hacer todas esas apply/unapply definiciones para usted (así como otras cosas) así que úselas siempre que sea posible para ahorrar tiempo y reducir el código.

  • unapplySeq. Esto funciona de manera similar a unapply como arriba, excepto que debe devolver un Option de algún tipo de secuencia.

Como un ejemplo rápido,

scala> List.unapplySeq(List(1,2,3)) 
res2: Some[List[Int]] = Some(List(1, 2, 3)) 
18

clases especiales: tuplas y Símbolos

Como se ha mencionado por Rahul G, tuplas y símbolos obtener una sintaxis un poco especial.

  • Símbolos: la sintaxis 'x es la abreviatura de Symbol("x")
  • tuplas: (p1,p2,..,pn) es la abreviatura de una clase caso Tuplen[T1,T2,..,Tn](p1,p2,..,pn)

Por ejemplo, los dos siguientes son equivalentes.

funciones
val tuple1 = ("Hello",1) 
val tuple2 = Tuple2[String,Int]("Hello",1) 
+1

Esto no es exclusivo de tuplas y símbolos, sin embargo: cadenas, enteros, largos, dobles, flotantes, caracteres, booleanos, funciones, XML y 'null' también tienen una sintaxis literal especial. De hecho, discutiría si los literales son o no "azúcar sintáctico". El azúcar sintáctico es una transformación de código puramente local. ¿En qué se transforman los literales? –

4

Anónimo:

_ + _ es la abreviatura de (a, b) => a + b

3

fuera de contexto desugar en implicit parámetros, por ejemplo considerar una función que aprovecha la clase Monoid Tipo:

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

donde la parte : Monoid es un contexto ligado, se traduce a:

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

por lo tanto las siguientes compilaciones, también:

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