¿Cuáles son todas las instancias de azúcar sintáctico en Scala?
syntactic-sugar (6)
Clases especiales: Tuplas y símbolos
Como menciona Rahul G , las tuplas y los símbolos tienen una sintaxis ligeramente especial.
- Símbolos: la sintaxis
''x
es la abreviatura deSymbol("x")
- Tuplas:
(p1,p2,..,pn)
es la abreviatura de una clase de casoTuplen[T1,T2,..,Tn](p1,p2,..,pn)
Por ejemplo, los siguientes dos son equivalentes.
val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
¿Cuáles son todas las instancias de azúcar sintáctico en Scala?
Son difíciles de buscar ya que la mayoría / todos ellos son puramente símbolos y, por lo tanto, difíciles de buscar sin conocer el nombre del concepto.
QUE HACER:
- Conversiones implícitas
-
_
sintaxis para funciones anónimas - Otras cosas que olvido
Extractores:
Hay dos métodos usados para extractores, unapply
y unapplySeq
. Estos se utilizan en asignaciones de variables múltiples y coincidencia de patrones.
El primer caso de uso es cuando una aplicación toma el objeto con el que se supone que debe coincidir y devuelve un
Boolean
según si coincide o no, 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 colocando el código en las declaraciones de case
. Por supuesto, si tiene un mejor ejemplo, deje un comentario a continuación
El caso general en el que
unapply
seunapply
toma un número fijo de parámetros y devuelve unaOption[T]
para un solo parámetro o unaOption[(p1,p2,...)]
para múltiples, es decir, una Tupla con los valores coincidentes, para 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: Las clases Case hacen todas esas definiciones de apply
/ unapply
para usted (así como para otras cosas) así que úselas siempre que sea posible para ahorrar tiempo y reducir el código.
-
unapplySeq
. Esto funciona de manera similar aunapply
como arriba, excepto que debe devolver unaOption
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))
Lo esencial:
-
ab
es equivalente aab
-
abc
es equivalente aab(c)
, excepto cuandob
termina en:
En ese caso,abc
es equivalente acb(a)
a(b)
es equivalente aa.apply(b)
Esta es la razón por la cual las siguientes definiciones para funciones anónimas son idénticas: val square1 = (x: Int) => x x val square2 = new Function1 [Int, Int] {def aplicar (x: Int) = x x}Al llamar a
square1(y)
, en realidad está llamando asquare1.apply(y)
quesquare1
debe tener como lo especifica el rasgo deFunction1
(oFunction2
, etc ...)a(b) = c
es equivalente aa.update(b,c)
Del mismo modo,a(b,c) = d
es equivalente aa.update(b,c,d)
y así sucesivamente.ab = c
es equivalente aa.b_=(c)
. Cuando creas unval
/var
x
en una clase / objeto, Scala crea los métodosx
yx_=
para ti. Puede definirlos usted mismo, pero si definey_=
debe definiry
o no se compilará, por ejemplo,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
correspondea.unary_-
Dela.unary_-
modo para+a
,~a
y!a
a <operator>= b
, donde<operator>
es un conjunto de caracteres especiales, es equivalente aa = a <operator> b
solo sia
no tiene el método<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
Además de la respuesta de Jaxkson:
-
type F[A,B]
se puede utilizar comoAFB
.
Por ejemplo:
type ->[A,B] = (A,B)
def foo(f: String -> String)
- Usar
=> type
en una definición de método hace que el compilador ajuste las expresiones dentro de la llamada al método en un thunk de función.
Por ejemplo
def until(cond: => Boolean)(body: => Unit) = while(!cond) body
var a = 0
until (a > 5) {a += 1}
El contexto limita el azúcar en implicit
parámetros implicit
, por ejemplo, considera una función que aprovecha la clase de tipo Monoid
:
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 vinculado, 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
...
}
Funciones anónimas:
_ + _
es la abreviatura de (a, b) => a + b