Scala 中的所有语法糖实例是什么?
它们很难搜索,因为它们中的大多数/全部都是纯粹的符号,因此在不知道概念名称的情况下很难搜索。
去做:
- 隐式转换
_
匿名函数的语法- 其他我忘记的事情
Scala 中的所有语法糖实例是什么?
它们很难搜索,因为它们中的大多数/全部都是纯粹的符号,因此在不知道概念名称的情况下很难搜索。
去做:
_
匿名函数的语法a b
相当于a.b
。a b c
等价于a.b(c)
,除非b
以 结尾:
。在这种情况下,a b c
相当于c.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
Function1
Function2
a(b) = c
相当于a.update(b,c)
。同样,a(b,c) = d
等价于a.update(b,c,d)
等。
a.b = c
相当于a.b_=(c)
。当您在类/对象中创建 / 时,Scala 会val
为您创建方法。你可以自己定义这些,但是如果你定义了你必须定义否则它不会编译,例如:var
x
x
x_=
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
, where <operator>
is some set of special characters,相当于a = a <operator> b
only if a
doesn't have the <operator>=
method,例如:
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
正如Rahul G所提到的,元组和符号有一种稍微特殊的语法。
'x
的缩写Symbol("x")
(p1,p2,..,pn)
是案例类的缩写Tuplen[T1,T2,..,Tn](p1,p2,..,pn)
例如,以下两个是等价的。
val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
除了 Jaxkson 的回答:
type F[A,B]
可以用作A F B
。例如:
type ->[A,B] = (A,B)
def foo(f: String -> String)
=> type
会使编译器将表达式包装在函数 thunk 中的方法调用中。例如
def until(cond: => Boolean)(body: => Unit) = while(!cond) body
var a = 0
until (a > 5) {a += 1}
提取器有两种方法,unapply
和unapplySeq
。这些用于多个变量分配和模式匹配。
第一个用例是 unapply 获取它应该匹配的对象并Boolean
根据它是否匹配返回 a ,例如,
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,...)]
多个参数的 a,即具有匹配值的元组,例如,从上面的代码继续:
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))
匿名函数:
_ + _
简称(a, b) => a + b
上下文将 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
...
}